Ignore:
Timestamp:
09/12/11 12:07:41 (13 years ago)
Author:
Takeshi Nakazato
Message:

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: MSFillerUtils and MSWriterUtils added

Test Programs: sd regressions, test_sdsave

Put in Release Notes: No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Rewrote MSFiller and MSWriter based on TableTraverse?.
TableTraverse? is changed a bit since it doesn't work on plain table.


File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/MSFiller.cpp

    r2289 r2291  
     1
    12//
    23// C++ Interface: MSFiller
     
    45// Description:
    56//
    6 // This class is specific filler for MS format
     7// This class is specific filler for MS format
     8// New version that is implemented using TableVisitor instead of TableIterator
    79//
    8 // Takeshi Nakazato <takeshi.nakazato@nao.ac.jp>, (C) 2010
     10// Takeshi Nakazato <takeshi.nakazato@nao.ac.jp>, (C) 2011
    911//
    1012// Copyright: See COPYING file that comes with this distribution
     
    1214//
    1315
     16#include <assert.h>
    1417#include <iostream>
    1518#include <map>
     
    5154#include "STHeader.h"
    5255
    53 // #include <ctime>
    54 // #include <sys/time.h>
    55 
    5656#include "MathUtils.h"
    5757
     
    6060
    6161namespace asap {
    62 // double MSFiller::gettimeofday_sec()
    63 // {
    64 //   struct timeval tv ;
    65 //   gettimeofday( &tv, NULL ) ;
    66 //   return tv.tv_sec + (double)tv.tv_usec*1.0e-6 ;
    67 // }
     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    sctab = hdr.asTable( "SYSCAL" ) ;
     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    srctab = hdr.asTable( "SOURCE" ) ;
     290
     291    // attach to columns
     292    // MS MAIN
     293    intervalCol.attach( table, "INTERVAL" ) ;
     294    flagRowCol.attach( table, "FLAG_ROW" ) ;
     295    flagCol.attach( table, "FLAG" ) ;
     296    if ( dataColumnName.compare( "DATA" ) == 0 )
     297      dataCol.attach( table, dataColumnName ) ;
     298    else
     299      floatDataCol.attach( table, dataColumnName ) ;
     300
     301    // set dummy epoch
     302    mf.set( currentTime ) ;
     303
     304    // initialize dirType
     305    dirType = MDirection::N_Types ;
     306
     307    //
     308    // add rows to scantable
     309    //
     310    // number of polarization is up to 4
     311    uInt addrow = table.nrow() * maxNumPol() ;
     312    scantable.table().addRow( addrow ) ;
     313
     314    // attach to columns
     315    // Scantable MAIN
     316    TableRecord &r = tablerow.record() ;
     317    timeRF.attachToRecord( r, "TIME" ) ;
     318    intervalRF.attachToRecord( r, "INTERVAL" ) ;
     319    directionRF.attachToRecord( r, "DIRECTION" ) ;
     320    azimuthRF.attachToRecord( r, "AZIMUTH" ) ;
     321    elevationRF.attachToRecord( r, "ELEVATION" ) ;
     322    scanRateRF.attachToRecord( r, "SCANRATE" ) ;
     323    weatherIdRF.attachToRecord( r, "WEATHER_ID" ) ;
     324    cycleNoRF.attachToRecord( r, "CYCLENO" ) ;
     325    flagRowRF.attachToRecord( r, "FLAGROW" ) ;
     326    polNoRF.attachToRecord( r, "POLNO" ) ;
     327    tcalIdRF.attachToRecord( r, "TCAL_ID" ) ;
     328    spectraRF.attachToRecord( r, "SPECTRA" ) ;
     329    flagtraRF.attachToRecord( r, "FLAGTRA" ) ;
     330    tsysRF.attachToRecord( r, "TSYS" ) ;
     331    beamNoRF.attachToRecord( r, "BEAMNO" ) ;
     332    ifNoRF.attachToRecord( r, "IFNO" ) ;
     333    freqIdRF.attachToRecord( r, "FREQ_ID" ) ;
     334    moleculeIdRF.attachToRecord( r, "MOLECULE_ID" ) ;
     335    sourceNameRF.attachToRecord( r, "SRCNAME" ) ;
     336    sourceProperMotionRF.attachToRecord( r, "SRCPROPERMOTION" ) ;
     337    sourceDirectionRF.attachToRecord( r, "SRCDIRECTION" ) ;
     338    sourceVelocityRF.attachToRecord( r, "SRCVELOCITY" ) ;
     339    focusIdRF.attachToRecord( r, "FOCUS_ID" ) ;
     340    fieldNameRF.attachToRecord( r, "FIELDNAME" ) ;
     341    sourceTypeRF.attachToRecord( r, "SRCTYPE" ) ;
     342    scanNoRF.attachToRecord( r, "SCANNO" ) ;
     343
     344    // put values
     345    RecordFieldPtr<Int> refBeamNoRF( r, "REFBEAMNO" ) ;
     346    *refBeamNoRF = -1 ;
     347    RecordFieldPtr<Int> fitIdRF( r, "FIT_ID" ) ;
     348    *fitIdRF = -1 ;
     349    RecordFieldPtr<Float> opacityRF( r, "OPACITY" ) ;
     350    *opacityRF = 0.0 ;
     351  }
     352
     353  virtual void enterObservationId(const uInt recordNo, Int columnValue) {
     354    //printf("%u: ObservationId: %d\n", recordNo, columnValue);
     355    // update header
     356    if ( header.observer.empty() )
     357      getScalar( String("OBSERVER"), (uInt)columnValue, obstab, header.observer ) ;
     358    if ( header.project.empty() )
     359      getScalar( "PROJECT", (uInt)columnValue, obstab, header.project ) ;
     360    if ( header.utc == 0.0 ) {
     361      Vector<MEpoch> amp ;
     362      getArrayMeas( "TIME_RANGE", (uInt)columnValue, obstab, amp ) ;
     363      header.utc = amp[0].get( "d" ).getValue() ;
     364    }
     365    if ( header.antennaname.empty() )
     366      getScalar( "TELESCOPE_NAME", (uInt)columnValue, obstab, header.antennaname ) ;
     367  }
     368  virtual void leaveObservationId(const uInt recordNo, Int columnValue) {
     369    // update header
     370    header.nbeam = max( header.nbeam, (Int)nbeam ) ;
     371
     372    nbeam = 0 ;
     373    feedEntry = -1 ;
     374  }
     375  virtual void enterFeedId(const uInt recordNo, Int columnValue) {
     376    //printf("%u: FeedId: %d\n", recordNo, columnValue);
     377
     378    // update feed entry
     379    if ( allNE( feedEntry, columnValue ) ) {
     380      feedEntry[nbeam] = columnValue ;
     381      nbeam++ ;
     382    }
     383
     384    // put values
     385    *beamNoRF = (uInt)columnValue ;
     386    *focusIdRF = (uInt)0 ;
     387  }
     388  virtual void leaveFeedId(const uInt recordNo, Int columnValue) {
     389    Int nelem = (Int)feedEntry.nelements() ;
     390    if ( nbeam > nelem ) {
     391      feedEntry.resize( nelem+64, True ) ;
     392      Slicer slice( IPosition( 1, nelem ), IPosition( 1, feedEntry.nelements()-1 ) ) ;
     393      feedEntry( slice ) = -1 ;
     394    }
     395  }
     396  virtual void enterFieldId(const uInt recordNo, Int columnValue) {
     397    //printf("%u: FieldId: %d\n", recordNo, columnValue);
     398    // update sourceId and fieldName
     399    getScalar( "SOURCE_ID", (uInt)columnValue, fieldtab, sourceId ) ;
     400    String fieldName ;
     401    getScalar( "NAME", (uInt)columnValue, fieldtab, fieldName ) ;
     402    fieldName += "__" + String::toString( columnValue ) ;
     403
     404    // put values
     405    *fieldNameRF = fieldName ;
     406  }
     407  virtual void leaveFieldId(const uInt recordNo, Int columnValue) {
     408    sourceId = -1 ;
     409  }
     410  virtual void enterDataDescId(const uInt recordNo, Int columnValue) {
     411    //printf("%u: DataDescId: %d\n", recordNo, columnValue);
     412    // update polarization and spectral window ids
     413    getScalar( "POLARIZATION_ID", (uInt)columnValue, ddtab, polId ) ;
     414    getScalar( "SPECTRAL_WINDOW_ID", (uInt)columnValue, ddtab, spwId ) ;
     415
     416    // polarization setup
     417    getScalar( "NUM_CORR", (uInt)polId, poltab, npol ) ;
     418    Vector<Int> corrtype ;
     419    getArray( "CORR_TYPE", (uInt)polId, poltab, corrtype ) ;
     420    polnos = getPolNos( corrtype ) ;
     421   
     422    // process SOURCE table
     423    String sourceName ;
     424    Vector<Double> sourcePM, restFreqs, sysVels ;
     425    Vector<String> transition ;
     426    processSource( sourceId, spwId, sourceName, sourceDir, sourcePM,
     427                   restFreqs, transition, sysVels ) ;
     428
     429    // spectral setup
     430    uInt freqId ;
     431    Double reffreq, bandwidth ;
     432    String freqref ;
     433    getScalar( "NUM_CHAN", (uInt)spwId, spwtab, nchan ) ;
     434    Bool iswvr = (Bool)(nchan == 4) ;
     435    map<Int,uInt>::iterator iter = ifmap.find( spwId ) ;
     436    if ( iter == ifmap.end() ) {
     437      MEpoch me ;
     438      getScalarMeas( "TIME", recordNo, table, me ) ;
     439      spectralSetup( spwId, me, antpos, sourceDir,
     440                     freqId, nchan,
     441                     freqref, reffreq, bandwidth ) ;
     442      ifmap.insert( pair<Int,uInt>(spwId,freqId) ) ;
     443    }
     444    else {
     445      freqId = iter->second ;
     446    }
     447    sp.resize( npol, nchan ) ;
     448    fl.resize( npol, nchan ) ;
     449
     450
     451    // molecular setup
     452    STMolecules mtab = scantable.molecules() ;
     453    uInt molId = mtab.addEntry( restFreqs, transition, transition ) ;
     454
     455    // process SYSCAL table
     456    if ( isSysCal )
     457      processSysCal( spwId ) ;
     458
     459    // update header
     460    if ( !iswvr ) {
     461      header.nchan = max( header.nchan, nchan ) ;
     462      header.bandwidth = max( header.bandwidth, bandwidth ) ;
     463      if ( header.reffreq == -1.0 )
     464        header.reffreq = reffreq ;
     465      header.npol = max( header.npol, npol ) ;
     466      if ( header.poltype.empty() )
     467        header.poltype = getPolType( corrtype[0] ) ;
     468      if ( header.freqref.empty() )
     469        header.freqref = freqref ;
     470    }
     471   
     472    // put values
     473    *ifNoRF = (uInt)spwId ;
     474    *freqIdRF = freqId ;
     475    *moleculeIdRF = molId ;
     476    *sourceNameRF = sourceName ;
     477    sourceProperMotionRF.define( sourcePM ) ;
     478    Vector<Double> srcD = sourceDir.getAngle().getValue( "rad" ) ;
     479    sourceDirectionRF.define( srcD ) ;
     480    if ( !sysVels.empty() )
     481      *sourceVelocityRF = sysVels[0] ;
     482    else {
     483      *sourceVelocityRF = (Double)0.0 ;
     484    }
     485  }
     486  virtual void leaveDataDescId(const uInt recordNo, Int columnValue) {
     487    npol = 0 ;
     488    nchan = 0 ;
     489    numSysCalRow = 0 ;
     490  }
     491  virtual void enterScanNo(const uInt recordNo, Int columnValue) {
     492    //printf("%u: ScanNo: %d\n", recordNo, columnValue);
     493    // put value
     494    // scan number is 1-based in MS while 0-based in Scantable
     495    *scanNoRF = (uInt)columnValue - 1 ;
     496  }
     497  virtual void leaveScanNo(const uInt recordNo, Int columnValue) {
     498    cycleNo = 0 ;
     499  }
     500  virtual void enterStateId(const uInt recordNo, Int columnValue) {
     501    //printf("%u: StateId: %d\n", recordNo, columnValue);
     502    // SRCTYPE
     503    Int srcType = getSrcType( columnValue ) ;
     504   
     505    // update header
     506    if ( header.obstype.empty() )
     507      getScalar( "OBS_MODE", (uInt)columnValue, statetab, header.obstype ) ;
     508
     509    // put value
     510    *sourceTypeRF = srcType ;
     511  }
     512  virtual void leaveStateId(const uInt recordNo, Int columnValue) { }
     513  virtual void enterTime(const uInt recordNo, Double columnValue) {
     514    //printf("%u: Time: %f\n", recordNo, columnValue);
     515    currentTime = MEpoch( Quantity( columnValue, "s" ), MEpoch::UTC ) ;
     516
     517    // DIRECTION, AZEL, and SCANRATE
     518    Vector<Double> direction, azel ;
     519    Vector<Double> scanrate( 2, 0.0 ) ;
     520    if ( getpt )
     521      getDirection( direction, azel, scanrate ) ;
     522    else
     523      getSourceDirection( direction, azel, scanrate ) ;
     524
     525    // INTERVAL
     526    Double interval = intervalCol.asdouble( recordNo ) ;
     527
     528    // WEATHER_ID
     529    uInt wid = 0 ;
     530    if ( isWeather )
     531      wid = getWeatherId() ;
     532
     533    // put value
     534    Double t = currentTime.get( "d" ).getValue() ;
     535    *timeRF = t ;
     536    *intervalRF = interval ;
     537    directionRF.define( direction ) ;
     538    *azimuthRF = (Float)azel[0] ;
     539    *elevationRF = (Float)azel[1] ;
     540    scanRateRF.define( scanrate ) ;
     541    *weatherIdRF = wid ;
     542  }
     543  virtual void leaveTime(const uInt recordNo, Double columnValue) { }
     544  virtual Bool visitRecord(const uInt recordNo,
     545                           const Int observationId,
     546                           const Int feedId,
     547                           const Int fieldId,
     548                           const Int dataDescId,
     549                           const Int scanNo,
     550                           const Int stateId,
     551                           const Double time)
     552  {
     553    //printf("%u: %d, %d, %d, %d, %d, %d, %f\n", recordNo,
     554    //observationId, feedId, fieldId, dataDescId, scanNo, stateId, time);
     555
     556    // SPECTRA and FLAGTRA
     557    //Matrix<Float> sp;
     558    //Matrix<uChar> fl;
     559    spectraAndFlagtra( recordNo, sp, fl ) ;
     560
     561    // FLAGROW
     562    Bool flr = flagRowCol.asBool( recordNo ) ;
     563
     564    // TSYS
     565    Matrix<Float> tsys ;
     566    uInt scIdx = getSysCalIndex() ;
     567    if ( numSysCalRow > 0 ) {
     568      tsys = sysCalTsysCol( syscalRow[scIdx] ) ;
     569    }
     570    else {
     571      tsys.resize( npol, 1 ) ;
     572      tsys = 1.0 ;
     573    }
     574
     575    // TCAL_ID
     576    Block<uInt> tcalids( npol, 0 ) ;
     577    if ( numSysCalRow > 0 ) {
     578      tcalids = getTcalId( syscalTime[scIdx] ) ;
     579    }
     580
     581    // put value
     582    *cycleNoRF = cycleNo ;
     583    *flagRowRF = (uInt)flr ;
     584
     585    // for each polarization component
     586    for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
     587      // put value depending on polarization component
     588      *polNoRF = polnos[ipol] ;
     589      *tcalIdRF = tcalids[ipol] ;
     590      spectraRF.define( sp.row( ipol ) ) ;
     591      flagtraRF.define( fl.row( ipol ) ) ;
     592      tsysRF.define( tsys.row( ipol ) ) ;
     593     
     594      // commit row
     595      tablerow.put( rowidx ) ;
     596      rowidx++ ;
     597    }
     598
     599    // increment CYCLENO
     600    cycleNo++ ;
     601
     602    return True ;
     603  }
     604  virtual void finish()
     605  {
     606    BaseMSFillerVisitor::finish();
     607    //printf("Total: %u\n", count);
     608    // remove redundant rows
     609    //cout << "filled " << rowidx << " rows out of " << scantable.nrow() << " rows" << endl ;
     610    if ( scantable.nrow() > rowidx ) {
     611      uInt numRemove = scantable.nrow() - rowidx ;
     612      //cout << "numRemove = " << numRemove << endl ;
     613      Vector<uInt> rows( numRemove ) ;
     614      indgen( rows, rowidx ) ;
     615      scantable.table().removeRow( rows ) ;
     616    }
     617   
     618    // antenna name and station name
     619    String antennaName ;
     620    getScalar( "NAME", (uInt)antennaId, anttab, antennaName ) ;
     621    String stationName ;
     622    getScalar( "STATION", (uInt)antennaId, anttab, stationName ) ;
     623
     624    // update header
     625    header.nif = ifmap.size() ;
     626    header.antennaposition = antpos.get( "m" ).getValue() ;
     627    if ( header.antennaname.empty() || header.antennaname == antennaName )
     628      header.antennaname = antennaName ;
     629    else
     630      header.antennaname += "//" + antennaName ;
     631    if ( !stationName.empty() && stationName != antennaName )
     632      header.antennaname += "@" + stationName ;
     633    if ( header.fluxunit.empty() || header.fluxunit == "CNTS" )
     634      header.fluxunit = "K" ;
     635    header.epoch = "UTC" ;
     636    header.equinox = 2000.0 ;
     637    if (header.freqref == "TOPO") {
     638      header.freqref = "TOPOCENT";
     639    } else if (header.freqref == "GEO") {
     640      header.freqref = "GEOCENTR";
     641    } else if (header.freqref == "BARY") {
     642      header.freqref = "BARYCENT";
     643    } else if (header.freqref == "GALACTO") {
     644      header.freqref = "GALACTOC";
     645    } else if (header.freqref == "LGROUP") {
     646      header.freqref = "LOCALGRP";
     647    } else if (header.freqref == "CMB") {
     648      header.freqref = "CMBDIPOL";
     649    } else if (header.freqref == "REST") {
     650      header.freqref = "SOURCE";
     651    }
     652    scantable.setHeader( header ) ;
     653  }
     654  void setAntenna( Int id )
     655  {
     656    antennaId = id ;
     657
     658    Vector< Quantum<Double> > pos ;
     659    getArrayQuant( "POSITION", (uInt)antennaId, anttab, pos ) ;
     660    antpos = MPosition( MVPosition( pos ), MPosition::ITRF ) ;
     661    mf.set( antpos ) ;
     662  }
     663  void setPointingTable( const Table &tab, String columnToUse="DIRECTION" )
     664  {
     665    // input POINTING table must be
     666    //  1) selected by antenna
     667    //  2) sorted by TIME
     668    ROScalarColumn<Double> tcol( tab, "TIME" ) ;
     669    ROArrayColumn<Double> dcol( tab, columnToUse ) ;
     670    tcol.getColumn( pointingTime ) ;
     671    dcol.getColumn( pointingDirection ) ;
     672    const TableRecord &rec = dcol.keywordSet() ;
     673    String pointingRef = rec.asRecord( "MEASINFO" ).asString( "Ref" ) ;
     674    MDirection::getType( dirType, pointingRef ) ;
     675    getpt = True ;
     676  }
     677  void setWeatherTime( const Vector<Double> &t, const Vector<Double> &it )
     678  {
     679    isWeather = True ;
     680    weatherTime = t ;
     681    weatherInterval = it ;
     682  }
     683  void setSysCalRecord( const Record &r )
     684  //void setSysCalRecord( const map< String,Vector<uInt> > &r )
     685  {
     686    isSysCal = True ;
     687    syscalRecord = r ;
     688
     689    const TableDesc &desc = sctab.tableDesc() ;
     690    uInt nrow = sctab.nrow() ;
     691    syscalRow.resize( nrow ) ;
     692    syscalTime.resize( nrow ) ;
     693    syscalInterval.resize( nrow ) ;
     694    String tsysCol = "NONE" ;
     695    Vector<String> tsysCols = stringToVector( "TSYS_SPECTRUM,TSYS" ) ;
     696    for ( uInt i = 0 ; i < tsysCols.nelements() ; i++ ) {
     697      if ( tsysCol == "NONE" && desc.isColumn( tsysCols[i] ) )
     698        tsysCol = tsysCols[i] ;
     699    }
     700    sysCalTsysCol.attach( sctab, tsysCol ) ;
     701  }
     702  STHeader getHeader() { return header ; }
     703  uInt getNumBeam() { return nbeam ; }
     704  uInt getFilledRowNum() { return rowidx ; }
     705private:
     706  void fluxUnit( String &u )
     707  {
     708    ROTableColumn col( table, dataColumnName ) ;
     709    const TableRecord &rec = col.keywordSet() ;
     710    if ( rec.isDefined( "UNIT" ) )
     711      u = rec.asString( "UNIT" ) ;
     712    else if ( rec.isDefined( "QuantumUnits" ) )
     713      u = rec.asString( "QuantumUnits" ) ;
     714    if ( u.empty() )
     715      u = "K" ;
     716  }
     717  void processSource( Int sourceId, Int spwId,
     718                      String &name, MDirection &dir, Vector<Double> &pm,
     719                      Vector<Double> &rf, Vector<String> &trans, Vector<Double> &vel )
     720  {
     721    // find row
     722    uInt nrow = srctab.nrow() ;
     723    Int idx = -1 ;
     724    ROTableRow row( srctab ) ;
     725    for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
     726      const TableRecord &r = row.get( irow ) ;
     727      if ( r.asInt( "SOURCE_ID" ) == sourceId ) {
     728        Int tmpSpwId = r.asInt( "SPECTRAL_WINDOW_ID" ) ;
     729        if ( tmpSpwId == spwId || tmpSpwId == -1 ) {
     730          idx = (Int)irow ;
     731          break ;
     732        }
     733      }
     734    }
     735
     736    // fill
     737    Int numLines = 0 ;
     738    if ( idx != -1 ) {
     739      const TableRecord &r = row.get( idx ) ;
     740      name = r.asString( "NAME" ) ;
     741      getScalarMeas( "DIRECTION", idx, srctab, dir ) ;
     742      pm = r.toArrayDouble( "PROPER_MOTION" ) ;
     743      numLines = r.asInt( "NUM_LINES" ) ;
     744    }
     745    else {
     746      name = "" ;
     747      pm = Vector<Double>( 2, 0.0 ) ;
     748      dir = MDirection( Quantum<Double>(0.0,Unit("rad")), Quantum<Double>(0.0,Unit("rad")) ) ;
     749    }
     750    if ( !getpt ) {
     751      String ref = dir.getRefString() ;
     752      MDirection::getType( dirType, ref ) ;
     753    }
     754
     755    rf.resize( numLines ) ;
     756    trans.resize( numLines ) ;
     757    vel.resize( numLines ) ;
     758    if ( numLines > 0 ) {
     759      Block<Bool> isDefined = row.getDefined() ;
     760      Vector<String> colNames = row.columnNames() ;
     761      Vector<Int> indexes( 3, -1 ) ;
     762      Vector<String> cols = stringToVector( "REST_FREQUENCY,TRANSITION,SYSVEL" ) ;
     763      for ( uInt icol = 0 ; icol < colNames.nelements() ; icol++ ) {
     764        if ( anyEQ( indexes, -1 ) ) {
     765          for ( uInt jcol = 0 ; jcol < cols.nelements() ; jcol++ ) {
     766            if ( colNames[icol] == cols[jcol] )
     767              indexes[jcol] = icol ;
     768          }
     769        }
     770      }
     771      if ( indexes[0] != -1 && isDefined[indexes[0]] == True ) {
     772        Vector< Quantum<Double> > qrf ;
     773        getArrayQuant( "REST_FREQUENCY", idx, srctab, qrf ) ;
     774        for ( int i = 0 ; i < numLines ; i++ )
     775          rf[i] = qrf[i].getValue( "Hz" ) ;
     776      }
     777      if ( indexes[1] != -1 && isDefined[indexes[1]] == True ) {
     778        getArray( "TRANSITION", idx, srctab, trans ) ;
     779      }
     780      if ( indexes[2] != -1 && isDefined[indexes[2]] == True ) {
     781        Vector< Quantum<Double> > qsv ;
     782        getArrayQuant( "SYSVEL", idx, srctab, qsv ) ;
     783        for ( int i = 0 ; i < numLines ; i++ )
     784          vel[i] = qsv[i].getValue( "m/s" ) ;
     785      }
     786    }
     787  }
     788  void spectralSetup( Int &spwId, MEpoch &me, MPosition &mp, MDirection &md,
     789                      uInt &freqId, Int &nchan,
     790                      String &freqref, Double &reffreq, Double &bandwidth )
     791  {
     792    // fill
     793    Int measFreqRef ;
     794    getScalar( "MEAS_FREQ_REF", spwId, spwtab, measFreqRef ) ;
     795    MFrequency::Types freqRef = MFrequency::castType( measFreqRef ) ;
     796    //freqref = MFrequency::showType( freqRef ) ;
     797    freqref = "LSRK" ;
     798    Quantum<Double> q ;
     799    getScalarQuant( "TOTAL_BANDWIDTH", spwId, spwtab, q ) ;
     800    bandwidth = q.getValue( "Hz" ) ;
     801    getScalarQuant( "REF_FREQUENCY", spwId, spwtab, q ) ;
     802    reffreq = q.getValue( "Hz" ) ;
     803    Double refpix = 0.5 * ( (Double)nchan-1.0 ) ;
     804    Int refchan = ( nchan - 1 ) / 2 ;
     805    Bool even = (Bool)( nchan % 2 == 0 ) ;
     806    Vector< Quantum<Double> > qa ;
     807    getArrayQuant( "CHAN_WIDTH", spwId, spwtab, qa ) ;
     808    Double increment = qa[refchan].getValue( "Hz" ) ;
     809    getArrayQuant( "CHAN_FREQ", spwId, spwtab, qa ) ;
     810    if ( nchan == 1 ) {
     811      Int netSideband ;
     812      getScalar( "NET_SIDEBAND", spwId, spwtab, netSideband ) ;
     813      if ( netSideband == 1 ) increment *= -1.0 ;
     814    }
     815    else {
     816      if ( qa[0].getValue( "Hz" ) > qa[1].getValue( "Hz" ) )
     817        increment *= -1.0 ;
     818    }
     819    Double refval = qa[refchan].getValue( "Hz" ) ;
     820    if ( even )
     821      refval = 0.5 * ( refval + qa[refchan+1].getValue( "Hz" ) ) ;
     822    if ( freqRef != MFrequency::LSRK ) {
     823      MeasFrame mframe( me, mp, md ) ;
     824      MFrequency::Convert tolsr( freqRef, MFrequency::Ref( MFrequency::LSRK, mframe ) ) ;
     825      refval = tolsr( Quantum<Double>( refval, "Hz" ) ).get( "Hz" ).getValue() ;
     826    }
     827   
     828    // add new row to FREQUENCIES
     829    Table ftab = scantable.frequencies().table() ;
     830    freqId = ftab.nrow() ;
     831    ftab.addRow() ;
     832    TableRow row( ftab ) ;
     833    TableRecord &r = row.record() ;
     834    RecordFieldPtr<uInt> idRF( r, "ID" ) ;
     835    *idRF = freqId ;
     836    RecordFieldPtr<Double> refpixRF( r, "REFPIX" ) ;
     837    RecordFieldPtr<Double> refvalRF( r, "REFVAL" ) ;
     838    RecordFieldPtr<Double> incrRF( r, "INCREMENT" ) ;
     839    *refpixRF = refpix ;
     840    *refvalRF = refval ;
     841    *incrRF = increment ;
     842    row.put( freqId ) ;
     843  }
     844  void spectraAndFlagtra( uInt recordNo, Matrix<Float> &sp, Matrix<uChar> &fl )
     845  {
     846    Matrix<Bool> b = flagCol( recordNo ) ;
     847    if ( dataColumnName.compare( "FLOAT_DATA" ) == 0 ) {
     848      sp = floatDataCol( recordNo ) ;
     849      convertArray( fl, b ) ;
     850    }
     851    else {
     852      Bool notyet = True ;
     853      Matrix<Complex> c = dataCol( recordNo ) ;
     854      for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
     855        if ( ( header.poltype == "linear" || header.poltype == "circular" )
     856             && ( polnos[ipol] == 2 || polnos[ipol] == 3 ) ) {
     857          if ( notyet ) {
     858            Vector<Float> tmp = ComplexToReal( c.row( ipol ) ) ;
     859            IPosition start( 1, 0 ) ;
     860            IPosition end( 1, 2*nchan-1 ) ;
     861            IPosition inc( 1, 2 ) ;
     862            if ( polnos[ipol] == 2 ) {
     863              sp.row( ipol ) = tmp( start, end, inc ) ;
     864              Vector<Bool> br = b.row( ipol ) ;
     865              Vector<uChar> flr = fl.row( ipol ) ;
     866              convertArray( flr, br ) ;
     867              start = IPosition( 1, 1 ) ;
     868              Int jpol = ipol+1 ;
     869              while( polnos[jpol] != 3 && jpol < npol )
     870                jpol++ ;
     871              sp.row( jpol ) = tmp( start, end, inc ) ;
     872              flr.reference( fl.row( jpol ) ) ;
     873              convertArray( flr, br ) ;
     874            }
     875            else if ( polnos[ipol] == 3 ) {
     876              sp.row( ipol ) = sp.row( ipol ) * (Float)(-1.0) ;
     877              Int jpol = ipol+1 ;
     878              while( polnos[jpol] != 2 && jpol < npol )
     879                jpol++ ;
     880              Vector<Bool> br = b.row( ipol ) ;
     881              Vector<uChar> flr = fl.row( jpol ) ;
     882              sp.row( jpol ) = tmp( start, end, inc ) ;
     883              convertArray( flr, br ) ;
     884              start = IPosition( 1, 1 ) ;
     885              sp.row( ipol ) = tmp( start, end, inc ) * (Float)(-1.0) ;
     886              flr.reference( fl.row( ipol ) ) ;
     887              convertArray( flr, br ) ;
     888            }
     889            notyet = False ;
     890          }
     891        }
     892        else {
     893          Vector<Float> tmp = ComplexToReal( c.row( ipol ) ) ;
     894          IPosition start( 1, 0 ) ;
     895          IPosition end( 1, 2*nchan-1 ) ;
     896          IPosition inc( 1, 2 ) ;
     897          sp.row( ipol ) = tmp( start, end, inc ) ;
     898          Vector<Bool> br = b.row( ipol ) ;
     899          Vector<uChar> flr = fl.row( ipol ) ;
     900          convertArray( flr, br ) ;
     901        }
     902      }
     903    }
     904  }
     905  uInt binarySearch( Vector<Double> &timeList, Double target )
     906  {
     907    Int low = 0 ;
     908    Int high = timeList.nelements() ;
     909    uInt idx = 0 ;
     910   
     911    while ( low <= high ) {
     912      idx = (Int)( 0.5 * ( low + high ) ) ;
     913      Double t = timeList[idx] ;
     914      if ( t < target )
     915        low = idx + 1 ;
     916      else if ( t > target )
     917        high = idx - 1 ;
     918      else {
     919        return idx ;
     920      }
     921    }
     922   
     923    idx = max( 0, min( low, high ) ) ;
     924    return idx ;
     925  }
     926  void getDirection( Vector<Double> &dir, Vector<Double> &azel, Vector<Double> &srate )
     927  {
     928    // @todo At the moment, do binary search every time
     929    //       if this is bottleneck, frequency of binary search must be reduced
     930    Double t = currentTime.get( "s" ).getValue() ;
     931    uInt idx = min( binarySearch( pointingTime, t ), pointingTime.nelements()-1 ) ;
     932    Matrix<Double> d ;
     933    if ( pointingTime[idx] == t )
     934      d = pointingDirection.xyPlane( idx ) ;
     935    else if ( pointingTime[idx] < t ) {
     936      if ( idx == pointingTime.nelements()-1 )
     937        d = pointingDirection.xyPlane( idx ) ;
     938      else
     939        d = interp( pointingTime[idx], pointingTime[idx+1], t,
     940                    pointingDirection.xyPlane( idx ), pointingDirection.xyPlane( idx+1 ) ) ;
     941    }
     942    else {
     943      if ( idx == 0 )
     944        d = pointingDirection.xyPlane( idx ) ;
     945      else
     946        d = interp( pointingTime[idx-1], pointingTime[idx], t,
     947                    pointingDirection.xyPlane( idx-1 ), pointingDirection.xyPlane( idx ) ) ;
     948    }
     949    mf.resetEpoch( currentTime ) ;
     950    Quantum< Vector<Double> > tmp( d.column( 0 ), Unit( "rad" ) ) ;
     951    if ( dirType != MDirection::J2000 ) {
     952      MDirection::Convert toj2000( dirType, MDirection::Ref( MDirection::J2000, mf ) ) ;
     953      dir = toj2000( tmp ).getAngle( "rad" ).getValue() ;
     954    }
     955    else {
     956      dir = d.column( 0 ) ;
     957    }
     958    if ( dirType != MDirection::AZELGEO ) {
     959      MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZELGEO, mf ) ) ;
     960      //MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZEL, mf ) ) ;
     961      azel = toazel( tmp ).getAngle( "rad" ).getValue() ;
     962    }
     963    else {
     964      azel = d.column( 0 ) ;
     965    }
     966    if ( d.ncolumn() > 1 )
     967      srate = d.column( 1 ) ;
     968  }
     969  void getSourceDirection( Vector<Double> &dir, Vector<Double> &azel, Vector<Double> &srate )
     970  {
     971    dir = sourceDir.getAngle( "rad" ).getValue() ;
     972    mf.resetEpoch( currentTime ) ;
     973    MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZELGEO, mf ) ) ;
     974    azel = toazel( Quantum< Vector<Double> >( dir, Unit("rad") ) ).getAngle( "rad" ).getValue() ;
     975    if ( dirType != MDirection::J2000 ) {
     976      MDirection::Convert toj2000( dirType, MDirection::Ref( MDirection::J2000, mf ) ) ;
     977      dir = toj2000( Quantum< Vector<Double> >( dir, Unit("rad") ) ).getAngle( "rad" ).getValue() ;
     978    }
     979  }
     980  String detectSeparator( String &s )
     981  {
     982    String tmp = s.substr( 0, s.find_first_of( "," ) ) ;
     983    Char *separators[] = { ":", "#", ".", "_" } ;
     984    uInt nsep = 4 ;
     985    for ( uInt i = 0 ; i < nsep ; i++ ) {
     986      if ( tmp.find( separators[i] ) != String::npos )
     987        return separators[i] ;
     988    }
     989    return "" ;
     990  }
     991  Int getSrcType( Int stateId )
     992  {
     993    // get values
     994    Bool sig ;
     995    getScalar( "SIG", stateId, statetab, sig ) ;
     996    Bool ref ;
     997    getScalar( "REF", stateId, statetab, ref ) ;
     998    Double cal ;
     999    getScalar( "CAL", stateId, statetab, cal ) ;
     1000    String obsmode ;
     1001    getScalar( "OBS_MODE", stateId, statetab, obsmode ) ;
     1002    String sep = detectSeparator( obsmode ) ;
     1003   
     1004    Int srcType = SrcType::NOTYPE ;
     1005    if ( sep == ":" )
     1006      srcTypeGBT( srcType, sep, obsmode, sig, ref, cal ) ;
     1007    else if ( sep == "." || sep == "#" )
     1008      srcTypeALMA( srcType, sep, obsmode ) ;
     1009    else if ( sep == "_" )
     1010      srcTypeOldALMA( srcType, sep, obsmode, sig, ref ) ;
     1011    else
     1012      srcTypeDefault( srcType, sig, ref ) ;
     1013
     1014    return srcType ;
     1015  }
     1016  void srcTypeDefault( Int &st, Bool &sig, Bool &ref )
     1017  {
     1018    if ( sig ) st = SrcType::SIG ;
     1019    else if ( ref ) st = SrcType::REF ;
     1020  }
     1021  void srcTypeGBT( Int &st, String &sep, String &mode, Bool &sig, Bool &ref, Double &cal )
     1022  {
     1023    Int epos = mode.find_first_of( sep ) ;
     1024    Int nextpos = mode.find_first_of( sep, epos+1 ) ;
     1025    String m1 = mode.substr( 0, epos ) ;
     1026    String m2 = mode.substr( epos+1, nextpos-epos-1 ) ;
     1027    if ( m1 == "Nod" ) {
     1028      st = SrcType::NOD ;
     1029    }
     1030    else if ( m1 == "OffOn" ) {
     1031      if ( m2 == "PSWITCHON" ) st = SrcType::PSON ;
     1032      if ( m2 == "PSWITCHOFF" ) st = SrcType::PSOFF ;
     1033    }
     1034    else {
     1035      if ( m2 == "FSWITCH" ) {
     1036        if ( sig ) st = SrcType::FSON ;
     1037        else if ( ref ) st = SrcType::FSOFF ;
     1038      }
     1039    }
     1040    if ( cal > 0.0 ) {
     1041      if ( st == SrcType::NOD )
     1042        st = SrcType::NODCAL ;
     1043      else if ( st == SrcType::PSON )
     1044        st = SrcType::PONCAL ;
     1045      else if ( st == SrcType::PSOFF )
     1046        st = SrcType::POFFCAL ;
     1047      else if ( st == SrcType::FSON )
     1048        st = SrcType::FONCAL ;
     1049      else if ( st == SrcType::FSOFF )
     1050        st = SrcType::FOFFCAL ;
     1051      else
     1052        st = SrcType::CAL ;
     1053    }
     1054  }
     1055  void srcTypeALMA( Int &st, String &sep, String &mode )
     1056  {
     1057    Int epos = mode.find_first_of( "," ) ;
     1058    String first = mode.substr( 0, epos ) ;
     1059    epos = first.find_first_of( sep ) ;
     1060    Int nextpos = first.find_first_of( sep, epos+1 ) ;
     1061    String m1 = first.substr( 0, epos ) ;
     1062    String m2 = first.substr( epos+1, nextpos-epos-1 ) ;
     1063    if ( m1.find( "CALIBRATE_" ) == 0 ) {
     1064      if ( m2.find( "ON_SOURCE" ) == 0 )
     1065        st = SrcType::PONCAL ;
     1066      else if ( m2.find( "OFF_SOURCE" ) == 0 )
     1067        st = SrcType::POFFCAL ;
     1068    }
     1069    else if ( m1.find( "OBSERVE_TARGET" ) == 0 ) {
     1070      if ( m2.find( "ON_SOURCE" ) == 0 )
     1071        st = SrcType::PSON ;
     1072      else if ( m2.find( "OFF_SOURCE" ) == 0 )
     1073        st = SrcType::PSOFF ;
     1074    }
     1075  }
     1076  void srcTypeOldALMA( Int &st, String &sep, String &mode, Bool &sig, Bool &ref )
     1077  {
     1078    Int epos = mode.find_first_of( "," ) ;
     1079    String first = mode.substr( 0, epos ) ;
     1080    string substr[4] ;
     1081    int numSubstr = split( first, substr, 4, sep ) ;
     1082    String m1( substr[0] ) ;
     1083    String m2( substr[2] ) ;
     1084    if ( numSubstr == 4 ) {
     1085      if ( m1.find( "CALIBRATE" ) == 0 ) {
     1086        if ( m2.find( "ON" ) == 0 )
     1087          st = SrcType::PONCAL ;
     1088        else if ( m2.find( "OFF" ) == 0 )
     1089          st = SrcType::POFFCAL ;
     1090      }
     1091      else if ( m1.find( "OBSERVE" ) == 0 ) {
     1092        if ( m2.find( "ON" ) == 0 )
     1093          st = SrcType::PSON ;
     1094        else if ( m2.find( "OFF" ) == 0 )
     1095          st = SrcType::PSOFF ;
     1096      }
     1097    }
     1098    else {
     1099      if ( sig ) st = SrcType::SIG ;
     1100      else if ( ref ) st = SrcType::REF ;
     1101    }
     1102  }
     1103  Block<uInt> getPolNos( Vector<Int> &corr )
     1104  {
     1105    Block<uInt> polnos( npol ) ;
     1106    for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
     1107      if ( corr[ipol] == Stokes::I || corr[ipol] == Stokes::RR || corr[ipol] == Stokes::XX )
     1108        polnos[ipol] = 0 ;
     1109      else if ( corr[ipol] == Stokes::Q || corr[ipol] == Stokes::LL || corr[ipol] == Stokes::YY )
     1110        polnos[ipol] = 1 ;
     1111      else if ( corr[ipol] == Stokes::U || corr[ipol] == Stokes::RL || corr[ipol] == Stokes::XY )
     1112        polnos[ipol] = 2 ;
     1113      else if ( corr[ipol] == Stokes::V || corr[ipol] == Stokes::LR || corr[ipol] == Stokes::YX )
     1114        polnos[ipol] = 3 ;
     1115    }
     1116    return polnos ;
     1117  }
     1118  String getPolType( Int &corr )
     1119  {
     1120    String poltype = "" ;
     1121    if ( corr == Stokes::I || corr == Stokes::Q || corr == Stokes::U || corr == Stokes::V )
     1122      poltype = "stokes" ;
     1123    else if ( corr == Stokes::XX || corr == Stokes::YY || corr == Stokes::XY || corr == Stokes::YX )
     1124      poltype = "linear" ;
     1125    else if ( corr == Stokes::RR || corr == Stokes::LL || corr == Stokes::RL || corr == Stokes::LR )
     1126      poltype = "circular" ;
     1127    else if ( corr == Stokes::Plinear || corr == Stokes::Pangle )
     1128      poltype = "linpol" ;
     1129    return poltype ;   
     1130  }
     1131  uInt getWeatherId()
     1132  {
     1133    // if only one row, return 0
     1134    if ( weatherTime.nelements() == 1 )
     1135      return 0 ;
     1136
     1137    // @todo At the moment, do binary search every time
     1138    //       if this is bottleneck, frequency of binary search must be reduced
     1139    Double t = currentTime.get( "s" ).getValue() ;
     1140    uInt idx = min( binarySearch( weatherTime, t ), weatherTime.nelements()-1 ) ;
     1141    if ( weatherTime[idx] < t ) {
     1142      if ( idx != weatherTime.nelements()-1 ) {
     1143        if ( weatherTime[idx+1] - t < 0.5 * weatherInterval[idx+1] )
     1144          idx++ ;
     1145      }
     1146    }
     1147    else if ( weatherTime[idx] > t ) {
     1148      if ( idx != 0 ) {
     1149        if ( weatherTime[idx] - t > 0.5 * weatherInterval[idx] )
     1150          idx-- ;
     1151      }
     1152    }
     1153    return idx ;
     1154  }
     1155  void processSysCal( Int &spwId )
     1156  {
     1157    // get feedId from row
     1158    Int feedId = (Int)tablerow.record().asuInt( "BEAMNO" ) ;
     1159
     1160    uInt nrow = sctab.nrow() ;
     1161    ROScalarColumn<Int> col( sctab, "ANTENNA_ID" ) ;
     1162    Vector<Int> aids = col.getColumn() ;
     1163    col.attach( sctab, "FEED_ID" ) ;
     1164    Vector<Int> fids = col.getColumn() ;
     1165    col.attach( sctab, "SPECTRAL_WINDOW_ID" ) ;
     1166    Vector<Int> sids = col.getColumn() ;
     1167    ROScalarColumn<Double> timeCol( sctab, "TIME" ) ;
     1168    ROScalarColumn<Double> intCol( sctab, "INTERVAL" ) ;
     1169    for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
     1170      if ( aids[irow] == antennaId
     1171           && fids[irow] == feedId
     1172           && sids[irow] == spwId ) {
     1173        syscalRow[numSysCalRow] = irow ;
     1174        syscalTime[numSysCalRow] = timeCol( irow ) ;
     1175        syscalInterval[numSysCalRow] = intCol( irow ) ;
     1176        numSysCalRow++ ;
     1177      }
     1178    }
     1179  }
     1180  uInt getSysCalIndex()
     1181  {
     1182    // if only one row, return 0
     1183    if ( numSysCalRow == 1 || !isSysCal )
     1184      return 0 ;
     1185
     1186    // @todo At the moment, do binary search every time
     1187    //       if this is bottleneck, frequency of binary search must be reduced
     1188    Double t = currentTime.get( "s" ).getValue() ;
     1189    Vector<Double> tslice  = syscalTime( Slice(0, numSysCalRow) ) ;
     1190    uInt idx = min( binarySearch( tslice, t ), numSysCalRow-1 ) ;
     1191    if ( syscalTime[idx] < t ) {
     1192      if ( idx != numSysCalRow-1 ) {
     1193        if ( syscalTime[idx+1] - t < 0.5 * syscalInterval[idx+1] )
     1194          idx++ ;
     1195      }
     1196    }
     1197    else if ( syscalTime[idx] > t ) {
     1198      if ( idx != 0 ) {
     1199        if ( syscalTime[idx] - t > 0.5 * syscalInterval[idx] )
     1200          idx-- ;
     1201      }
     1202    }
     1203    return idx ;   
     1204  }
     1205  Block<uInt> getTcalId( Double &t )
     1206  {
     1207    // return 0 if no SysCal table
     1208    if ( !isSysCal ) {
     1209      return Block<uInt>( 4, 0 ) ;
     1210    }
     1211     
     1212    // get feedId from row
     1213    Int feedId = (Int)tablerow.record().asuInt( "BEAMNO" ) ;
     1214
     1215    // key
     1216    String key = keyTcal( feedId, spwId, t ) ;
     1217   
     1218    // retrieve ids
     1219    Vector<uInt> ids = syscalRecord.asArrayuInt( key ) ;
     1220    //Vector<uInt> ids = syscalRecord[key] ;
     1221    uInt np = ids[1] - ids[0] + 1 ;
     1222    Block<uInt> tcalids( np ) ;
     1223    if ( np > 0 ) {
     1224      tcalids[0] = ids[0] ;
     1225      if ( np > 1 ) {
     1226        tcalids[1] = ids[1] ;
     1227        for ( uInt ip = 2 ; ip < np ; ip++ )
     1228          tcalids[ip] = ids[0] + ip - 1 ;
     1229      }
     1230    }
     1231    return tcalids ;
     1232  }
     1233  uInt maxNumPol()
     1234  {
     1235    ROScalarColumn<Int> numCorrCol( poltab, "NUM_CORR" ) ;
     1236    return max( numCorrCol.getColumn() ) ;
     1237  }
     1238
     1239  Scantable &scantable;
     1240  Int antennaId;
     1241  uInt rowidx;
     1242  String dataColumnName;
     1243  TableRow tablerow;
     1244  STHeader header;
     1245  Vector<Int> feedEntry;
     1246  uInt nbeam;
     1247  Int npol;
     1248  Int nchan;
     1249  Int sourceId;
     1250  Int polId;
     1251  Int spwId;
     1252  uInt cycleNo;
     1253  MDirection sourceDir;
     1254  MPosition antpos;
     1255  MEpoch currentTime;
     1256  map<Int,uInt> ifmap;
     1257  Block<uInt> polnos;
     1258  Bool getpt;
     1259  Vector<Double> pointingTime;
     1260  Cube<Double> pointingDirection;
     1261  MDirection::Types dirType;
     1262  Bool isWeather;
     1263  Vector<Double> weatherTime;
     1264  Vector<Double> weatherInterval;
     1265  Bool isSysCal;
     1266  Record syscalRecord;
     1267  //map< String,Vector<uInt> > syscalRecord;
     1268  uInt numSysCalRow ;
     1269  Vector<uInt> syscalRow;
     1270  Vector<Double> syscalTime;
     1271  Vector<Double> syscalInterval;
     1272  //String tsysCol;
     1273  //String tcalCol;
     1274
     1275  // MS subtables
     1276  Table obstab;
     1277  Table sctab;
     1278  Table spwtab;
     1279  Table statetab;
     1280  Table ddtab;
     1281  Table poltab;
     1282  Table fieldtab;
     1283  Table anttab;
     1284  Table srctab;
     1285  Matrix<Float> sp;
     1286  Matrix<uChar> fl;
     1287  MeasFrame mf;
     1288
     1289  // MS MAIN columns
     1290  ROTableColumn intervalCol;
     1291  ROTableColumn flagRowCol;
     1292  ROArrayColumn<Float> floatDataCol;
     1293  ROArrayColumn<Complex> dataCol;
     1294  ROArrayColumn<Bool> flagCol;
     1295
     1296  // MS SYSCAL columns
     1297  ROArrayColumn<Float> sysCalTsysCol;
     1298
     1299  // Scantable MAIN columns
     1300  RecordFieldPtr<Double> timeRF,intervalRF,sourceVelocityRF;
     1301  RecordFieldPtr< Vector<Double> > directionRF,scanRateRF,
     1302    sourceProperMotionRF,sourceDirectionRF;
     1303  RecordFieldPtr<Float> azimuthRF,elevationRF;
     1304  RecordFieldPtr<uInt> weatherIdRF,cycleNoRF,flagRowRF,polNoRF,tcalIdRF,
     1305    ifNoRF,freqIdRF,moleculeIdRF,beamNoRF,focusIdRF,scanNoRF;
     1306  RecordFieldPtr< Vector<Float> > spectraRF,tsysRF;
     1307  RecordFieldPtr< Vector<uChar> > flagtraRF;
     1308  RecordFieldPtr<String> sourceNameRF,fieldNameRF;
     1309  RecordFieldPtr<Int> sourceTypeRF;
     1310};
     1311
     1312class BaseTcalVisitor: public TableVisitor {
     1313  uInt lastRecordNo ;
     1314  Int lastAntennaId ;
     1315  Int lastFeedId ;
     1316  Int lastSpwId ;
     1317  Double lastTime ;
     1318protected:
     1319  const Table &table;
     1320  uInt count;
     1321public:
     1322  BaseTcalVisitor(const Table &table)
     1323   : table(table)
     1324  {
     1325    count = 0;
     1326  }
     1327 
     1328  virtual void enterAntennaId(const uInt recordNo, Int columnValue) { }
     1329  virtual void leaveAntennaId(const uInt recordNo, Int columnValue) { }
     1330  virtual void enterFeedId(const uInt recordNo, Int columnValue) { }
     1331  virtual void leaveFeedId(const uInt recordNo, Int columnValue) { }
     1332  virtual void enterSpwId(const uInt recordNo, Int columnValue) { }
     1333  virtual void leaveSpwId(const uInt recordNo, Int columnValue) { }
     1334  virtual void enterTime(const uInt recordNo, Double columnValue) { }
     1335  virtual void leaveTime(const uInt recordNo, Double columnValue) { }
     1336
     1337  virtual Bool visitRecord(const uInt recordNo,
     1338                           const Int antennaId,
     1339                           const Int feedId,
     1340                           const Int spwId,
     1341                           const Double time) { return True ; }
     1342
     1343  virtual Bool visit(Bool isFirst, const uInt recordNo,
     1344                     const uInt nCols, void const *const colValues[]) {
     1345    Int antennaId, feedId, spwId;
     1346    Double time;
     1347    { // prologue
     1348      uInt i = 0;
     1349      {
     1350        const Int *col = (const Int *)colValues[i++];
     1351        antennaId = col[recordNo];
     1352      }
     1353      {
     1354        const Int *col = (const Int *)colValues[i++];
     1355        feedId = col[recordNo];
     1356      }
     1357      {
     1358        const Int *col = (const Int *)colValues[i++];
     1359        spwId = col[recordNo];
     1360      }
     1361      {
     1362        const Double *col = (const Double *)colValues[i++];
     1363        time = col[recordNo];
     1364      }
     1365      assert(nCols == i);
     1366    }
     1367
     1368    if (isFirst) {
     1369      enterAntennaId(recordNo, antennaId);
     1370      enterFeedId(recordNo, feedId);
     1371      enterSpwId(recordNo, spwId);
     1372      enterTime(recordNo, time);
     1373    } else {
     1374      if ( lastAntennaId != antennaId ) {
     1375        leaveTime(lastRecordNo, lastTime);
     1376        leaveSpwId(lastRecordNo, lastSpwId);
     1377        leaveFeedId(lastRecordNo, lastFeedId);
     1378        leaveAntennaId(lastRecordNo, lastAntennaId);
     1379
     1380        enterAntennaId(recordNo, antennaId);
     1381        enterFeedId(recordNo, feedId);
     1382        enterSpwId(recordNo, spwId);
     1383        enterTime(recordNo, time);
     1384      }       
     1385      else if (lastFeedId != feedId) {
     1386        leaveTime(lastRecordNo, lastTime);
     1387        leaveSpwId(lastRecordNo, lastSpwId);
     1388        leaveFeedId(lastRecordNo, lastFeedId);
     1389
     1390        enterFeedId(recordNo, feedId);
     1391        enterSpwId(recordNo, spwId);
     1392        enterTime(recordNo, time);
     1393      } else if (lastSpwId != spwId) {
     1394        leaveTime(lastRecordNo, lastTime);
     1395        leaveSpwId(lastRecordNo, lastSpwId);
     1396
     1397        enterSpwId(recordNo, spwId);
     1398        enterTime(recordNo, time);
     1399      } else if (lastTime != time) {
     1400        leaveTime(lastRecordNo, lastTime);
     1401        enterTime(recordNo, time);
     1402      }
     1403    }
     1404    count++;
     1405    Bool result = visitRecord(recordNo, antennaId, feedId, spwId, time);
     1406
     1407    { // epilogue
     1408      lastRecordNo = recordNo;
     1409
     1410      lastAntennaId = antennaId;
     1411      lastFeedId = feedId;
     1412      lastSpwId = spwId;
     1413      lastTime = time;
     1414    }
     1415    return result ;
     1416  }
     1417
     1418  virtual void finish() {
     1419    if (count > 0) {
     1420      leaveTime(lastRecordNo, lastTime);
     1421      leaveSpwId(lastRecordNo, lastSpwId);
     1422      leaveFeedId(lastRecordNo, lastFeedId);
     1423      leaveAntennaId(lastRecordNo, lastAntennaId);
     1424    }
     1425  }
     1426};
     1427
     1428class TcalVisitor: public BaseTcalVisitor, public MSFillerUtils {
     1429public:
     1430  TcalVisitor(const Table &table, Table &tcaltab, Record &r, Int aid )
     1431  //TcalVisitor(const Table &table, Table &tcaltab, map< String,Vector<uInt> > &r, Int aid )
     1432    : BaseTcalVisitor( table ),
     1433      tcal(tcaltab),
     1434      rec(r),
     1435      antenna(aid)
     1436  {
     1437    process = False ;
     1438    rowidx = 0 ;
     1439
     1440    // attach to SYSCAL columns
     1441    timeCol.attach( table, "TIME" ) ;
     1442
     1443    // add rows
     1444    uInt addrow = table.nrow() * 4 ;
     1445    tcal.addRow( addrow ) ;
     1446
     1447    // attach to TCAL columns
     1448    row = TableRow( tcal ) ;
     1449    TableRecord &trec = row.record() ;
     1450    idRF.attachToRecord( trec, "ID" ) ;
     1451    timeRF.attachToRecord( trec, "TIME" ) ;
     1452    tcalRF.attachToRecord( trec, "TCAL" ) ;
     1453  }
     1454
     1455  virtual void enterAntennaId(const uInt recordNo, Int columnValue) {
     1456    if ( columnValue == antenna )
     1457      process = True ;
     1458  }
     1459  virtual void leaveAntennaId(const uInt recordNo, Int columnValue) {
     1460    process = False ;
     1461  }
     1462  virtual void enterFeedId(const uInt recordNo, Int columnValue) { }
     1463  virtual void leaveFeedId(const uInt recordNo, Int columnValue) { }
     1464  virtual void enterSpwId(const uInt recordNo, Int columnValue) { }
     1465  virtual void leaveSpwId(const uInt recordNo, Int columnValue) { }
     1466  virtual void enterTime(const uInt recordNo, Double columnValue) {
     1467    qtime = timeCol( recordNo ) ;
     1468  }
     1469  virtual void leaveTime(const uInt recordNo, Double columnValue) { }
     1470  virtual Bool visitRecord(const uInt recordNo,
     1471                           const Int antennaId,
     1472                           const Int feedId,
     1473                           const Int spwId,
     1474                           const Double time)
     1475  {
     1476    //cout << "(" << recordNo << "," << antennaId << "," << feedId << "," << spwId << ")" << endl ;
     1477    if ( process ) {
     1478      String sTime = MVTime( qtime ).string( MVTime::YMD ) ;
     1479      *timeRF = sTime ;
     1480      uInt oldidx = rowidx ;
     1481      Matrix<Float> subtcal = tcalCol( recordNo ) ;
     1482      Vector<uInt> idminmax( 2 ) ;
     1483      for ( uInt ipol = 0 ; ipol < subtcal.nrow() ; ipol++ ) {
     1484        *idRF = rowidx ;
     1485        tcalRF.define( subtcal.row( ipol ) ) ;
     1486       
     1487        // commit row
     1488        row.put( rowidx ) ;
     1489        rowidx++ ;
     1490      }
     1491     
     1492      idminmax[0] = oldidx ;
     1493      idminmax[1] = rowidx - 1 ;
     1494     
     1495      String key = keyTcal( feedId, spwId, sTime ) ;
     1496      rec.define( key, idminmax ) ;
     1497      //rec[key] = idminmax ;
     1498    }
     1499    return True ;
     1500  }
     1501  virtual void finish()
     1502  {
     1503    BaseTcalVisitor::finish() ;
     1504
     1505    if ( tcal.nrow() > rowidx ) {
     1506      uInt numRemove = tcal.nrow() - rowidx ;
     1507      //cout << "numRemove = " << numRemove << endl ;
     1508      Vector<uInt> rows( numRemove ) ;
     1509      indgen( rows, rowidx ) ;
     1510      tcal.removeRow( rows ) ;
     1511    }
     1512
     1513  }
     1514  void setTcalColumn( String &col )
     1515  {
     1516    //colName = col ;
     1517    tcalCol.attach( table, col ) ;
     1518  }
     1519private:
     1520  Table &tcal;
     1521  Record &rec;
     1522  //map< String,Vector<uInt> > &rec;
     1523  Int antenna;
     1524  uInt rowidx;
     1525  Bool process;
     1526  Quantum<Double> qtime;
     1527  TableRow row;
     1528  String colName;
     1529
     1530  // MS SYSCAL columns
     1531  ROScalarQuantColumn<Double> timeCol;
     1532  ROArrayColumn<Float> tcalCol;
     1533
     1534  // TCAL columns
     1535  RecordFieldPtr<uInt> idRF;
     1536  RecordFieldPtr<String> timeRF;
     1537  RecordFieldPtr< Vector<Float> > tcalRF;
     1538};
    681539
    691540MSFiller::MSFiller( casa::CountedPtr<Scantable> stable )
     
    1221593
    1231594  MeasurementSet *tmpMS = new MeasurementSet( filename, Table::Old ) ;
    124   //mstable_ = (*tmpMS)( tmpMS->col("ANTENNA1") == antenna_
    125   //                     && tmpMS->col("ANTENNA1") == tmpMS->col("ANTENNA2") ) ;
    1261595  tablename_ = tmpMS->tableName() ;
    1271596  if ( antenna_ == -1 && antennaStr_.size() > 0 ) {
     
    1391608  mstable_ = MeasurementSet( (*tmpMS)( tmpMS->col("ANTENNA1") == antenna_
    1401609                                       && tmpMS->col("ANTENNA1") == tmpMS->col("ANTENNA2") ) ) ;
    141 //   stringstream ss ;
    142 //   ss << "SELECT FROM $1 WHERE ANTENNA1 == ANTENNA2 && ANTENNA1 == " << antenna_ ;
    143 //   String taql( ss.str() ) ;
    144 //   mstable_ = MeasurementSet( tableCommand( taql, *tmpMS ) ) ;
     1610
    1451611  delete tmpMS ;
    1461612
     
    1561622void MSFiller::fill()
    1571623{
    158   os_.origin( LogOrigin( "MSFiller", "fill()", WHERE ) ) ;
    1591624  //double startSec = mathutil::gettimeofday_sec() ;
    1601625  //os_ << "start MSFiller::fill() startSec=" << startSec << LogIO::POST ;
    1611626
    162   //double time0 = mathutil::gettimeofday_sec() ;
    163   //os_ << "start init fill: " << time0 << LogIO::POST ;
     1627  os_.origin( LogOrigin( "MSFiller", "fill()", WHERE ) ) ;
    1641628
    1651629  // Initialize header
    1661630  STHeader sdh ; 
    1671631  initHeader( sdh ) ;
     1632  table_->setHeader( sdh ) ;
    1681633 
    1691634  // check if optional table exists
    170   //const TableRecord msrec = tablesel_.keywordSet() ;
    171   const TableRecord msrec = mstable_.keywordSet() ;
     1635  const TableRecord &msrec = mstable_.keywordSet() ;
    1721636  isDoppler_ = msrec.isDefined( "DOPPLER" ) ;
    1731637  if ( isDoppler_ )
     
    1991663      isWeather_ = False ;
    2001664
    201   // Access to MS subtables
    202   MSField fieldtab = mstable_.field() ;
    203   MSPolarization poltab = mstable_.polarization() ;
    204   MSDataDescription ddtab = mstable_.dataDescription() ;
    205   MSObservation obstab = mstable_.observation() ;
    206   MSSource srctab = mstable_.source() ;
    207   MSSpectralWindow spwtab = mstable_.spectralWindow() ;
    208   MSSysCal caltab = mstable_.sysCal() ;
    209   if ( caltab.nrow() == 0 )
    210     isSysCal_ = False ;
    211   else {
     1665  // column name for Tsys and Tcal
     1666  if ( isSysCal_ ) {
     1667    const MSSysCal &caltab = mstable_.sysCal() ;
    2121668    if ( !caltab.tableDesc().isColumn( colTcal_ ) ) {
    2131669      colTcal_ = "TCAL" ;
     
    2211677    }
    2221678  }
    223 //   colTcal_ = "TCAL" ;
    224 //   colTsys_ = "TSYS" ;
    225   MSPointing pointtab = mstable_.pointing() ;
    226   if ( mstable_.weather().nrow() == 0 )
    227     isWeather_ = False ;
    228   MSState stattab = mstable_.state() ;
    229   MSAntenna anttab = mstable_.antenna() ;
    230 
    231   // TEST
    232   // memory allocation by boost::object_pool
    233   boost::object_pool<ROTableColumn> *tpoolr = new boost::object_pool<ROTableColumn> ;
    234   //
     1679  else {
     1680    colTcal_ = "NONE" ;
     1681    colTsys_ = "NONE" ;
     1682  }
     1683
     1684  // Access to MS subtables
     1685  //MSField &fieldtab = mstable_.field() ;
     1686  //MSPolarization &poltab = mstable_.polarization() ;
     1687  //MSDataDescription &ddtab = mstable_.dataDescription() ;
     1688  //MSObservation &obstab = mstable_.observation() ;
     1689  //MSSource &srctab = mstable_.source() ;
     1690  //MSSpectralWindow &spwtab = mstable_.spectralWindow() ;
     1691  //MSSysCal &caltab = mstable_.sysCal() ;
     1692  MSPointing &pointtab = mstable_.pointing() ;
     1693  //MSState &stattab = mstable_.state() ;
     1694  //MSAntenna &anttab = mstable_.antenna() ;
    2351695
    2361696  // SUBTABLES: FREQUENCIES
     
    2471707
    2481708  // SUBTABLES: TCAL
    249   fillTcal( tpoolr ) ;
     1709  fillTcal() ;
    2501710
    2511711  // SUBTABLES: FIT
     
    2551715  //fillHistory() ;
    2561716
    257   // MAIN
    258   // Iterate over several ids
    259   map<Int, uInt> ifmap ; // (IFNO, FREQ_ID) pair
    260   ROArrayQuantColumn<Double> *sharedQDArrCol = new ROArrayQuantColumn<Double>( anttab, "POSITION" ) ;
    261   Vector< Quantum<Double> > antpos = (*sharedQDArrCol)( antenna_ ) ;
    262   delete sharedQDArrCol ;
    263   MPosition mp( MVPosition( antpos ), MPosition::ITRF ) ;
    264   Vector<Double> pt ;
    265   ROArrayColumn<Double> pdcol ;
    266   Vector<Double> defaultScanrate( 2, 0.0 ) ;
    267   if ( getPt_ ) {
    268     pointtab = MSPointing( pointtab( pointtab.col("ANTENNA_ID")==antenna_ ).sort("TIME") ) ;
    269     ROScalarColumn<Double> ptcol( pointtab, "TIME" ) ;
    270     ptcol.getColumn( pt ) ;
    271     TableRecord trec = ptcol.keywordSet() ;
    272     String tUnit = trec.asArrayString( "QuantumUnits" ).data()[0] ;
    273     if ( tUnit == "d" )
    274       pt *= 86400.0 ;
    275     pdcol.attach( pointtab, "DIRECTION" ) ;
    276   }
    277   String stationName = asString( "STATION", antenna_, anttab, tpoolr ) ;
    278   String antennaName = asString( "NAME", antenna_, anttab, tpoolr ) ;
    279   sdh.antennaposition.resize( 3 ) ;
    280   for ( int i = 0 ; i < 3 ; i++ )
    281     sdh.antennaposition[i] = antpos[i].getValue( "m" ) ;
    282   String telescopeName = "" ;
    283 
    284   //double time1 = mathutil::gettimeofday_sec() ;
    285   //os_ << "end init fill: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    286 
    287   // row based
    288   Table &stab = table_->table() ;
    289   TableRow row( stab ) ;
    290   TableRecord &trec = row.record() ;
    291   RecordFieldPtr< Array<Float> > spRF( trec, "SPECTRA" ) ;
    292   RecordFieldPtr< Array<uChar> > ucarrRF( trec, "FLAGTRA" ) ;
    293   RecordFieldPtr<Double> timeRF( trec, "TIME" ) ;
    294   RecordFieldPtr< Array<Float> > tsysRF( trec, "TSYS" ) ;
    295   RecordFieldPtr<Double> intervalRF( trec, "INTERVAL" ) ;
    296   RecordFieldPtr< Array<Double> > dirRF( trec, "DIRECTION" ) ;
    297   RecordFieldPtr<Float> azRF( trec, "AZIMUTH" ) ;
    298   RecordFieldPtr<Float> elRF( trec, "ELEVATION" ) ;
    299   RecordFieldPtr< Array<Double> > scrRF( trec, "SCANRATE" ) ;
    300   RecordFieldPtr<uInt> cycleRF( trec, "CYCLENO" ) ;
    301   RecordFieldPtr<uInt> flrRF( trec, "FLAGROW" ) ;
    302   RecordFieldPtr<uInt> tcalidRF( trec, "TCAL_ID" ) ;
    303   RecordFieldPtr<uInt> widRF( trec, "WEATHER_ID" ) ;
    304   RecordFieldPtr<uInt> polnoRF( trec, "POLNO" ) ;
    305   RecordFieldPtr<Int> refbRF( trec, "REFBEAMNO" ) ;
    306   RecordFieldPtr<Int> fitidRF( trec, "FIT_ID" ) ;
    307   RecordFieldPtr<Float> tauRF( trec, "OPACITY" ) ;
    308   RecordFieldPtr<uInt> beamRF( trec, "BEAMNO" ) ;
    309   RecordFieldPtr<uInt> focusidRF( trec, "FOCUS_ID" ) ;
    310   RecordFieldPtr<uInt> ifnoRF( trec, "IFNO" ) ;
    311   RecordFieldPtr<uInt> molidRF( trec, "MOLECULE_ID" ) ;
    312   RecordFieldPtr<uInt> freqidRF( trec, "FREQ_ID" ) ;
    313   RecordFieldPtr<uInt> scanRF( trec, "SCANNO" ) ;
    314   RecordFieldPtr<Int> srctypeRF( trec, "SRCTYPE" ) ;
    315   RecordFieldPtr<String> srcnameRF( trec, "SRCNAME" ) ;
    316   RecordFieldPtr<String> fieldnameRF( trec, "FIELDNAME" ) ;
    317   RecordFieldPtr< Array<Double> > srcpmRF( trec, "SRCPROPERMOTION" ) ;
    318   RecordFieldPtr< Array<Double> > srcdirRF( trec, "SRCDIRECTION" ) ;
    319   RecordFieldPtr<Double> sysvelRF( trec, "SRCVELOCITY" ) ;
    320 
    321   // REFBEAMNO
    322   *refbRF = -1 ;
    323 
    324   // FIT_ID
    325   *fitidRF = -1 ;
    326 
    327   // OPACITY
    328   *tauRF = 0.0 ;
    329 
    330   //
    331   // ITERATION: OBSERVATION_ID
    332   //
    333   TableIterator iter0( mstable_, "OBSERVATION_ID" ) ;
    334   while( !iter0.pastEnd() ) {
    335     //time0 = mathutil::gettimeofday_sec() ;
    336     //os_ << "start 0th iteration: " << time0 << LogIO::POST ;
    337     Table t0 = iter0.table() ;
    338     Int obsId = asInt( "OBSERVATION_ID", 0, t0, tpoolr ) ;
    339     if ( sdh.observer == "" ) {
    340       sdh.observer = asString( "OBSERVER", obsId, obstab, tpoolr ) ;
    341     }
    342     if ( sdh.project == "" ) {
    343       sdh.project = asString( "PROJECT", obsId, obstab, tpoolr ) ;
    344     }
    345     ROArrayMeasColumn<MEpoch> *tmpMeasCol = new ROArrayMeasColumn<MEpoch>( obstab, "TIME_RANGE" ) ;
    346     MEpoch me = (*tmpMeasCol)( obsId )( IPosition(1,0) ) ;
    347     delete tmpMeasCol ;
    348     if ( sdh.utc == 0.0 ) {
    349       sdh.utc = me.get( "d" ).getValue() ;
    350     }
    351     if ( telescopeName == "" ) {
    352       telescopeName = asString( "TELESCOPE_NAME", obsId, obstab, tpoolr ) ;
    353     }
    354     Int nbeam = 0 ;
    355     //time1 = mathutil::gettimeofday_sec() ;
    356     //os_ << "end 0th iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    357     //
    358     // ITERATION: FEED1
    359     //
    360     TableIterator iter1( t0, "FEED1" ) ;
    361     while( !iter1.pastEnd() ) {
    362       //time0 = mathutil::gettimeofday_sec() ;
    363       //os_ << "start 1st iteration: " << time0 << LogIO::POST ;
    364       Table t1 = iter1.table() ;
    365       // assume FEED1 == FEED2
    366       Int feedId = asInt( "FEED1", 0, t1, tpoolr ) ;
    367       nbeam++ ;
    368 
    369       // BEAMNO
    370       *beamRF = feedId ;
    371 
    372       // FOCUS_ID
    373       *focusidRF = 0 ;
    374 
    375       //time1 = mathutil::gettimeofday_sec() ;
    376       //os_ << "end 1st iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    377       //
    378       // ITERATION: FIELD_ID
    379       //
    380       TableIterator iter2( t1, "FIELD_ID" ) ;
    381       while( !iter2.pastEnd() ) {
    382         //time0 = mathutil::gettimeofday_sec() ;
    383         //os_ << "start 2nd iteration: " << time0 << LogIO::POST ;
    384         Table t2 = iter2.table() ;
    385         Int fieldId = asInt( "FIELD_ID", 0, t2, tpoolr ) ;
    386         Int srcId = asInt( "SOURCE_ID", fieldId, fieldtab, tpoolr ) ;
    387         String fieldName = asString( "NAME", fieldId, fieldtab, tpoolr ) ;
    388         fieldName += "__" + String::toString(fieldId) ;
    389         ROArrayMeasColumn<MDirection> *delayDirCol = new ROArrayMeasColumn<MDirection>( fieldtab, "DELAY_DIR" ) ;
    390         Vector<MDirection> delayDir = (*delayDirCol)( fieldId ) ;
    391         delete delayDirCol ;         
    392 
    393         // FIELDNAME
    394         *fieldnameRF = fieldName ;
    395 
    396 
    397         //time1 = mathutil::gettimeofday_sec() ;
    398         //os_ << "end 2nd iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    399         //
    400         // ITERATION: DATA_DESC_ID
    401         //
    402         TableIterator iter3( t2, "DATA_DESC_ID" ) ;
    403         while( !iter3.pastEnd() ) {
    404           //time0 = mathutil::gettimeofday_sec() ;
    405           //os_ << "start 3rd iteration: " << time0 << LogIO::POST ;
    406           Table t3 = iter3.table() ;
    407           Int ddId = asInt( "DATA_DESC_ID", 0, t3, tpoolr ) ;
    408           Int polId = asInt( "POLARIZATION_ID", ddId, ddtab, tpoolr ) ;
    409           Int spwId = asInt( "SPECTRAL_WINDOW_ID", ddId, ddtab, tpoolr ) ;
    410 
    411           // IFNO
    412           *ifnoRF = (uInt)spwId ;
    413 
    414           // polarization information
    415           Int npol = asInt( "NUM_CORR", polId, poltab, tpoolr ) ;
    416           ROArrayColumn<Int> *roArrICol = new ROArrayColumn<Int>( poltab, "CORR_TYPE" ) ;
    417           Vector<Int> corrtype = (*roArrICol)( polId ) ;
    418           delete roArrICol ;
    419           String srcName( "" ) ;
    420           Vector<Double> srcPM( 2, 0.0 ) ;
    421           Vector<Double> srcDir( 2, 0.0 ) ;
    422           MDirection md ;
    423           Vector<Double> restFreqs ;
    424           Vector<String> transitionName ;
    425           Vector<Double> sysVels ;
    426 //           os_ << "npol = " << npol << LogIO::POST ;
    427 //           os_ << "corrtype = " << corrtype << LogIO::POST ;
    428 
    429           // source and molecular transition
    430           sourceInfo( srcId, spwId, srcName, md, srcPM, restFreqs, transitionName, sysVels, tpoolr ) ;
    431 //           os_ << "srcId = " << srcId << ", spwId = " << spwId << LogIO::POST ;
    432 
    433           // SRCNAME
    434           *srcnameRF = srcName ;
    435 
    436 //           os_ << "srcName = " << srcName << LogIO::POST ;
    437 
    438           // SRCPROPERMOTION
    439           *srcpmRF = srcPM ;
    440 
    441           //os_ << "srcPM = " << srcPM << LogIO::POST ;
    442 
    443           // SRCDIRECTION
    444           *srcdirRF = md.getAngle().getValue( "rad" ) ;
    445 
    446           //os_ << "srcDir = " << srcDir << LogIO::POST ;
    447 
    448           // SRCVELOCITY
    449           Double sysVel = 0.0 ;
    450           if ( !sysVels.empty() )
    451             sysVel = sysVels[0] ;
    452           *sysvelRF = sysVel ;
    453 
    454 //           os_ << "sysVel = " << sysVel << LogIO::POST ;
    455 
    456           uInt molId = table_->molecules().addEntry( restFreqs, transitionName, transitionName ) ;
    457 
    458           // MOLECULE_ID
    459           *molidRF = molId ;
    460 
    461           // spectral setup
    462           uInt freqId ;
    463           Int nchan = asInt( "NUM_CHAN", spwId, spwtab, tpoolr ) ;
    464           Bool iswvr = False ;
    465           if ( nchan == 4 ) iswvr = True ;
    466           sdh.nchan = max( sdh.nchan, nchan ) ;
    467           map<Int,uInt>::iterator iter = ifmap.find( spwId ) ;
    468           if ( iter == ifmap.end() ) {
    469             ROScalarMeasColumn<MEpoch> *tmpMeasCol = new ROScalarMeasColumn<MEpoch>( t3, "TIME" ) ;
    470             me = (*tmpMeasCol)( 0 ) ;
    471             delete tmpMeasCol ;
    472             Double refpix ;
    473             Double refval ;
    474             Double increment ;
    475             spectralSetup( spwId,
    476                            me,
    477                            mp,
    478                            md,
    479                            refpix,
    480                            refval,
    481                            increment,
    482                            nchan,
    483                            sdh.freqref,
    484                            sdh.reffreq,
    485                            sdh.bandwidth,
    486                            tpoolr ) ;
    487             freqId = table_->frequencies().addEntry( refpix, refval, increment ) ;
    488             ifmap.insert( pair<Int, uInt>(spwId,freqId) ) ;
    489             //os_ << "added to ifmap: (" << spwId << "," << freqId << ")" << LogIO::POST ;
    490           }
    491           else {
    492             freqId = iter->second ;
    493           }
    494 
    495           // FREQ_ID
    496           *freqidRF = freqId ;
    497 
    498           // for TSYS and TCAL
    499           Vector<MEpoch> scTime ;
    500           Vector<Double> scInterval ;
    501           ROArrayColumn<Float> scTsysCol ;
    502           MSSysCal caltabsel ;
    503           if ( isSysCal_ ) {
    504             caltabsel = caltab( caltab.col("ANTENNA_ID") == antenna_ && caltab.col("FEED_ID") == feedId && caltab.col("SPECTRAL_WINDOW_ID") == spwId ).sort("TIME") ;
    505             ROScalarMeasColumn<MEpoch> scTimeCol( caltabsel, "TIME" ) ;
    506             scTime.resize( caltabsel.nrow() ) ;
    507             for ( uInt irow = 0 ; irow < caltabsel.nrow() ; irow++ )
    508               scTime[irow] = scTimeCol( irow ) ;
    509             ROScalarColumn<Double> scIntervalCol( caltabsel, "INTERVAL" ) ;
    510             scIntervalCol.getColumn( scInterval ) ;
    511             if ( colTsys_ != "NONE" )
    512               scTsysCol.attach( caltabsel, colTsys_ ) ;
    513           }
    514 
    515           sdh.npol = max( sdh.npol, npol ) ;
    516           if ( !iswvr && sdh.poltype == "" ) sdh.poltype = getPolType( corrtype[0] ) ;
    517 
    518           //time1 = mathutil::gettimeofday_sec() ;
    519           //os_ << "end 3rd iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    520           //
    521           // ITERATION: SCAN_NUMBER
    522           //
    523           TableIterator iter4( t3, "SCAN_NUMBER" ) ;
    524           while( !iter4.pastEnd() ) {
    525             //time0 = mathutil::gettimeofday_sec() ;
    526             //os_ << "start 4th iteration: " << time0 << LogIO::POST ;
    527             Table t4 = iter4.table() ;
    528             Int scanNum = asInt( "SCAN_NUMBER", 0, t4, tpoolr ) ;
    529 
    530             // SCANNO
    531             *scanRF = scanNum - 1 ;
    532 
    533             uInt cycle = 0 ;
    534 
    535             //time1 = mathutil::gettimeofday_sec() ;
    536             //os_ << "end 4th iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    537             //
    538             // ITERATION: STATE_ID
    539             //
    540             TableIterator iter5( t4, "STATE_ID" ) ;
    541             while( !iter5.pastEnd() ) {
    542               //time0 = mathutil::gettimeofday_sec() ;
    543               //os_ << "start 5th iteration: " << time0 << LogIO::POST ;
    544               Table t5 = iter5.table() ;
    545               Int stateId = asInt( "STATE_ID", 0, t5, tpoolr ) ;
    546               String obstype = asString( "OBS_MODE", 0, stattab, tpoolr ) ;
    547               if ( sdh.obstype == "" ) sdh.obstype = obstype ;
    548 
    549               Int nrow = t5.nrow() ;
    550               //time1 = mathutil::gettimeofday_sec() ;
    551               //os_ << "end 5th iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    552 
    553               Cube<Float> spArr ;
    554               Cube<Bool> flArr ;
    555               reshapeSpectraAndFlagtra( spArr,
    556                                         flArr,
    557                                         t5,
    558                                         npol,
    559                                         nchan,
    560                                         nrow,
    561                                         corrtype ) ;
    562               if ( sdh.fluxunit == "" ) {
    563                 String colName = "FLOAT_DATA" ;
    564                 if ( isData_ ) colName = "DATA" ;
    565                 ROTableColumn dataCol( t5, colName ) ;
    566                 const TableRecord &dataColKeys = dataCol.keywordSet() ;
    567                 if ( dataColKeys.isDefined( "UNIT" ) )
    568                   sdh.fluxunit = dataColKeys.asString( "UNIT" ) ;
    569                 else if ( dataColKeys.isDefined( "QuantumUnits" ) )
    570                   sdh.fluxunit = dataColKeys.asString( "QuantumUnits" ) ;
    571               }
    572 
    573               ROScalarMeasColumn<MEpoch> *mTimeCol = new ROScalarMeasColumn<MEpoch>( t5, "TIME" ) ;
    574               Block<MEpoch> mTimeB( nrow ) ;
    575               for ( Int irow = 0 ; irow < nrow ; irow++ )
    576                 mTimeB[irow] = (*mTimeCol)( irow ) ;
    577               Block<Int> sysCalIdx( nrow, -1 ) ;
    578               if ( isSysCal_ ) {
    579                 getSysCalTime( scTime, scInterval, mTimeB, sysCalIdx ) ;
    580               }
    581               delete mTimeCol ;
    582               Matrix<Float> defaulttsys( npol, 1, 1.0 ) ;
    583               Int srcType = getSrcType( stateId, tpoolr ) ;
    584               uInt diridx = 0 ;
    585               uInt wid = 0 ;
    586               Int pidx = 0 ;
    587               Bool crossOK = False ;
    588               Block<uInt> polnos( npol, 99 ) ;
    589               for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
    590                 Block<uInt> p = getPolNo( corrtype[ipol] ) ;
    591                 if ( p.size() > 1 ) {
    592                   if ( crossOK ) continue ;
    593                   else {
    594                     polnos[pidx] = p[0] ;
    595                     pidx++ ;
    596                     polnos[pidx] = p[1] ;
    597                     pidx++ ;
    598                     crossOK = True ;
    599                   }
    600                 }
    601                 else {
    602                   polnos[pidx] = p[0] ;
    603                   pidx++ ;
    604                 }
    605               }
    606              
    607               // SRCTYPE
    608               *srctypeRF = srcType ;
    609 
    610               for ( Int irow = 0 ; irow < nrow ; irow++ ) {
    611                 // CYCLENO
    612                 *cycleRF = cycle ;
    613 
    614                 // FLAGROW
    615                 *flrRF = (uInt)asBool( "FLAG_ROW", irow, t5, tpoolr ) ;
    616 
    617                 // SPECTRA, FLAG
    618                 Matrix<Float> sp = spArr.xyPlane( irow ) ;
    619                 Matrix<Bool> flb = flArr.xyPlane( irow ) ;
    620                 Matrix<uChar> fl( flb.shape() ) ;
    621                 convertArray( fl, flb ) ;
    622 
    623                 // TIME
    624                 *timeRF = mTimeB[irow].get("d").getValue() ;
    625 
    626                 // INTERVAL
    627                 *intervalRF = asDouble( "INTERVAL", irow, t5, tpoolr ) ;
    628 
    629                 // TSYS
    630                 Matrix<Float> tsys ;
    631                 if ( sysCalIdx[irow] != -1 && colTsys_ != "NONE" )
    632                   tsys = scTsysCol( sysCalIdx[irow] ) ;
    633                 else
    634                   tsys = defaulttsys ;
    635 
    636                 // TCAL_ID
    637                 Block<uInt> tcalids( npol, 0 ) ;
    638                 if ( sysCalIdx[irow] != -1 && colTcal_ != "NONE" ) {
    639                   tcalids = getTcalId( feedId, spwId, scTime[sysCalIdx[irow]] ) ;
    640                 }
    641 
    642                 // WEATHER_ID
    643                 if ( isWeather_ ) {
    644                   wid = getWeatherId( wid, mTimeB[irow].get("s").getValue() ) ;
    645                   *widRF = mwIndex_[wid] ;
    646                 }
    647                 else {
    648                   *widRF = wid ;
    649                 }
    650                  
    651 
    652                 // DIRECTION, AZEL, SCANRATE
    653                 Vector<Double> dir ;
    654                 Vector<Double> azel ;
    655                 Vector<Double> scanrate = defaultScanrate ;
    656                 String refString ;
    657                 if ( getPt_ )
    658                   diridx = getDirection( diridx, dir, azel, scanrate, pt, pdcol, mTimeB[irow], mp ) ;
    659                 else
    660                   getSourceDirection( dir, azel, scanrate, mTimeB[irow], mp, delayDir ) ;
    661                 *dirRF = dir ;
    662                 *azRF = azel[0] ;
    663                 *elRF = azel[1] ;
    664                 *scrRF = scanrate ;
    665 
    666                 // Polarization dependent things
    667                 for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
    668                   // POLNO
    669                   *polnoRF = polnos[ipol] ;
    670 
    671                   spRF.define( sp.row( ipol ) ) ;
    672                   ucarrRF.define( fl.row( ipol ) ) ;
    673                   tsysRF.define( tsys.row( ipol ) ) ;
    674                   *tcalidRF = tcalids[ipol] ;
    675 
    676                   // Commit row
    677                   stab.addRow() ;
    678                   row.put( stab.nrow()-1 ) ;
    679                 }
    680 
    681                 cycle++ ;
    682               }
    683              
    684               //time1 = mathutil::gettimeofday_sec() ;
    685               //os_ << "end 5th iteration: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    686 
    687               iter5.next() ;
    688             }
    689             iter4.next() ;
    690           }
    691           iter3.next() ;
    692         }
    693         iter2.next() ;
    694       }
    695       iter1.next() ;
    696     }
    697     if ( sdh.nbeam < nbeam ) sdh.nbeam = nbeam ;
    698 
    699     iter0.next() ;
    700   }
    701 
    702 
    703   delete tpoolr ;
    704 
    705 
    706   // Table Keywords
    707   sdh.nif = ifmap.size() ;
    708   if ( ( telescopeName == "" ) || ( antennaName == telescopeName ) ) {
    709     sdh.antennaname = antennaName ;
    710   }
    711   else {
    712     sdh.antennaname = telescopeName + "//" + antennaName ;
    713   }
    714   if ( stationName != "" && stationName != antennaName ) {
    715     sdh.antennaname += "@" + stationName ;
    716   }
    717   ROArrayColumn<Double> pdirCol( pointtab, "DIRECTION" ) ;
    718   String dirref = pdirCol.keywordSet().asRecord("MEASINFO").asString("Ref") ;
    719   if ( dirref == "AZELGEO" || dirref == "AZEL" ) {
    720     dirref = "J2000" ;
    721   }
    722   sscanf( dirref.chars()+1, "%f", &sdh.equinox ) ;
    723   sdh.epoch = "UTC" ;
    724   if (sdh.freqref == "TOPO") {
    725     sdh.freqref = "TOPOCENT";
    726   } else if (sdh.freqref == "GEO") {
    727     sdh.freqref = "GEOCENTR";
    728   } else if (sdh.freqref == "BARY") {
    729     sdh.freqref = "BARYCENT";
    730   } else if (sdh.freqref == "GALACTO") {
    731     sdh.freqref = "GALACTOC";
    732   } else if (sdh.freqref == "LGROUP") {
    733     sdh.freqref = "LOCALGRP";
    734   } else if (sdh.freqref == "CMB") {
    735     sdh.freqref = "CMBDIPOL";
    736   } else if (sdh.freqref == "REST") {
    737     sdh.freqref = "SOURCE";
    738   }
    739 
    740   if ( sdh.fluxunit == "" || sdh.fluxunit == "CNTS" )
    741     sdh.fluxunit = "K" ;
    742   table_->setHeader( sdh ) ;
     1717  /***
     1718   * Start iteration using TableVisitor
     1719   ***/
     1720  Table stab = table_->table() ;
     1721  {
     1722    static const char *cols[] = {
     1723      "OBSERVATION_ID", "FEED1", "FIELD_ID", "DATA_DESC_ID", "SCAN_NUMBER",
     1724      "STATE_ID", "TIME",
     1725      NULL
     1726    };
     1727    static const TypeManagerImpl<Int> tmInt;
     1728    static const TypeManagerImpl<Double> tmDouble;
     1729    static const TypeManager *const tms[] = {
     1730      &tmInt, &tmInt, &tmInt, &tmInt, &tmInt, &tmInt, &tmDouble, NULL
     1731    };
     1732    //double t0 = mathutil::gettimeofday_sec() ;
     1733    MSFillerVisitor myVisitor(mstable_, *table_ );
     1734    //double t1 = mathutil::gettimeofday_sec() ;
     1735    //cout << "MSFillerVisitor(): elapsed time " << t1-t0 << " sec" << endl ;
     1736    myVisitor.setAntenna( antenna_ ) ;
     1737    //myVisitor.setHeader( sdh ) ;
     1738    if ( getPt_ ) {
     1739      Table ptsel = pointtab( pointtab.col("ANTENNA_ID")==antenna_ ).sort( "TIME" ) ;
     1740      myVisitor.setPointingTable( ptsel ) ;
     1741    }
     1742    if ( isWeather_ )
     1743      myVisitor.setWeatherTime( mwTime_, mwInterval_ ) ;
     1744    if ( isSysCal_ )
     1745      myVisitor.setSysCalRecord( tcalrec_ ) ;
     1746   
     1747    //double t2 = mathutil::gettimeofday_sec() ;
     1748    traverseTable(mstable_, cols, tms, &myVisitor);
     1749    //double t3 = mathutil::gettimeofday_sec() ;
     1750    //cout << "traverseTable(): elapsed time " << t3-t2 << " sec" << endl ;
     1751   
     1752    sdh = myVisitor.getHeader() ;
     1753  }
     1754  /***
     1755   * End iteration using TableVisitor
     1756   ***/
     1757
     1758  // set header
     1759  //sdh = myVisitor.getHeader() ;
     1760  //table_->setHeader( sdh ) ;
    7431761
    7441762  // save path to POINTING table
     
    7531771
    7541772  // for GBT
    755   if ( antennaName.contains( "GBT" ) ) {
     1773  if ( sdh.antennaname.contains( "GBT" ) ) {
    7561774    String goTabName = datapath.absoluteName() + "/GBT_GO" ;
    7571775    stab.rwKeywordSet().define( "GBT_GO", goTabName ) ;
     
    7591777
    7601778  // for MS created from ASDM
    761   //mstable_.keywordSet().print(cout) ;
    7621779  const TableRecord &msKeys = mstable_.keywordSet() ;
    7631780  uInt nfields = msKeys.nfields() ;
     
    7821799  //tablesel_.unlock() ;
    7831800  mstable_.unlock() ;
    784 }
    785 
    786 Int MSFiller::getSrcType( Int stateId, boost::object_pool<ROTableColumn> *tpool )
    787 {
    788   //double startSec = mathutil::gettimeofday_sec() ;
    789   //os_ << "start MSFiller::getSrcType() startSec=" << startSec << LogIO::POST ;
    790 
    791   MSState statetab = mstable_.state() ;
    792   String obsMode = asString( "OBS_MODE", stateId, statetab, tpool ) ;
    793   Bool sig = asBool( "SIG", stateId, statetab, tpool ) ;
    794   Bool ref = asBool( "REF", stateId, statetab, tpool ) ;
    795   Double cal = asDouble( "CAL", stateId, statetab, tpool ) ;
    796   //os_ << "OBS_MODE = " << obsMode << LogIO::POST ;
    797 
    798   // determine separator
    799   String sep = "" ;
    800   String tmpStr = obsMode.substr( 0, obsMode.find_first_of( "," ) ) ;
    801   //os_ << "tmpStr = " << tmpStr << LogIO::POST ;
    802   //if ( obsMode.find( ":" ) != String::npos ) {
    803   if ( tmpStr.find( ":" ) != String::npos ) {
    804     sep = ":" ;
    805   }
    806   //else if ( obsMode.find( "." ) != String::npos ) {
    807   else if ( tmpStr.find( "." ) != String::npos ) {
    808     sep = "." ;
    809   }
    810   else if ( tmpStr.find( "#" ) != String::npos ) {
    811     sep = "#" ;
    812   }
    813   //else if ( obsMode.find( "_" ) != String::npos ) {
    814   else if ( tmpStr.find( "_" ) != String::npos ) {
    815     sep = "_" ;
    816   }
    817   //os_ << "separator = " << sep << LogIO::POST ;
    818 
    819   // determine SRCTYPE
    820   Int srcType = SrcType::NOTYPE ;
    821   if ( sep == ":" ) {
    822     // sep == ":"
    823     //
    824     // GBT case
    825     //
    826     // obsMode1=Nod
    827     //    NOD
    828     // obsMode1=OffOn
    829     //    obsMode2=PSWITCHON:  PSON
    830     //    obsMode2=PSWITCHOFF: PSOFF
    831     // obsMode1=??
    832     //    obsMode2=FSWITCH:
    833     //       SIG=1: FSON
    834     //       REF=1: FSOFF
    835     // Calibration scan if CAL != 0
    836     Int epos = obsMode.find_first_of( sep ) ;
    837     Int nextpos = obsMode.find_first_of( sep, epos+1 ) ;
    838     String obsMode1 = obsMode.substr( 0, epos ) ;
    839     String obsMode2 = obsMode.substr( epos+1, nextpos-epos-1 ) ;
    840     if ( obsMode1 == "Nod" ) {
    841       srcType = SrcType::NOD ;
    842     }
    843     else if ( obsMode1 == "OffOn" ) {
    844       if ( obsMode2 == "PSWITCHON" ) srcType = SrcType::PSON ;
    845       if ( obsMode2 == "PSWITCHOFF" ) srcType = SrcType::PSOFF ;
    846     }
    847     else {
    848       if ( obsMode2 == "FSWITCH" ) {
    849         if ( sig ) srcType = SrcType::FSON ;
    850         if ( ref ) srcType = SrcType::FSOFF ;
    851       }
    852     }
    853     if ( cal > 0.0 ) {
    854       if ( srcType == SrcType::NOD )
    855         srcType = SrcType::NODCAL ;
    856       else if ( srcType == SrcType::PSON )
    857         srcType = SrcType::PONCAL ;
    858       else if ( srcType == SrcType::PSOFF )
    859         srcType = SrcType::POFFCAL ;
    860       else if ( srcType == SrcType::FSON )
    861         srcType = SrcType::FONCAL ;
    862       else if ( srcType == SrcType::FSOFF )
    863         srcType = SrcType::FOFFCAL ;
    864       else
    865         srcType = SrcType::CAL ;
    866     }
    867   }
    868   else if ( sep == "." || sep == "#" ) {
    869     // sep == "." or "#"
    870     //
    871     // ALMA & EVLA case (MS via ASDM) before3.1
    872     //
    873     // obsMode1=CALIBRATE_*
    874     //    obsMode2=ON_SOURCE: PONCAL
    875     //    obsMode2=OFF_SOURCE: POFFCAL
    876     // obsMode1=OBSERVE_TARGET
    877     //    obsMode2=ON_SOURCE: PON
    878     //    obsMode2=OFF_SOURCE: POFF
    879     string substr[2] ;
    880     int numSubstr = split( obsMode, substr, 2, "," ) ;
    881     //os_ << "numSubstr = " << numSubstr << LogIO::POST ;
    882     //for ( int i = 0 ; i < numSubstr ; i++ )
    883     //os_ << "substr[" << i << "] = " << substr[i] << LogIO::POST ;
    884     String obsType( substr[0] ) ;
    885     //os_ << "obsType = " << obsType << LogIO::POST ;
    886     Int epos = obsType.find_first_of( sep ) ;
    887     Int nextpos = obsType.find_first_of( sep, epos+1 ) ;
    888     String obsMode1 = obsType.substr( 0, epos ) ;
    889     String obsMode2 = obsType.substr( epos+1, nextpos-epos-1 ) ;
    890     //os_ << "obsMode1 = " << obsMode1 << LogIO::POST ;
    891     //os_ << "obsMode2 = " << obsMode2 << LogIO::POST ;
    892     if ( obsMode1.find( "CALIBRATE_" ) == 0 ) {
    893       if ( obsMode2 == "ON_SOURCE" ) srcType = SrcType::PONCAL ;
    894       if ( obsMode2 == "OFF_SOURCE" ) srcType = SrcType::POFFCAL ;
    895     }
    896     else if ( obsMode1 == "OBSERVE_TARGET" ) {
    897       if ( obsMode2 == "ON_SOURCE" ) srcType = SrcType::PSON ;
    898       if ( obsMode2 == "OFF_SOURCE" ) srcType = SrcType::PSOFF ;
    899     }
    900   }
    901   else if ( sep == "_" ) {
    902     // sep == "_"
    903     //
    904     // ALMA & EVLA case (MS via ASDM) after 3.2
    905     //
    906     // obsMode1=CALIBRATE_*
    907     //    obsMode2=ON_SOURCE: PONCAL
    908     //    obsMode2=OFF_SOURCE: POFFCAL
    909     // obsMode1=OBSERVE_TARGET
    910     //    obsMode2=ON_SOURCE: PON
    911     //    obsMode2=OFF_SOURCE: POFF
    912     string substr[2] ;
    913     int numSubstr = split( obsMode, substr, 2, "," ) ;
    914     //os_ << "numSubstr = " << numSubstr << LogIO::POST ;
    915     //for ( int i = 0 ; i < numSubstr ; i++ )
    916     //os_ << "substr[" << i << "] = " << substr[i] << LogIO::POST ;
    917     String obsType( substr[0] ) ;
    918     //os_ << "obsType = " << obsType << LogIO::POST ;
    919     string substr2[4] ;
    920     int numSubstr2 = split( obsType, substr2, 4, sep ) ;
    921     //Int epos = obsType.find_first_of( sep ) ;
    922     //Int nextpos = obsType.find_first_of( sep, epos+1 ) ;
    923     //String obsMode1 = obsType.substr( 0, epos ) ;
    924     //String obsMode2 = obsType.substr( epos+1, nextpos-epos-1 ) ;
    925     String obsMode1( substr2[0] ) ;
    926     String obsMode2( substr2[2] ) ;
    927     //os_ << "obsMode1 = " << obsMode1 << LogIO::POST ;
    928     //os_ << "obsMode2 = " << obsMode2 << LogIO::POST ;
    929     if ( obsMode1.find( "CALIBRATE" ) == 0 ) {
    930       if ( obsMode2 == "ON" ) srcType = SrcType::PONCAL ;
    931       if ( obsMode2 == "OFF" ) srcType = SrcType::POFFCAL ;
    932     }
    933     else if ( obsMode1 == "OBSERVE" ) {
    934       if ( obsMode2 == "ON" ) srcType = SrcType::PSON ;
    935       if ( obsMode2 == "OFF" ) srcType = SrcType::PSOFF ;
    936     }
    937   }
    938   else {
    939     if ( sig ) srcType = SrcType::SIG ;
    940     if ( ref ) srcType = SrcType::REF ;
    941   }
    942    
    943   //os_ << "srcType = " << srcType << LogIO::POST ;
    944   //double endSec = mathutil::gettimeofday_sec() ;
    945   //os_ << "end MSFiller::getSrcType() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    946   return srcType ;
    947 }
    948 
    949 //Vector<uInt> MSFiller::getPolNo( Int corrType )
    950 Block<uInt> MSFiller::getPolNo( Int corrType )
    951 {
    952   //double startSec = mathutil::gettimeofday_sec() ;
    953   //os_ << "start MSFiller::getPolNo() startSec=" << startSec << LogIO::POST ;
    954   Block<uInt> polno( 1 ) ;
    955 
    956   if ( corrType == Stokes::I || corrType == Stokes::RR || corrType == Stokes::XX ) {
    957     polno = 0 ;
    958   }
    959   else if ( corrType == Stokes::Q || corrType == Stokes::LL || corrType == Stokes::YY ) {
    960     polno = 1 ;
    961   }
    962   else if ( corrType == Stokes::U ) {
    963     polno = 2 ;
    964   }
    965   else if ( corrType == Stokes::V ) {
    966     polno = 3 ;
    967   }
    968   else if ( corrType == Stokes::RL || corrType == Stokes::XY || corrType == Stokes::LR || corrType == Stokes::RL ) {
    969     polno.resize( 2 ) ;
    970     polno[0] = 2 ;
    971     polno[1] = 3 ;
    972   }
    973   else if ( corrType == Stokes::Plinear ) {
    974     polno[0] = 1 ;
    975   }
    976   else if ( corrType == Stokes::Pangle ) {
    977     polno[0] = 2 ;
    978   }
    979   else {
    980     polno = 99 ;
    981   }
    982   //os_ << "polno = " << polno << LogIO::POST ;
    983   //double endSec = mathutil::gettimeofday_sec() ;
    984   //os_ << "end MSFiller::getPolNo() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    985  
    986   return polno ;
    987 }
    988 
    989 String MSFiller::getPolType( Int corrType )
    990 {
    991   //double startSec = mathutil::gettimeofday_sec() ;
    992   //os_ << "start MSFiller::getPolType() startSec=" << startSec << LogIO::POST ;
    993   String poltype = "" ;
    994 
    995   if ( corrType == Stokes::I || corrType == Stokes::Q || corrType == Stokes::U || corrType == Stokes::V )
    996     poltype = "stokes" ;
    997   else if ( corrType == Stokes::XX || corrType == Stokes::YY || corrType == Stokes::XY || corrType == Stokes::YX )
    998     poltype = "linear" ;
    999   else if ( corrType == Stokes::RR || corrType == Stokes::LL || corrType == Stokes::RL || corrType == Stokes::LR )
    1000     poltype = "circular" ;
    1001   else if ( corrType == Stokes::Plinear || corrType == Stokes::Pangle )
    1002     poltype = "linpol" ;
    1003 
    1004   //double endSec = mathutil::gettimeofday_sec() ;
    1005   //os_ << "end MSFiller::getPolType() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    1006   return poltype ;
    10071801}
    10081802
     
    11641958}
    11651959
    1166 void MSFiller::fillTcal( boost::object_pool<ROTableColumn> *tpoolr )
     1960void MSFiller::fillTcal()
    11671961{
    11681962  //double startSec = mathutil::gettimeofday_sec() ;
     
    11891983  }
    11901984
    1191   Table sctab = mstable_.sysCal() ;
     1985  Table &sctab = mstable_.sysCal() ;
    11921986  if ( sctab.nrow() == 0 ) {
    11931987    os_ << "No SYSCAL rows" << LogIO::POST ;
    11941988    return ;
    11951989  }
    1196   Table sctabsel( sctab( sctab.col("ANTENNA_ID") == antenna_ ) ) ;
    1197   if ( sctabsel.nrow() == 0 ) {
     1990  ROScalarColumn<Int> antCol( sctab, "ANTENNA_ID" ) ;
     1991  Vector<Int> ant = antCol.getColumn() ;
     1992  if ( allNE( ant, antenna_ ) ) {
    11981993    os_ << "No SYSCAL rows" << LogIO::POST ;
    11991994    return ;
    12001995  }
    1201   ROArrayColumn<Float> *tmpTcalCol = new ROArrayColumn<Float>( sctabsel, colTcal_ ) ;
    1202   // return if any rows without Tcal value exists
     1996  ROTableColumn tcalCol( sctab, colTcal_ ) ;
    12031997  Bool notDefined = False ;
    1204   for ( uInt irow = 0 ; irow < sctabsel.nrow() ; irow++ ) {
    1205     if ( !tmpTcalCol->isDefined( irow ) ) {
     1998  for ( uInt irow = 0 ; irow < sctab.nrow() ; irow++ ) {
     1999    if ( ant[irow] == antenna_ && !tcalCol.isDefined( irow ) ) {
    12062000      notDefined = True ;
    12072001      break ;
     
    12102004  if ( notDefined ) {
    12112005    os_ << "No TCAL value" << LogIO::POST ;
    1212     delete tmpTcalCol ;
    12132006    table_->tcal().table().addRow(1,True) ;
    12142007    Vector<Float> defaultTcal( 1, 1.0 ) ;
     
    12172010    return ;
    12182011  }   
    1219   uInt npol = tmpTcalCol->shape( 0 )(0) ;
    1220   delete tmpTcalCol ;
    1221   //os_ << "fillTcal(): npol = " << npol << LogIO::POST ;
     2012 
     2013  static const char *cols[] = {
     2014    "ANTENNA_ID", "FEED_ID", "SPECTRAL_WINDOW_ID", "TIME",
     2015    NULL
     2016  };
     2017  static const TypeManagerImpl<Int> tmInt;
     2018  static const TypeManagerImpl<Double> tmDouble;
     2019  static const TypeManager *const tms[] = {
     2020    &tmInt, &tmInt, &tmInt, &tmDouble, NULL
     2021  };
    12222022  Table tab = table_->tcal().table() ;
    1223   ArrayColumn<Float> tcalCol( tab, "TCAL" ) ;
    1224   uInt oldnr = 0 ;
    1225   uInt newnr = 0 ;
    1226   TableRow row( tab ) ;
    1227   TableRecord &trec = row.record() ;
    1228   RecordFieldPtr<uInt> idRF( trec, "ID" ) ;
    1229   RecordFieldPtr<String> timeRF( trec, "TIME" ) ;
    1230   RecordFieldPtr< Array<Float> > tcalRF( trec, "TCAL" ) ;
    1231   TableIterator iter0( sctabsel, "FEED_ID" ) ;
    1232   while( !iter0.pastEnd() ) {
    1233     Table t0 = iter0.table() ;
    1234     Int feedId = asInt( "FEED_ID", 0, t0, tpoolr ) ;
    1235     TableIterator iter1( t0, "SPECTRAL_WINDOW_ID" ) ;
    1236     while( !iter1.pastEnd() ) {
    1237       Table t1 = iter1.table() ;
    1238       Int spwId = asInt( "SPECTRAL_WINDOW_ID", 0, t1, tpoolr ) ;
    1239       tmpTcalCol = new ROArrayColumn<Float>( t1, colTcal_ ) ;
    1240       ROScalarQuantColumn<Double> scTimeCol( t1, "TIME" ) ;
    1241       Vector<uInt> idminmax( 2, oldnr ) ;
    1242       for ( uInt irow = 0 ; irow < t1.nrow() ; irow++ ) {
    1243         String sTime = MVTime( scTimeCol(irow) ).string( MVTime::YMD ) ;
    1244         *timeRF = sTime ;
    1245         uInt idx = oldnr ;
    1246         Matrix<Float> subtcal = (*tmpTcalCol)( irow ) ;
    1247         for ( uInt ipol = 0 ; ipol < npol ; ipol++ ) {
    1248           *idRF = idx++ ;
    1249           //*tcalRF = subtcal.row( ipol ) ;
    1250           tcalRF.define( subtcal.row( ipol ) ) ;
    1251 
    1252           // commit row
    1253           tab.addRow() ;
    1254           row.put( tab.nrow()-1 ) ;
    1255 
    1256           newnr++ ;
    1257         }
    1258         idminmax[0] = oldnr ;
    1259         idminmax[1] = newnr - 1 ;
    1260         oldnr = newnr ;
    1261 
    1262         String key = keyTcal( feedId, spwId, sTime ) ;
    1263         tcalrec_.define( key, idminmax ) ;
    1264       }
    1265       delete tmpTcalCol ;
    1266       iter1++ ;
    1267     }
    1268     iter0++ ;
    1269   }
     2023  TcalVisitor visitor( sctab, tab, tcalrec_, antenna_ ) ;
     2024  visitor.setTcalColumn( colTcal_ ) ;
     2025 
     2026  traverseTable(sctab, cols, tms, &visitor);
    12702027
    12712028  //tcalrec_.print( std::cout ) ;
    12722029  //double endSec = mathutil::gettimeofday_sec() ;
    12732030  //os_ << "end MSFiller::fillTcal() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    1274 }
    1275 
    1276 uInt MSFiller::getWeatherId( uInt idx, Double wtime )
    1277 {
    1278   //double startSec = mathutil::gettimeofday_sec() ;
    1279   //os_ << "start MSFiller::getWeatherId() startSec=" << startSec << LogIO::POST ;
    1280   uInt nrow = mwTime_.size() ;
    1281   if ( nrow < 2 )
    1282     return 0 ;
    1283   uInt wid = nrow ;
    1284   if ( idx == 0 ) {
    1285     wid = 0 ;
    1286     Double tStart = mwTime_[wid]-0.5*mwInterval_[wid] ;
    1287     if ( wtime < tStart )
    1288       return wid ;
    1289   }
    1290   for ( uInt i = idx ; i < nrow-1 ; i++ ) {
    1291     Double tStart = mwTime_[i]-0.5*mwInterval_[i] ;
    1292     // use of INTERVAL column is problematic
    1293     // since there are "blank" time of weather monitoring
    1294     //Double tEnd = tStart + mwInterval_[i] ;
    1295     Double tEnd = mwTime_[i+1]-0.5*mwInterval_[i+1] ;
    1296     //os_ << "tStart = " << tStart << " dtEnd = " << tEnd-tStart << " dwtime = " << wtime-tStart << LogIO::POST ;
    1297     if ( wtime >= tStart && wtime <= tEnd ) {
    1298       wid = i ;
    1299       break ;
    1300     }
    1301   }
    1302   if ( wid == nrow ) {
    1303     uInt i = nrow - 1 ;
    1304     Double tStart = mwTime_[i-1]+0.5*mwInterval_[i-1] ;
    1305     Double tEnd = mwTime_[i]+0.5*mwInterval_[i] ;
    1306     //os_ << "tStart = " << tStart << " dtEnd = " << tEnd-tStart << " dwtime = " << wtime-tStart << LogIO::POST ;
    1307     if ( wtime >= tStart && wtime <= tEnd )
    1308       wid = i-1 ;
    1309     else
    1310       wid = i ;
    1311   }
    1312 
    1313   //if ( wid == nrow )
    1314   //os_ << LogIO::WARN << "Couldn't find correct WEATHER_ID for time " << wtime << LogIO::POST ;
    1315 
    1316   //double endSec = mathutil::gettimeofday_sec() ;
    1317   //os_ << "end MSFiller::getWeatherId() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    1318   return wid ;
    1319 }
    1320 
    1321 void MSFiller::getSysCalTime( Vector<MEpoch> &scTime, Vector<Double> &scInterval, Block<MEpoch> &tcol, Block<Int> &tidx )
    1322 {
    1323   //double startSec = mathutil::gettimeofday_sec() ;
    1324   //os_ << "start MSFiller::getSysCalTime() startSec=" << startSec << LogIO::POST ;
    1325 
    1326   if ( !isSysCal_ )
    1327     return ;
    1328 
    1329   uInt nrow = tidx.nelements() ;
    1330   if ( scTime.nelements() == 0 )
    1331     return ;
    1332   else if ( scTime.nelements() == 1 ) {
    1333     tidx[0] = 0 ;
    1334     return ;
    1335   }
    1336   uInt scnrow = scTime.nelements() ;
    1337   uInt idx = 0 ;
    1338   const Double half = 0.5e0 ;
    1339   // execute  binary search
    1340   idx = binarySearch( scTime, tcol[0].get( "s" ).getValue() ) ;
    1341   if ( idx != 0 )
    1342     idx -= 1 ;
    1343   for ( uInt i = 0 ; i < nrow ; i++ ) {
    1344     Double t = tcol[i].get( "s" ).getValue() ;
    1345     Double tsc = scTime[0].get( "s" ).getValue() ;
    1346     if ( t < tsc ) {
    1347       tidx[i] = 0 ;
    1348       continue ;
    1349     }
    1350     for ( uInt j = idx ; j < scnrow-1 ; j++ ) {
    1351       Double tsc1 = scTime[j].get( "s" ).getValue() ;
    1352       Double dt1 = scInterval[j] ;
    1353       Double tsc2 = scTime[j+1].get( "s" ).getValue() ;
    1354       Double dt2 = scInterval[j+1] ;
    1355       if ( t > tsc1-half*dt1 && t <= tsc2-half*dt2 ) {
    1356         tidx[i] = j ;
    1357         idx = j ;
    1358         break ;
    1359       }
    1360     }
    1361     if ( tidx[i] == -1 ) {
    1362 //       Double tsc = scTime[scnrow-1].get( "s" ).getValue() ;
    1363 //       Double dt = scInterval[scnrow-1] ;
    1364 //       if ( t <= tsc+0.5*dt ) {
    1365 //         tidx[i] = scnrow-1 ;
    1366 //       }
    1367       tidx[i] = scnrow-1 ;
    1368     }
    1369   }
    1370   //double endSec = mathutil::gettimeofday_sec() ;
    1371   //os_ << "end MSFiller::getSysCalTime() endSec=" << endSec << " (" << endSec-startSec << "sec) scnrow = " << scnrow << " tcol.nelements = " << tcol.nelements() << LogIO::POST ;
    1372   return ;
    1373 }
    1374 
    1375 Block<uInt> MSFiller::getTcalId( Int fid, Int spwid, MEpoch &t )
    1376 {
    1377   //double startSec = mathutil::gettimeofday_sec() ;
    1378   //os_ << "start MSFiller::getTcalId() startSec=" << startSec << LogIO::POST ;
    1379   //if ( table_->tcal().table().nrow() == 0 ) {
    1380   if ( !isSysCal_ ) {
    1381     os_ << "No TCAL rows" << LogIO::POST ;
    1382     Block<uInt> tcalids( 4, 0 ) ;
    1383     return  tcalids ;
    1384   }   
    1385   //String sctime = MVTime( Quantum<Double>(t,"s") ).string(MVTime::YMD) ;
    1386   String sctime = MVTime( t.getValue() ).string(MVTime::YMD) ;
    1387   String key = keyTcal( fid, spwid, sctime ) ;
    1388   if ( !tcalrec_.isDefined( key ) ) {
    1389     os_ << "No TCAL rows" << LogIO::POST ;
    1390     Block<uInt> tcalids( 4, 0 ) ;
    1391     return tcalids ;
    1392   }
    1393   Vector<uInt> ids = tcalrec_.asArrayuInt( key ) ;
    1394   uInt npol = ids[1] - ids[0] + 1 ;
    1395   Block<uInt> tcalids( npol ) ;
    1396   tcalids[0] = ids[0] ;
    1397   tcalids[1] = ids[1] ;
    1398   for ( uInt ipol = 2 ; ipol < npol ; ipol++ )
    1399     tcalids[ipol] = ids[0] + ipol - 1 ;
    1400 
    1401   //double endSec = mathutil::gettimeofday_sec() ;
    1402   //os_ << "end MSFiller::getTcalId() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    1403   return tcalids ;
    1404 }
    1405 
    1406 uInt MSFiller::getDirection( uInt idx,
    1407                              Vector<Double> &dir,
    1408                              Vector<Double> &srate,
    1409                              String &ref,
    1410                              Vector<Double> &tcol,
    1411                              ROArrayColumn<Double> &dcol,
    1412                              Double t )
    1413 {
    1414   //double startSec = mathutil::gettimeofday_sec() ;
    1415   //os_ << "start MSFiller::getDirection1() startSec=" << startSec << LogIO::POST ;
    1416   //double time0 = mathutil::gettimeofday_sec() ;
    1417   //os_ << "start getDirection 1st stage startSec=" << time0 << LogIO::POST ;
    1418   // assume that cols is sorted by TIME
    1419   Bool doInterp = False ;
    1420   uInt nrow = dcol.nrow() ;
    1421   if ( nrow == 0 )
    1422     return 0 ;
    1423   if ( idx == 0 ) {
    1424     uInt nrowb = 1000 ;
    1425     if ( nrow > nrowb ) {
    1426       uInt nblock = nrow / nrowb + 1 ;
    1427       for ( uInt iblock = 0 ; iblock < nblock ; iblock++ ) {
    1428         uInt high = min( nrowb, nrow-iblock*nrowb ) ;
    1429 
    1430         if ( tcol( high-1 ) < t ) {
    1431           idx = iblock * nrowb ;
    1432           continue ;
    1433         }
    1434 
    1435         Slice slice( iblock*nrowb, nrowb ) ;
    1436         Vector<Double> tarr = tcol( slice ) ;
    1437 
    1438         uInt bidx = binarySearch( tarr, t ) ;
    1439 
    1440         idx = iblock * nrowb + bidx ;
    1441         break ;
    1442       }
    1443     }
    1444     else {
    1445       idx = binarySearch( tcol, t ) ;
    1446     }
    1447   }
    1448   //double time1 = mathutil::gettimeofday_sec() ;
    1449   //os_ << "end getDirection 1st stage endSec=" << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    1450   // ensure that tcol(idx) < t
    1451   //os_ << "tcol(idx) = " << tcol(idx).get("s").getValue() << " t = " << t << " diff = " << tcol(idx).get("s").getValue()-t << endl ;
    1452   //time0 = mathutil::gettimeofday_sec() ;
    1453   //os_ << "start getDirection 2nd stage startSec=" << time0 << LogIO::POST ;
    1454   //while( tcol( idx ) * factor > t && idx > 0 )
    1455   while( tcol[idx] > t && idx > 0 )
    1456     idx-- ;
    1457   //os_ << "idx = " << idx << LogIO::POST ;
    1458 
    1459   // index search
    1460   for ( uInt i = idx ; i < nrow ; i++ ) {
    1461     Double tref = tcol[i] ;
    1462     if ( tref == t ) {
    1463       idx = i ;
    1464       break ;
    1465     }
    1466     else if ( tref > t ) {
    1467       if ( i == 0 ) {
    1468         idx = i ;
    1469       }
    1470       else {
    1471         idx = i-1 ;
    1472         doInterp = True ;
    1473       }
    1474       break ;
    1475     }
    1476     else {
    1477       idx = nrow - 1 ;
    1478     }
    1479   }
    1480   //time1 = mathutil::gettimeofday_sec() ;
    1481   //os_ << "end getDirection 2nd stage endSec=" << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    1482   //os_ << "searched idx = " << idx << LogIO::POST ;
    1483 
    1484   //time0 = mathutil::gettimeofday_sec() ;
    1485   //os_ << "start getDirection 3rd stage startSec=" << time0 << LogIO::POST ;
    1486   //os_ << "dmcol(idx).shape() = " << dmcol(idx).shape() << LogIO::POST ;
    1487   //IPosition ip( dmcol(idx).shape().nelements(), 0 ) ;
    1488   IPosition ip( dcol(idx).shape().nelements(), 0 ) ;
    1489   //os_ << "ip = " << ip << LogIO::POST ;
    1490   //ref = dmcol(idx)(ip).getRefString() ;
    1491   TableRecord trec = dcol.keywordSet() ;
    1492   Record rec = trec.asRecord( "MEASINFO" ) ;
    1493   ref = rec.asString( "Ref" ) ;
    1494   //os_ << "ref = " << ref << LogIO::POST ;
    1495   if ( doInterp ) {
    1496     //os_ << "do interpolation" << LogIO::POST ;
    1497     //os_ << "dcol(idx).shape() = " << dcol(idx).shape() << LogIO::POST ;
    1498     Double tref0 = tcol[idx] ;
    1499     Double tref1 = tcol[idx+1] ;
    1500     Matrix<Double> mdir0 = dcol( idx ) ;
    1501     Matrix<Double> mdir1 = dcol( idx+1 ) ;
    1502     Vector<Double> dir0 = mdir0.column( 0 ) ;
    1503     //os_ << "dir0 = " << dir0 << LogIO::POST ;
    1504     Vector<Double> dir1 = mdir1.column( 0 ) ;
    1505     //os_ << "dir1 = " << dir1 << LogIO::POST ;
    1506     Double dt0 = t - tref0 ;
    1507     Double dt1 = tref1 - t ;
    1508     dir.reference( (dt0*dir1+dt1*dir0)/(dt0+dt1) ) ;
    1509     if ( mdir0.ncolumn() > 1 ) {
    1510       if ( dt0 >= dt1 )
    1511         srate.reference( mdir0.column( 1 ) ) ;
    1512       else
    1513         srate.reference( mdir1.column( 1 ) ) ;
    1514     }
    1515     //os_ << "dir = " << dir << LogIO::POST ;
    1516   }
    1517   else {
    1518     //os_ << "no interpolation" << LogIO::POST ;
    1519     Matrix<Double> mdir0 = dcol( idx ) ;
    1520     dir.reference( mdir0.column( 0 ) ) ;
    1521     if ( mdir0.ncolumn() > 1 )
    1522       srate.reference( mdir0.column( 1 ) ) ;
    1523   }
    1524 
    1525   //time1 = mathutil::gettimeofday_sec() ;
    1526   //os_ << "end getDirection 3rd stage endSec=" << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
    1527   //double endSec = mathutil::gettimeofday_sec() ;
    1528   //os_ << "end MSFiller::getDirection1() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    1529   return idx ;
    1530 }
    1531 
    1532 String MSFiller::keyTcal( Int feedid, Int spwid, String stime )
    1533 {
    1534   String sfeed = "FEED" + String::toString( feedid ) ;
    1535   String sspw = "SPW" + String::toString( spwid ) ;
    1536   return sfeed+":"+sspw+":"+stime ;
    1537 }
    1538 
    1539 uInt MSFiller::binarySearch( Vector<MEpoch> &timeList, Double target )
    1540 {
    1541   Int low = 0 ;
    1542   Int high = timeList.nelements() ;
    1543   uInt idx = 0 ;
    1544 
    1545   while ( low <= high ) {
    1546     idx = (Int)( 0.5 * ( low + high ) ) ;
    1547     Double t = timeList[idx].get( "s" ).getValue() ;
    1548     if ( t < target )
    1549       low = idx + 1 ;
    1550     else if ( t > target )
    1551       high = idx - 1 ;
    1552     else {
    1553       return idx ;
    1554     }
    1555   }
    1556 
    1557   idx = max( 0, min( low, high ) ) ;
    1558 
    1559   return idx ;
    1560 }
    1561 
    1562 uInt MSFiller::binarySearch( Vector<Double> &timeList, Double target )
    1563 {
    1564   Int low = 0 ;
    1565   Int high = timeList.nelements() ;
    1566   uInt idx = 0 ;
    1567 
    1568   while ( low <= high ) {
    1569     idx = (Int)( 0.5 * ( low + high ) ) ;
    1570     Double t = timeList[idx] ;
    1571     if ( t < target )
    1572       low = idx + 1 ;
    1573     else if ( t > target )
    1574       high = idx - 1 ;
    1575     else {
    1576       return idx ;
    1577     }
    1578   }
    1579 
    1580   idx = max( 0, min( low, high ) ) ;
    1581 
    1582   return idx ;
    15832031}
    15842032
     
    16032051}
    16042052
    1605 void MSFiller::reshapeSpectraAndFlagtra( Cube<Float> &sp,
    1606                                          Cube<Bool> &fl,
    1607                                          Table &tab,
    1608                                          Int &npol,
    1609                                          Int &nchan,
    1610                                          Int &nrow,
    1611                                          Vector<Int> &corrtype )
    1612 {
    1613   //double startSec = mathutil::gettimeofday_sec() ;
    1614   //os_ << "start MSFiller::reshapeSpectraAndFlagtra() startSec=" << startSec << LogIO::POST ; 
    1615   if ( isFloatData_ ) {
    1616     ROArrayColumn<Bool> mFlagCol( tab, "FLAG" ) ;
    1617     ROArrayColumn<Float> mFloatDataCol( tab, "FLOAT_DATA" ) ;
    1618     mFloatDataCol.getColumn( sp ) ;
    1619     mFlagCol.getColumn( fl ) ;
    1620   }
    1621   else if ( isData_ ) {
    1622     sp.resize( npol, nchan, nrow ) ;
    1623     fl.resize( npol, nchan, nrow ) ;
    1624     ROArrayColumn<Bool> mFlagCol( tab, "FLAG" ) ;
    1625     ROArrayColumn<Complex> mDataCol( tab, "DATA" ) ;
    1626     if ( npol < 3 ) {
    1627       Cube<Float> tmp = ComplexToReal( mDataCol.getColumn() ) ;
    1628       IPosition start( 3, 0, 0, 0 ) ;
    1629       IPosition end( 3, 2*npol-1, nchan-1, nrow-1 ) ;
    1630       IPosition inc( 3, 2, 1, 1 ) ;
    1631       sp = tmp( start, end, inc ) ;
    1632       fl = mFlagCol.getColumn() ;
    1633     }
    1634     else {
    1635       for ( Int irow = 0 ; irow < nrow ; irow++ ) {
    1636         Bool crossOK = False ;
    1637         Matrix<Complex> mSp = mDataCol( irow ) ;
    1638         Matrix<Bool> mFl = mFlagCol( irow ) ;
    1639         Matrix<Float> spxy = sp.xyPlane( irow ) ;
    1640         Matrix<Bool> flxy = fl.xyPlane( irow ) ;
    1641         for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
    1642           if ( corrtype[ipol] == Stokes::XY || corrtype[ipol] == Stokes::YX
    1643                || corrtype[ipol] == Stokes::RL || corrtype[ipol] == Stokes::LR ) {
    1644             if ( !crossOK ) {
    1645               Vector<Float> tmp = ComplexToReal( mSp.row( ipol ) ) ;
    1646               IPosition start( 1, 0 ) ;
    1647               IPosition end( 1, 2*nchan-1 ) ;
    1648               IPosition inc( 1, 2 ) ;
    1649               spxy.row( ipol ) = tmp( start, end, inc ) ;
    1650               flxy.row( ipol ) = mFl.row( ipol ) ;
    1651               start = IPosition( 1, 1 ) ;
    1652               spxy.row( ipol+1 ) = tmp( start, end, inc ) ;
    1653               flxy.row( ipol+1 ) = mFl.row( ipol ) ;
    1654               if ( corrtype[ipol] == Stokes::YX || corrtype[ipol] == Stokes::LR ) {
    1655                 spxy.row( ipol+1 ) = spxy.row( ipol+1 ) * (Float)-1.0 ;
    1656               }
    1657               crossOK = True ;
    1658             }
    1659           }
    1660           else {
    1661             Vector<Float> tmp = ComplexToReal( mSp.row( ipol ) ) ;
    1662             IPosition start( 1, 0 ) ;
    1663             IPosition end( 1, 2*nchan-1 ) ;
    1664             IPosition inc( 1, 2 ) ;
    1665             spxy.row( ipol ) = tmp( start, end, inc ) ;
    1666             flxy.row( ipol ) = mFl.row( ipol ) ;
    1667           }
    1668         }
    1669       }
    1670     }
    1671   }
    1672   //double endSec = mathutil::gettimeofday_sec() ;
    1673   //os_ << "end MSFiller::reshapeSpectraAndFlagtra() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    1674 }
    1675 
    1676 uInt MSFiller::getDirection( uInt idx,
    1677                              Vector<Double> &dir,
    1678                              Vector<Double> &azel,
    1679                              Vector<Double> &srate,
    1680                              Vector<Double> &ptcol,
    1681                              ROArrayColumn<Double> &pdcol,
    1682                              MEpoch &t,
    1683                              MPosition &antpos )
    1684 {
    1685   //double startSec = mathutil::gettimeofday_sec() ;
    1686   //os_ << "start MSFiller::getDirection2() startSec=" << startSec << LogIO::POST ; 
    1687   String refString ;
    1688   MDirection::Types dirType ;
    1689   uInt diridx = getDirection( idx, dir, srate, refString, ptcol, pdcol, t.get("s").getValue() ) ;
    1690   MDirection::getType( dirType, refString ) ;
    1691   MeasFrame mf( t, antpos ) ;
    1692   if ( refString == "J2000" ) {
    1693     MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZEL, mf ) ) ;
    1694     azel = toazel( dir ).getAngle("rad").getValue() ;
    1695   }
    1696   else if ( refString(0,4) == "AZEL" ) {
    1697     azel = dir.copy() ;
    1698     MDirection::Convert toj2000( dirType, MDirection::Ref( MDirection::J2000, mf ) ) ;
    1699     dir = toj2000( dir ).getAngle("rad").getValue() ;
    1700   }
    1701   else {
    1702     MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZEL, mf ) ) ;
    1703     azel = toazel( dir ).getAngle("rad").getValue() ;
    1704     MDirection::Convert toj2000( dirType, MDirection::Ref( MDirection::J2000, mf ) ) ;
    1705     dir = toj2000( dir ).getAngle("rad").getValue() ;
    1706   }
    1707   if ( srate.size() == 0 ) {
    1708     srate.resize( 2 ) ;
    1709     srate = 0.0 ;
    1710   }
    1711   //double endSec = mathutil::gettimeofday_sec() ;
    1712   //os_ << "end MSFiller::getDirection2() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    1713   return diridx ;
    1714 }
    1715 
    1716 void MSFiller::getSourceDirection( Vector<Double> &dir,
    1717                                    Vector<Double> &azel,
    1718                                    Vector<Double> &srate,
    1719                                    MEpoch &t,
    1720                                    MPosition &antpos,
    1721                                    Vector<MDirection> &srcdir )
    1722 {
    1723   //double startSec = mathutil::gettimeofday_sec() ;
    1724   //os_ << "start MSFiller::getSourceDirection() startSec=" << startSec << LogIO::POST ;
    1725   Vector<Double> defaultDir = srcdir[0].getAngle( "rad" ).getValue() ;
    1726   if ( srcdir.nelements() > 1 )
    1727     srate = srcdir[1].getAngle( "rad" ).getValue() ;
    1728   String ref = srcdir[0].getRefString() ;
    1729   MDirection::Types dirType ;
    1730   MDirection::getType( dirType, ref ) ;
    1731   MeasFrame mf( t, antpos ) ;
    1732   if ( ref != "J2000" ) {
    1733     MDirection::Convert toj2000( dirType, MDirection::Ref( MDirection::J2000, mf ) ) ;
    1734     dir = toj2000( defaultDir ).getAngle("rad").getValue() ;
    1735   }
    1736   else
    1737     dir = defaultDir ;
    1738   MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZELGEO, mf ) ) ;
    1739   azel = toazel( defaultDir ).getAngle("rad").getValue() ;
    1740   //double endSec = mathutil::gettimeofday_sec() ;
    1741   //os_ << "end MSFiller::getSourceDirection() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    1742 }
    1743 
    17442053void MSFiller::initHeader( STHeader &header )
    17452054{
     
    17522061  header.obstype = "" ;
    17532062  header.antennaname = "" ;
    1754   header.antennaposition.resize( 0 ) ;
     2063  header.antennaposition.resize( 3 ) ;
    17552064  header.equinox = 0.0 ;
    17562065  header.freqref = "" ;
     
    17632072}
    17642073
    1765 String MSFiller::asString( String name,
    1766                            uInt idx,
    1767                            Table tab,
    1768                            boost::object_pool<ROTableColumn> *pool )
    1769 {
    1770   ROTableColumn *col = pool->construct( tab, name ) ;
    1771   String v = col->asString( idx ) ;
    1772   pool->destroy( col ) ;
    1773   return v ;
    1774 }
    1775 
    1776 Bool MSFiller::asBool( String name,
    1777                          uInt idx,
    1778                          Table &tab,
    1779                          boost::object_pool<ROTableColumn> *pool )
    1780 {
    1781   ROTableColumn *col = pool->construct( tab, name ) ;
    1782   Bool v = col->asBool( idx ) ;
    1783   pool->destroy( col ) ;
    1784   return v ;
    1785 }
    1786 
    1787 uInt MSFiller::asuInt( String name,
    1788                          uInt idx,
    1789                          Table &tab,
    1790                          boost::object_pool<ROTableColumn> *pool )
    1791 {
    1792   ROTableColumn *col = pool->construct( tab, name ) ;
    1793   uInt v = col->asuInt( idx ) ;
    1794   pool->destroy( col ) ;
    1795   return v ;
    1796 }
    1797 
    1798 Int MSFiller::asInt( String name,
    1799                         uInt idx,
    1800                         Table &tab,
    1801                         boost::object_pool<ROTableColumn> *pool )
    1802 {
    1803   ROTableColumn *col = pool->construct( tab, name ) ;
    1804   Int v = col->asInt( idx ) ;
    1805   pool->destroy( col ) ;
    1806   return v ;
    1807 }
    1808 
    1809 Float MSFiller::asFloat( String name,
    1810                           uInt idx,
    1811                           Table &tab,
    1812                           boost::object_pool<ROTableColumn> *pool )
    1813 {
    1814   ROTableColumn *col = pool->construct( tab, name ) ;
    1815   Float v = col->asfloat( idx ) ;
    1816   pool->destroy( col ) ;
    1817   return v ;
    1818 }
    1819 
    1820 Double MSFiller::asDouble( String name,
    1821                            uInt idx,
    1822                            Table &tab,
    1823                            boost::object_pool<ROTableColumn> *pool )
    1824 {
    1825   ROTableColumn *col = pool->construct( tab, name ) ;
    1826   Double v = col->asdouble( idx ) ;
    1827   pool->destroy( col ) ;
    1828   return v ;
    1829 }
    1830 
    1831 void MSFiller::sourceInfo( Int sourceId,
    1832                            Int spwId,
    1833                            String &name,
    1834                            MDirection &direction,
    1835                            Vector<casa::Double> &properMotion,
    1836                            Vector<casa::Double> &restFreqs,
    1837                            Vector<casa::String> &transitions,
    1838                            Vector<casa::Double> &sysVels,
    1839                            boost::object_pool<ROTableColumn> *tpoolr )
    1840 {
    1841   //double startSec = mathutil::gettimeofday_sec() ;
    1842   //os_ << "start MSFiller::sourceInfo() startSec=" << startSec << LogIO::POST ;
    1843 
    1844   MSSource srctab = mstable_.source() ;
    1845   MSSource srctabSel = srctab( srctab.col("SOURCE_ID") == sourceId && srctab.col("SPECTRAL_WINDOW_ID") == spwId ) ;
    1846   if ( srctabSel.nrow() == 0 ) {
    1847     srctabSel = srctab( srctab.col("SOURCE_ID") == sourceId && srctab.col("SPECTRAL_WINDOW_ID") == -1 ) ;
    1848   }
    1849   Int numLines = 0 ;
    1850   if ( srctabSel.nrow() > 0 ) {
    1851     // source name
    1852     name = asString( "NAME", 0, srctabSel, tpoolr ) ;
    1853    
    1854     // source proper motion
    1855     ROArrayColumn<Double> roArrDCol( srctabSel, "PROPER_MOTION" ) ;
    1856     properMotion = roArrDCol( 0 ) ;
    1857    
    1858     // source direction as MDirection object
    1859     ROScalarMeasColumn<MDirection> tmpMeasCol( srctabSel, "DIRECTION" ) ;
    1860     direction = tmpMeasCol( 0 ) ;
    1861    
    1862     // number of lines
    1863     numLines = asInt( "NUM_LINES", 0, srctabSel, tpoolr ) ;
    1864   }
    1865   else {
    1866     name = "" ;
    1867     properMotion = Vector<Double>( 2, 0.0 ) ;
    1868     direction = MDirection( Quantum<Double>(0.0,Unit("rad")), Quantum<Double>(0.0,Unit("rad")) ) ;
    1869   }
    1870 
    1871   restFreqs.resize( numLines ) ;
    1872   transitions.resize( numLines ) ;
    1873   sysVels.resize( numLines ) ;
    1874   if ( numLines > 0 ) {
    1875     if ( srctabSel.tableDesc().isColumn( "REST_FREQUENCY" ) ) {
    1876       ROArrayQuantColumn<Double> quantArrCol( srctabSel, "REST_FREQUENCY" ) ;
    1877       Array< Quantum<Double> > qRestFreqs = quantArrCol( 0 ) ;
    1878       for ( int i = 0 ; i < numLines ; i++ ) {
    1879         restFreqs[i] = qRestFreqs( IPosition( 1, i ) ).getValue( "Hz" ) ;
    1880       }
    1881     }
    1882     //os_ << "restFreqs = " << restFreqs << LogIO::POST ;
    1883     if ( srctabSel.tableDesc().isColumn( "TRANSITION" ) ) {
    1884       ROArrayColumn<String> transitionCol( srctabSel, "TRANSITION" ) ;
    1885       if ( transitionCol.isDefined( 0 ) )
    1886         transitions = transitionCol( 0 ) ;
    1887       //os_ << "transitionNameCol.nrow() = " << transitionCol.nrow() << LogIO::POST ;
    1888     }
    1889     if ( srctabSel.tableDesc().isColumn( "SYSVEL" ) ) {
    1890       ROArrayColumn<Double> roArrDCol( srctabSel, "SYSVEL" ) ;
    1891       sysVels = roArrDCol( 0 ) ;
    1892     }
    1893   }
    1894  
    1895   //double endSec = mathutil::gettimeofday_sec() ;
    1896   //os_ << "end MSFiller::sourceInfo() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    1897 }
    1898 
    1899 void MSFiller::spectralSetup( Int spwId,
    1900                               MEpoch &me,
    1901                               MPosition &mp,
    1902                               MDirection &md,
    1903                               Double &refpix,
    1904                               Double &refval,
    1905                               Double &increment,
    1906                               Int &nchan,
    1907                               String &freqref,
    1908                               Double &reffreq,
    1909                               Double &bandwidth,
    1910                               boost::object_pool<ROTableColumn> *tpoolr )
    1911 {
    1912   //double startSec = mathutil::gettimeofday_sec() ;
    1913   //os_ << "start MSFiller::spectralSetup() startSec=" << startSec << LogIO::POST ;
    1914 
    1915   MSSpectralWindow spwtab = mstable_.spectralWindow() ;
    1916   MeasFrame mf( me, mp, md ) ;
    1917   MFrequency::Types freqRef = MFrequency::castType( (uInt)asInt( "MEAS_FREQ_REF", spwId, spwtab, tpoolr ) ) ;
    1918   Bool even = False ;
    1919   if ( (nchan/2)*2 == nchan ) even = True ;
    1920   ROScalarQuantColumn<Double> tmpQuantCol( spwtab, "TOTAL_BANDWIDTH" ) ;
    1921   Double totbw = tmpQuantCol( spwId ).getValue( "Hz" ) ;
    1922   if ( nchan != 4 )
    1923     bandwidth = max( bandwidth, totbw ) ;
    1924   if ( freqref == "" && nchan != 4)
    1925     //sdh.freqref = MFrequency::showType( freqRef ) ;
    1926     freqref = "LSRK" ;
    1927   if ( reffreq == -1.0 && nchan != 4 ) {
    1928     tmpQuantCol.attach( spwtab, "REF_FREQUENCY" ) ;
    1929     Quantum<Double> qreffreq = tmpQuantCol( spwId ) ;
    1930     if ( freqRef == MFrequency::LSRK ) {
    1931       reffreq = qreffreq.getValue("Hz") ;
    1932     }
    1933     else {
    1934       MFrequency::Convert tolsr( freqRef, MFrequency::Ref( MFrequency::LSRK, mf ) ) ;
    1935       reffreq = tolsr( qreffreq ).get("Hz").getValue() ;
    1936     }
    1937   }
    1938   Int refchan = nchan / 2 ;
    1939   IPosition refip( 1, refchan ) ;
    1940   refpix = 0.5*(nchan-1) ;
    1941   refval = 0.0 ;
    1942   ROArrayQuantColumn<Double> sharedQDArrCol( spwtab, "CHAN_WIDTH" ) ;
    1943   ROTableColumn netSidebandCol( spwtab, "NET_SIDEBAND" ) ;
    1944   Int netSideband = netSidebandCol.asInt( spwId ) ;
    1945   increment = sharedQDArrCol( spwId )( refip ).getValue( "Hz" ) ;
    1946   //           os_ << "nchan = " << nchan << " refchan = " << refchan << "(even=" << even << ") refpix = " << refpix << LogIO::POST ;
    1947   sharedQDArrCol.attach( spwtab, "CHAN_FREQ" ) ;
    1948   Vector< Quantum<Double> > chanFreqs = sharedQDArrCol( spwId ) ;
    1949   if ( ( nchan > 1 &&
    1950          chanFreqs[0].getValue("Hz") > chanFreqs[1].getValue("Hz")  )
    1951        || ( nchan == 1 && netSideband == 1 ) ) 
    1952     increment *= -1.0 ;
    1953   if ( freqRef == MFrequency::LSRK ) {
    1954     if ( even ) {
    1955       IPosition refip0( 1, refchan-1 ) ;
    1956       Double refval0 = chanFreqs(refip0).getValue("Hz") ;
    1957       Double refval1 = chanFreqs(refip).getValue("Hz") ;
    1958       refval = 0.5 * ( refval0 + refval1 ) ;
    1959     }
    1960     else {
    1961       refval = chanFreqs(refip).getValue("Hz") ;
    1962     }
    1963   }
    1964   else {
    1965     MFrequency::Convert tolsr( freqRef, MFrequency::Ref( MFrequency::LSRK, mf ) ) ;
    1966     if ( even ) {
    1967       IPosition refip0( 1, refchan-1 ) ;
    1968       Double refval0 = chanFreqs(refip0).getValue("Hz") ;
    1969       Double refval1 = chanFreqs(refip).getValue("Hz") ;
    1970       refval = 0.5 * ( refval0 + refval1 ) ;
    1971       refval = tolsr( refval ).get("Hz").getValue() ;
    1972     }
    1973     else {
    1974       refval = tolsr( chanFreqs(refip) ).get("Hz").getValue() ;
    1975     }
    1976   }
    1977  
    1978   //double endSec = mathutil::gettimeofday_sec() ;
    1979   //os_ << "end MSFiller::spectralSetup() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    1980 }
    1981 
    1982 } ;
    1983 
     2074};
Note: See TracChangeset for help on using the changeset viewer.