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/MSWriter.cpp

    r2259 r2291  
    1111//
    1212//
     13#include <assert.h>
    1314
    1415#include <casa/OS/File.h>
     
    1718#include <casa/OS/SymLink.h>
    1819#include <casa/BasicSL/String.h>
    19 #include <casa/Containers/RecordField.h>
    2020#include <casa/Arrays/Cube.h>
    2121
     
    3939#include "STTcal.h"
    4040#include "MathUtils.h"
    41 
    42 // #include <ctime>
    43 // #include <sys/time.h>
    44 
     41#include "TableTraverse.h"
    4542
    4643using namespace casa ;
     
    4845
    4946namespace asap {
    50 // double MSWriter::gettimeofday_sec()
    51 // {
    52 //   struct timeval tv ;
    53 //   gettimeofday( &tv, NULL ) ;
    54 //   return tv.tv_sec + (double)tv.tv_usec*1.0e-6 ;
    55 // }
     47
     48class PolarizedComponentHolder {
     49public:
     50  PolarizedComponentHolder()
     51    : nchan(0),
     52      maxnpol(4)
     53  {
     54    reset() ;
     55  }
     56  PolarizedComponentHolder( uInt n )
     57    : nchan(n),
     58      maxnpol(4)
     59  {
     60    reset() ;
     61  }
     62
     63  void reset()
     64  {
     65    npol = 0 ;
     66    data.clear() ;
     67    flag.clear() ;
     68    flagrow = False ;
     69    polnos.resize() ;
     70  }
     71
     72  void accumulate( uInt id, Vector<Float> sp, Vector<Bool> fl, Bool flr )
     73  {
     74    map< uInt,Vector<Float> >::iterator itr = data.find( id ) ;
     75    if ( id < maxnpol && itr == data.end() ) {
     76      addPol( id ) ;
     77      accumulateData( id, sp ) ;
     78      accumulateFlag( id, fl ) ;
     79      accumulateFlagRow( flr ) ;
     80      npol++ ;
     81    }
     82  }
     83
     84  void setNchan( uInt n ) { nchan = n ; }
     85  uInt nPol() { return npol ; }
     86  uInt nChan() { return nchan ; }
     87  Vector<uInt> polNos() { return polnos ; }
     88  Vector<Float> getWeight() { return Vector<Float>( npol, 1.0 ) ; }
     89  Vector<Float> getSigma() { return Vector<Float>( npol, 1.0 ) ; }
     90  Bool getFlagRow() { return flagrow ; }
     91  Cube<Bool> getFlagCategory() { return Cube<Bool>( npol, nchan, 1, False ) ; }
     92  Matrix<Float> getData()
     93  {
     94    Matrix<Float> v( npol, nchan ) ;
     95    for ( map< uInt,Vector<Float> >::iterator i = data.begin() ; i != data.end() ; i++ ) {
     96      v.row( i->first ) =  i->second ;
     97    }
     98    return v ;
     99  }
     100  Matrix<Bool> getFlag()
     101  {
     102    Matrix<Bool> v( npol, nchan ) ;
     103    for ( map< uInt,Vector<Bool> >::iterator i = flag.begin() ; i != flag.end() ; i++ ) {
     104      v.row( i->first ) = i->second ;
     105    }
     106    return v ;
     107  }
     108  Matrix<Complex> getComplexData()
     109  {
     110    Matrix<Complex> v( npol, nchan ) ;
     111    Matrix<Float> dummy( 2, nchan, 0.0 ) ;
     112    map< uInt,Vector<Float> >::iterator itr0 = data.find( 0 ) ;
     113    map< uInt,Vector<Float> >::iterator itr1 = data.find( 1 ) ;
     114    if ( itr0 != data.end() ) {
     115      dummy.row( 0 ) = itr0->second ;
     116      v.row( 0 ) = RealToComplex( dummy ) ;
     117    }
     118    if ( itr1 != data.end() ) {
     119      dummy.row( 0 ) = itr1->second ;
     120      v.row( npol-1 ) = RealToComplex( dummy ) ;
     121    }
     122    itr0 = data.find( 2 ) ;
     123    itr1 = data.find( 3 ) ;
     124    if ( itr0 != data.end() && itr1 != data.end() ) {
     125      dummy.row( 0 ) = itr0->second ;
     126      dummy.row( 1 ) = itr1->second ;
     127      v.row( 1 ) = RealToComplex( dummy ) ;
     128      v.row( 2 ) = conj( v.row( 1 ) ) ;
     129    }
     130    return v ;
     131  }
     132
     133  Matrix<Bool> getComplexFlag()
     134  {
     135    Matrix<Bool> tmp = getFlag() ;
     136    Matrix<Bool> v( npol, nchan ) ;
     137    v.row( 0 ) = tmp.row( 0 ) ;
     138    if ( npol == 2 ) {
     139      v.row( npol-1 ) = tmp.row( 1 ) ;
     140    }
     141    else if ( npol > 2 ) {
     142      v.row( npol-1 ) = tmp.row( 1 ) ;
     143      v.row( 1 ) = tmp.row( 2 ) || tmp.row( 3 ) ;
     144      v.row( 2 ) = v.row( 1 ) ;
     145    }
     146    return v ;
     147  }
     148 
     149private:
     150  void accumulateData( uInt &id, Vector<Float> &v )
     151  {
     152    data.insert( pair< uInt,Vector<Float> >( id, v ) ) ;
     153  }
     154    void accumulateFlag( uInt &id, Vector<Bool> &v )
     155  {
     156    flag.insert( pair< uInt,Vector<Bool> >( id, v ) ) ;
     157  }
     158  void accumulateFlagRow( Bool &v )
     159  {
     160    flagrow |= v ;
     161  }
     162  void addPol( uInt id )
     163  {
     164    uInt i = polnos.nelements() ;
     165    polnos.resize( i+1, True ) ;
     166    polnos[i] = id ;
     167  }
     168
     169  uInt nchan;
     170  const uInt maxnpol;
     171  uInt npol;
     172  Vector<uInt> polnos;
     173
     174  map< uInt,Vector<Float> > data;
     175  map< uInt,Vector<Bool> > flag;
     176  Bool flagrow;
     177};
     178
     179class BaseMSWriterVisitor: public TableVisitor {
     180  const String *lastFieldName;
     181  uInt lastRecordNo;
     182  uInt lastBeamNo, lastScanNo, lastIfNo;
     183  Int lastSrcType;
     184  uInt lastCycleNo;
     185  Double lastTime;
     186  Int lastPolNo;
     187protected:
     188  const Table &table;
     189  uInt count;
     190public:
     191  BaseMSWriterVisitor(const Table &table)
     192    : table(table)
     193  {
     194    static const String dummy;
     195    lastFieldName = &dummy;
     196    count = 0;
     197  }
     198 
     199  virtual void enterFieldName(const uInt recordNo, const String &columnValue) {
     200  }
     201  virtual void leaveFieldName(const uInt recordNo, const String &columnValue) {
     202  }
     203  virtual void enterBeamNo(const uInt recordNo, uInt columnValue) { }
     204  virtual void leaveBeamNo(const uInt recordNo, uInt columnValue) { }
     205  virtual void enterScanNo(const uInt recordNo, uInt columnValue) { }
     206  virtual void leaveScanNo(const uInt recordNo, uInt columnValue) { }
     207  virtual void enterIfNo(const uInt recordNo, uInt columnValue) { }
     208  virtual void leaveIfNo(const uInt recordNo, uInt columnValue) { }
     209  virtual void enterSrcType(const uInt recordNo, Int columnValue) { }
     210  virtual void leaveSrcType(const uInt recordNo, Int columnValue) { }
     211  virtual void enterCycleNo(const uInt recordNo, uInt columnValue) { }
     212  virtual void leaveCycleNo(const uInt recordNo, uInt columnValue) { }
     213  virtual void enterTime(const uInt recordNo, Double columnValue) { }
     214  virtual void leaveTime(const uInt recordNo, Double columnValue) { }
     215  virtual void enterPolNo(const uInt recordNo, uInt columnValue) { }
     216  virtual void leavePolNo(const uInt recordNo, uInt columnValue) { }
     217
     218  virtual Bool visitRecord(const uInt recordNo,
     219                           const String &fieldName,
     220                           const uInt beamNo,
     221                           const uInt scanNo,
     222                           const uInt ifNo,
     223                           const Int srcType,
     224                           const uInt cycleNo,
     225                           const Double time,
     226                           const uInt polNo) { return True ;}
     227
     228  virtual Bool visit(Bool isFirst, const uInt recordNo,
     229                     const uInt nCols, void const *const colValues[]) {
     230    const String *fieldName = NULL;
     231    uInt beamNo, scanNo, ifNo;
     232    Int srcType;
     233    uInt cycleNo;
     234    Double time;
     235    Int polNo;
     236    { // prologue
     237      uInt i = 0;
     238      {
     239        const String *col = (const String*)colValues[i++];
     240        fieldName = &col[recordNo];
     241      }
     242      {
     243        const uInt *col = (const uInt *)colValues[i++];
     244        beamNo = col[recordNo];
     245      }
     246      {
     247        const uInt *col = (const uInt *)colValues[i++];
     248        scanNo = col[recordNo];
     249      }
     250      {
     251        const uInt *col = (const uInt *)colValues[i++];
     252        ifNo = col[recordNo];
     253      }
     254      {
     255        const Int *col = (const Int *)colValues[i++];
     256        srcType = col[recordNo];
     257      }
     258      {
     259        const uInt *col = (const uInt *)colValues[i++];
     260        cycleNo = col[recordNo];
     261      }
     262      {
     263        const Double *col = (const Double *)colValues[i++];
     264        time = col[recordNo];
     265      }
     266      {
     267        const Int *col = (const Int *)colValues[i++];
     268        polNo = col[recordNo];
     269      }
     270      assert(nCols == i);
     271    }
     272
     273    if (isFirst) {
     274      enterFieldName(recordNo, *fieldName);
     275      enterBeamNo(recordNo, beamNo);
     276      enterScanNo(recordNo, scanNo);
     277      enterIfNo(recordNo, ifNo);
     278      enterSrcType(recordNo, srcType);
     279      enterCycleNo(recordNo, cycleNo);
     280      enterTime(recordNo, time);
     281      enterPolNo(recordNo, polNo);
     282    } else {
     283      if (lastFieldName->compare(*fieldName) != 0) {
     284        leavePolNo(lastRecordNo, lastPolNo);
     285        leaveTime(lastRecordNo, lastTime);
     286        leaveCycleNo(lastRecordNo, lastCycleNo);
     287        leaveSrcType(lastRecordNo, lastSrcType);
     288        leaveIfNo(lastRecordNo, lastIfNo);
     289        leaveScanNo(lastRecordNo, lastScanNo);
     290        leaveBeamNo(lastRecordNo, lastBeamNo);
     291        leaveFieldName(lastRecordNo, *lastFieldName);
     292
     293        enterFieldName(recordNo, *fieldName);
     294        enterBeamNo(recordNo, beamNo);
     295        enterScanNo(recordNo, scanNo);
     296        enterIfNo(recordNo, ifNo);
     297        enterSrcType(recordNo, srcType);
     298        enterCycleNo(recordNo, cycleNo);
     299        enterTime(recordNo, time);
     300        enterPolNo(recordNo, polNo);
     301      } else if (lastBeamNo != beamNo) {
     302        leavePolNo(lastRecordNo, lastPolNo);
     303        leaveTime(lastRecordNo, lastTime);
     304        leaveCycleNo(lastRecordNo, lastCycleNo);
     305        leaveSrcType(lastRecordNo, lastSrcType);
     306        leaveIfNo(lastRecordNo, lastIfNo);
     307        leaveScanNo(lastRecordNo, lastScanNo);
     308        leaveBeamNo(lastRecordNo, lastBeamNo);
     309
     310        enterBeamNo(recordNo, beamNo);
     311        enterScanNo(recordNo, scanNo);
     312        enterIfNo(recordNo, ifNo);
     313        enterSrcType(recordNo, srcType);
     314        enterCycleNo(recordNo, cycleNo);
     315        enterTime(recordNo, time);
     316        enterPolNo(recordNo, polNo);
     317      } else if (lastScanNo != scanNo) {
     318        leavePolNo(lastRecordNo, lastPolNo);
     319        leaveTime(lastRecordNo, lastTime);
     320        leaveCycleNo(lastRecordNo, lastCycleNo);
     321        leaveSrcType(lastRecordNo, lastSrcType);
     322        leaveIfNo(lastRecordNo, lastIfNo);
     323        leaveScanNo(lastRecordNo, lastScanNo);
     324
     325        enterScanNo(recordNo, scanNo);
     326        enterIfNo(recordNo, ifNo);
     327        enterSrcType(recordNo, srcType);
     328        enterCycleNo(recordNo, cycleNo);
     329        enterTime(recordNo, time);
     330        enterPolNo(recordNo, polNo);
     331      } else if (lastIfNo != ifNo) {
     332        leavePolNo(lastRecordNo, lastPolNo);
     333        leaveTime(lastRecordNo, lastTime);
     334        leaveCycleNo(lastRecordNo, lastCycleNo);
     335        leaveSrcType(lastRecordNo, lastSrcType);
     336        leaveIfNo(lastRecordNo, lastIfNo);
     337
     338        enterIfNo(recordNo, ifNo);
     339        enterSrcType(recordNo, srcType);
     340        enterCycleNo(recordNo, cycleNo);
     341        enterTime(recordNo, time);
     342        enterPolNo(recordNo, polNo);
     343      } else if (lastSrcType != srcType) {
     344        leavePolNo(lastRecordNo, lastPolNo);
     345        leaveTime(lastRecordNo, lastTime);
     346        leaveCycleNo(lastRecordNo, lastCycleNo);
     347        leaveSrcType(lastRecordNo, lastSrcType);
     348
     349        enterSrcType(recordNo, srcType);
     350        enterCycleNo(recordNo, cycleNo);
     351        enterTime(recordNo, time);
     352        enterPolNo(recordNo, polNo);
     353      } else if (lastCycleNo != cycleNo) {
     354        leavePolNo(lastRecordNo, lastPolNo);
     355        leaveTime(lastRecordNo, lastTime);
     356        leaveCycleNo(lastRecordNo, lastCycleNo);
     357
     358        enterCycleNo(recordNo, cycleNo);
     359        enterTime(recordNo, time);
     360        enterPolNo(recordNo, polNo);
     361      } else if (lastTime != time) {
     362        leavePolNo(lastRecordNo, lastPolNo);
     363        leaveTime(lastRecordNo, lastTime);
     364
     365        enterTime(recordNo, time);
     366        enterPolNo(recordNo, polNo);
     367      } else if (lastPolNo != polNo) {
     368        leavePolNo(lastRecordNo, lastPolNo);
     369        enterPolNo(recordNo, polNo);
     370      }
     371    }
     372    count++;
     373    Bool result = visitRecord(recordNo, *fieldName, beamNo, scanNo, ifNo, srcType,
     374                              cycleNo, time, polNo);
     375
     376    { // epilogue
     377      lastRecordNo = recordNo;
     378
     379      lastFieldName = fieldName;
     380      lastBeamNo = beamNo;
     381      lastScanNo = scanNo;
     382      lastIfNo = ifNo;
     383      lastSrcType = srcType;
     384      lastCycleNo = cycleNo;
     385      lastTime = time;
     386      lastPolNo = polNo;
     387    }
     388    return result ;
     389  }
     390
     391  virtual void finish() {
     392    if (count > 0) {
     393      leavePolNo(lastRecordNo, lastPolNo);
     394      leaveTime(lastRecordNo, lastTime);
     395      leaveCycleNo(lastRecordNo, lastCycleNo);
     396      leaveSrcType(lastRecordNo, lastSrcType);
     397      leaveIfNo(lastRecordNo, lastIfNo);
     398      leaveScanNo(lastRecordNo, lastScanNo);
     399      leaveBeamNo(lastRecordNo, lastBeamNo);
     400      leaveFieldName(lastRecordNo, *lastFieldName);
     401    }
     402  }
     403};
     404
     405class MSWriterVisitor: public BaseMSWriterVisitor, public MSWriterUtils {
     406public:
     407  MSWriterVisitor(const Table &table, Table &mstable)
     408    : BaseMSWriterVisitor(table),
     409      ms(mstable)
     410  {
     411    rowidx = 0 ;
     412    fieldName = "" ;
     413    defaultFieldId = 0 ;
     414    spwId = -1 ;
     415    subscan = 1 ;
     416    ptName = "" ;
     417    srcId = 0 ;
     418   
     419    row = TableRow( ms ) ;
     420
     421    holder.reset() ;
     422
     423    makePolMap() ;
     424    initFrequencies() ;
     425    initTcal() ;
     426
     427    //
     428    // add rows to MS
     429    //
     430    uInt addrow = table.nrow() ;
     431    ms.addRow( addrow ) ;
     432
     433    // attach to Scantable columns
     434    spectraCol.attach( table, "SPECTRA" ) ;
     435    flagtraCol.attach( table, "FLAGTRA" ) ;
     436    flagRowCol.attach( table, "FLAGROW" ) ;
     437    tcalIdCol.attach( table, "TCAL_ID" ) ;
     438    intervalCol.attach( table, "INTERVAL" ) ;
     439    directionCol.attach( table, "DIRECTION" ) ;
     440    scanRateCol.attach( table, "SCANRATE" ) ;
     441    timeCol.attach( table, "TIME" ) ;
     442    freqIdCol.attach( table, "FREQ_ID" ) ;
     443    sourceNameCol.attach( table, "SRCNAME" ) ;
     444    sourceDirectionCol.attach( table, "SRCDIRECTION" ) ;
     445    fieldNameCol.attach( table, "FIELDNAME" ) ;
     446
     447    // MS subtables
     448    attachSubtables() ;
     449
     450    // attach to MS columns
     451    attachMain() ;
     452    attachPointing() ;
     453  }
     454 
     455  virtual void enterFieldName(const uInt recordNo, const String &columnValue) {
     456    //printf("%u: FieldName: %s\n", recordNo, columnValue.c_str());
     457    fieldName = fieldNameCol.asString( recordNo ) ;
     458    String::size_type pos = fieldName.find( "__" ) ;
     459    if ( pos != String::npos ) {
     460      fieldId = String::toInt( fieldName.substr( pos+2 ) ) ;
     461      fieldName = fieldName.substr( 0, pos ) ;
     462    }
     463    else {
     464      fieldId = defaultFieldId ;
     465      defaultFieldId++ ;
     466    }
     467    Double tSec = timeCol.asdouble( recordNo ) * 86400.0 ;
     468    Vector<Double> srcDir = sourceDirectionCol( recordNo ) ;
     469    Vector<Double> srate = scanRateCol( recordNo ) ;
     470    String srcName = sourceNameCol.asString( recordNo ) ;
     471
     472    addField( fieldId, fieldName, srcName, srcDir, srate, tSec ) ;
     473
     474    // put value
     475    *fieldIdRF = fieldId ;
     476  }
     477  virtual void leaveFieldName(const uInt recordNo, const String &columnValue) {
     478  }
     479  virtual void enterBeamNo(const uInt recordNo, uInt columnValue) {
     480    //printf("%u: BeamNo: %u\n", recordNo, columnValue);
     481   
     482    feedId = (Int)columnValue ;
     483
     484    // put value
     485    *feed1RF = feedId ;
     486    *feed2RF = feedId ;
     487  }
     488  virtual void leaveBeamNo(const uInt recordNo, uInt columnValue) {
     489  }
     490  virtual void enterScanNo(const uInt recordNo, uInt columnValue) {
     491    //printf("%u: ScanNo: %u\n", recordNo, columnValue);
     492
     493    // put value
     494    // SCAN_NUMBER is 0-based in Scantable while 1-based in MS
     495    *scanNumberRF = (Int)columnValue + 1 ;
     496  }
     497  virtual void leaveScanNo(const uInt recordNo, uInt columnValue) {
     498    subscan = 1 ;
     499  }
     500  virtual void enterIfNo(const uInt recordNo, uInt columnValue) {
     501    //printf("%u: IfNo: %u\n", recordNo, columnValue);
     502
     503    spwId = (Int)columnValue ;
     504    uInt freqId = freqIdCol.asuInt( recordNo ) ;
     505
     506    Vector<Float> sp = spectraCol( recordNo ) ;
     507    uInt nchan = sp.nelements() ;
     508    holder.setNchan( nchan ) ;
     509
     510    addSpectralWindow( spwId, freqId ) ;
     511
     512    addFeed( feedId, spwId ) ;
     513  }
     514  virtual void leaveIfNo(const uInt recordNo, uInt columnValue) {
     515  }
     516  virtual void enterSrcType(const uInt recordNo, Int columnValue) {
     517    //printf("%u: SrcType: %d\n", recordNo, columnValue);
     518
     519    Int stateId = addState( columnValue ) ;
     520
     521    // put value
     522    *stateIdRF = stateId ;
     523  }
     524  virtual void leaveSrcType(const uInt recordNo, Int columnValue) {
     525  }
     526  virtual void enterCycleNo(const uInt recordNo, uInt columnValue) {
     527    //printf("%u: CycleNo: %u\n", recordNo, columnValue);
     528  }
     529  virtual void leaveCycleNo(const uInt recordNo, uInt columnValue) {
     530  }
     531  virtual void enterTime(const uInt recordNo, Double columnValue) {
     532    //printf("%u: Time: %f\n", recordNo, columnValue);
     533
     534    Double timeSec = columnValue * 86400.0 ;
     535    Double interval = intervalCol.asdouble( recordNo ) ;
     536
     537    if ( ptName.empty() ) {
     538      Vector<Double> dir = directionCol( recordNo ) ;
     539      Vector<Double> rate = scanRateCol( recordNo ) ;
     540      if ( anyNE( rate, 0.0 ) ) {
     541        Matrix<Double> msdir( 2, 2 ) ;
     542        msdir.column( 0 ) = dir ;
     543        msdir.column( 1 ) = rate ;
     544        addPointing( timeSec, interval, msdir ) ;
     545      }
     546      else {
     547        Matrix<Double> msdir( 2, 1 ) ;
     548        msdir.column( 0 ) = dir ;
     549        addPointing( timeSec, interval, msdir ) ;
     550      }
     551    }
     552
     553    // put value
     554    *timeRF = timeSec ;
     555    *timeCentroidRF = timeSec ;
     556    *intervalRF = interval ;
     557    *exposureRF = interval ;
     558  }
     559  virtual void leaveTime(const uInt recordNo, Double columnValue) {
     560    if ( holder.nPol() > 0 ) {
     561      Vector<Float> w = holder.getWeight() ;
     562      Cube<Bool> c = holder.getFlagCategory() ;
     563      Bool flr = holder.getFlagRow() ;
     564      Matrix<Bool> fl = holder.getFlag() ;
     565      Vector<uInt> polnos = holder.polNos() ;
     566      Int polId = addPolarization( polnos ) ;
     567      Int ddId = addDataDescription( polId, spwId ) ;
     568       
     569      // put field
     570      *dataDescIdRF = ddId ;
     571      *flagRowRF = flr ;
     572      weightRF.define( w ) ;
     573      sigmaRF.define( w ) ;
     574      flagCategoryRF.define( c ) ;
     575      flagRF.define( fl ) ;
     576      if ( useFloat ) {
     577        Matrix<Float> sp = holder.getData() ;
     578        floatDataRF.define( sp ) ;
     579      }
     580      else {
     581        Matrix<Complex> sp = holder.getComplexData() ;
     582        dataRF.define( sp ) ;
     583      }
     584     
     585      // commit row
     586      row.put( rowidx ) ;
     587      rowidx++ ;
     588
     589      // reset holder
     590      holder.reset() ;
     591    }
     592    if ( tcalKey != -1 ) {
     593      tcalNotYet[tcalKey] = False ;
     594      tcalKey = -1 ;
     595    }
     596  }
     597  virtual void enterPolNo(const uInt recordNo, uInt columnValue) {
     598    //printf("%u: PolNo: %d\n", recordNo, columnValue);
     599    uInt tcalId = tcalIdCol.asuInt( recordNo ) ;
     600    if ( tcalKey == -1 ) {
     601      tcalKey = tcalId ;
     602    }
     603    if ( tcalNotYet[tcalKey] ) {
     604      map< Int,Vector<uInt> >::iterator itr = tcalIdRec.find( tcalKey ) ;
     605      if ( itr != tcalIdRec.end() ) {
     606        Vector<uInt> ids = itr->second ;
     607        uInt nrow = ids.nelements() ;
     608        ids.resize( nrow+1, True ) ;
     609        ids[nrow] = tcalId ;
     610        tcalIdRec.erase( tcalKey ) ;
     611        tcalIdRec[tcalKey] = ids ;
     612      }
     613      else {
     614        Vector<uInt> rows( 1, tcalId ) ;
     615        tcalIdRec[tcalKey] = rows ;
     616      }
     617    }
     618    map< Int,Vector<uInt> >::iterator itr = tcalRowRec.find( tcalKey ) ;
     619    if ( itr != tcalRowRec.end() ) {
     620      Vector<uInt> rows = itr->second ;
     621      uInt nrow = rows.nelements() ;
     622      rows.resize( nrow+1, True ) ;
     623      rows[nrow] = recordNo ;
     624      tcalRowRec.erase( tcalKey ) ;
     625      tcalRowRec[tcalKey] = rows ;
     626    }
     627    else {
     628      Vector<uInt> rows( 1, recordNo ) ;
     629      tcalRowRec[tcalKey] = rows ;
     630    }
     631  }
     632  virtual void leavePolNo(const uInt recordNo, uInt columnValue) {
     633  }
     634
     635  virtual Bool visitRecord(const uInt recordNo,
     636                           const String &fieldName,
     637                           const uInt beamNo,
     638                           const uInt scanNo,
     639                           const uInt ifNo,
     640                           const Int srcType,
     641                           const uInt cycleNo,
     642                           const Double time,
     643                           const uInt polNo) {
     644    //printf("%u: %s, %u, %u, %u, %d, %u, %f, %d\n", recordNo,
     645    //       fieldName.c_str(), beamNo, scanNo, ifNo, srcType, cycleNo, time, polNo);
     646
     647    Vector<Float> sp = spectraCol( recordNo ) ;
     648    Vector<uChar> tmp = flagtraCol( recordNo ) ;
     649    Vector<Bool> fl( tmp.shape() ) ;
     650    convertArray( fl, tmp ) ;
     651    Bool flr = (Bool)flagRowCol.asuInt( recordNo ) ;
     652    holder.accumulate( polNo, sp, fl, flr ) ;
     653
     654    return True ;
     655  }
     656
     657  virtual void finish() {
     658    BaseMSWriterVisitor::finish();
     659    //printf("Total: %u\n", count);
     660
     661    // remove rows
     662    if ( ms.nrow() > rowidx ) {
     663      uInt numRemove = ms.nrow() - rowidx ;
     664      //cout << "numRemove = " << numRemove << endl ;
     665      Vector<uInt> rows( numRemove ) ;
     666      indgen( rows, rowidx ) ;
     667      ms.removeRow( rows ) ;
     668    }
     669
     670    // fill empty SPECTRAL_WINDOW rows
     671    infillSpectralWindow() ;
     672  }
     673
     674  void dataColumnName( String name )
     675  {
     676    TableRecord &r = row.record() ;
     677    if ( name == "DATA" ) {
     678      useFloat = False ;
     679      dataRF.attachToRecord( r, name ) ;
     680    }
     681    else if ( name == "FLOAT_DATA" ) {
     682      useFloat = True ;
     683      floatDataRF.attachToRecord( r, name ) ;
     684    }
     685  }
     686  void pointingTableName( String name ) {
     687    ptName = name ;
     688  }
     689  void setSourceRecord( Record &r ) {
     690    srcRec = r ;
     691  }
     692  map< Int,Vector<uInt> > &getTcalIdRecord() { return tcalIdRec ; }
     693  map< Int,Vector<uInt> > &getTcalRowRecord() { return tcalRowRec ; }
     694private:
     695  void addField( Int &fid, String &fname, String &srcName,
     696                 Vector<Double> &sdir, Vector<Double> &srate,
     697                 Double &tSec )
     698  {
     699    uInt nrow = fieldtab.nrow() ;
     700    while( (Int)nrow <= fid ) {
     701      fieldtab.addRow( 1, True ) ;
     702      nrow++ ;
     703    }
     704
     705    Matrix<Double> dir ;
     706    Int numPoly = 0 ;
     707    if ( anyNE( srate, 0.0 ) ) {
     708      dir.resize( 2, 2 ) ;
     709      dir.column( 0 ) = sdir ;
     710      dir.column( 1 ) = srate ;
     711      numPoly = 1 ;
     712    }
     713    else {
     714      dir.resize( 2, 1 ) ;
     715      dir.column( 0 ) = sdir ;
     716    }
     717    srcId = srcRec.asInt( srcName ) ;
     718
     719    TableRow tr( fieldtab ) ;
     720    TableRecord &r = tr.record() ;
     721    putField( "NAME", r, fname ) ;
     722    putField( "NUM_POLY", r, numPoly ) ;
     723    putField( "TIME", r, tSec ) ;
     724    putField( "SOURCE_ID", r, srcId ) ;
     725    defineField( "DELAY_DIR", r, dir ) ;
     726    defineField( "REFERENCE_DIR", r, dir ) ;
     727    defineField( "PHASE_DIR", r, dir ) ;
     728    tr.put( fid ) ;
     729
     730    // for POINTING table
     731    *poNameRF = fname ;
     732  }
     733  Int addState( Int &id )
     734  {
     735    String obsMode ;
     736    Bool isSignal ;
     737    Double tnoise ;
     738    Double tload ;
     739    queryType( id, obsMode, isSignal, tnoise, tload ) ;
     740
     741    String key = obsMode+"_"+String::toString( subscan ) ;
     742    Int idx = -1 ;
     743    uInt nEntry = stateEntry.nelements() ;
     744    for ( uInt i = 0 ; i < nEntry ; i++ ) {
     745      if ( stateEntry[i] == key ) {
     746        idx = i ;
     747        break ;
     748      }
     749    }
     750    if ( idx == -1 ) {
     751      uInt nrow = statetab.nrow() ;
     752      statetab.addRow( 1, True ) ;
     753      TableRow tr( statetab ) ;
     754      TableRecord &r = tr.record() ;
     755      putField( "OBS_MODE", r, obsMode ) ;
     756      putField( "SIG", r, isSignal ) ;
     757      isSignal = !isSignal ;
     758      putField( "REF", r, isSignal ) ;
     759      putField( "CAL", r, tnoise ) ;
     760      putField( "LOAD", r, tload ) ;
     761      tr.put( nrow ) ;
     762      idx = nrow ;
     763
     764      stateEntry.resize( nEntry+1, True ) ;
     765      stateEntry[nEntry] = key ;
     766    }
     767    subscan++ ;
     768
     769    return idx ;
     770  }
     771  void addPointing( Double &tSec, Double &interval, Matrix<Double> &dir )
     772  {
     773    uInt nrow = potab.nrow() ;
     774    potab.addRow( 1, True ) ;
     775
     776    *poNumPolyRF = dir.ncolumn() - 1 ;
     777    *poTimeRF = tSec ;
     778    *poTimeOriginRF = tSec ;
     779    *poIntervalRF = interval ;
     780    poDirectionRF.define( dir ) ;
     781    poTargetRF.define( dir ) ;
     782    porow.put( nrow ) ;
     783  }
     784  Int addPolarization( Vector<uInt> &nos )
     785  {
     786    Int idx = -1 ;
     787    uInt nEntry = polEntry.size() ;
     788    for ( uInt i = 0 ; i < nEntry ; i++ ) {
     789      if ( polEntry[i].conform( nos ) && allEQ( polEntry[i], nos ) ) {
     790        idx = i ;
     791        break ;
     792      }
     793    }
     794   
     795    Int numCorr ;
     796    Vector<Int> corrType ;
     797    Matrix<Int> corrProduct ;
     798    polProperty( nos, numCorr, corrType, corrProduct ) ;
     799
     800    if ( idx == -1 ) {
     801      uInt nrow = poltab.nrow() ;
     802      poltab.addRow( 1, True ) ;
     803      TableRow tr( poltab ) ;
     804      TableRecord &r = tr.record() ;
     805      putField( "NUM_CORR", r, numCorr ) ;
     806      defineField( "CORR_TYPE", r, corrType ) ;
     807      defineField( "CORR_PRODUCT", r, corrProduct ) ;
     808      tr.put( nrow ) ;
     809      idx = nrow ;
     810
     811      polEntry.resize( nEntry+1 ) ;
     812      polEntry[nEntry] = nos ;
     813    }
     814
     815    return idx ;
     816  }
     817  Int addDataDescription( Int pid, Int sid )
     818  {
     819    Int idx = -1 ;
     820    uInt nEntry = ddEntry.nrow() ;
     821    Vector<Int> key( 2 ) ;
     822    key[0] = pid ;
     823    key[1] = sid ;
     824    for ( uInt i = 0 ; i < nEntry ; i++ ) {
     825      if ( allEQ( ddEntry.row(i), key ) ) {
     826        idx = i ;
     827        break ;
     828      }
     829    }
     830
     831    if ( idx == -1 ) {
     832      uInt nrow = ddtab.nrow() ;
     833      ddtab.addRow( 1, True ) ;
     834      TableRow tr( ddtab ) ;
     835      TableRecord &r = tr.record() ;
     836      putField( "POLARIZATION_ID", r, pid ) ;
     837      putField( "SPECTRAL_WINDOW_ID", r, sid ) ;
     838      tr.put( nrow ) ;
     839      idx = nrow ;
     840
     841      ddEntry.resize( nEntry+1, 2, True ) ;
     842      ddEntry.row(nEntry) = key ;
     843    }
     844
     845    return idx ;
     846  }
     847  void infillSpectralWindow()
     848  {
     849    ROScalarColumn<Int> nchanCol( spwtab, "NUM_CHAN" ) ;
     850    Vector<Int> nchan = nchanCol.getColumn() ;
     851    TableRow tr( spwtab ) ;
     852    TableRecord &r = tr.record() ;
     853    Int mfr = 1 ;
     854    Vector<Double> dummy( 1, 0.0 ) ;
     855    putField( "MEAS_FREQ_REF", r, mfr ) ;
     856    defineField( "CHAN_FREQ", r, dummy ) ;
     857    defineField( "CHAN_WIDTH", r, dummy ) ;
     858    defineField( "EFFECTIVE_BW", r, dummy ) ;
     859    defineField( "RESOLUTION", r, dummy ) ;
     860
     861    for ( uInt i = 0 ; i < spwtab.nrow() ; i++ ) {
     862      if ( nchan[i] == 0 )
     863        tr.put( i ) ;
     864    }
     865  }
     866  void addSpectralWindow( Int sid, uInt fid )
     867  {
     868    if ( !processedFreqId[fid] ) {
     869      uInt nrow = spwtab.nrow() ;
     870      while( (Int)nrow <= sid ) {
     871        spwtab.addRow( 1, True ) ;
     872        nrow++ ;
     873      }
     874      processedFreqId[fid] = True ;
     875    }
     876
     877    Double rp = refpix[fid] ;
     878    Double rv = refval[fid] ;
     879    Double ic = increment[fid] ;
     880
     881    Int mfrInt = (Int)freqframe ;
     882    Int nchan = holder.nChan() ;
     883    Double bw = nchan * abs( ic ) ;
     884    Double reffreq = rv - rp * ic ;
     885    Int netsb = 0 ; // USB->0, LSB->1
     886    if ( ic < 0 )
     887      netsb = 1 ;
     888    Vector<Double> res( nchan, abs(ic) ) ;
     889    Vector<Double> chanf( nchan ) ;
     890    indgen( chanf, reffreq, ic ) ;
     891
     892    TableRow tr( spwtab ) ;
     893    TableRecord &r = tr.record() ;
     894    putField( "MEAS_FREQ_REF", r, mfrInt ) ;
     895    putField( "NUM_CHAN", r, nchan ) ;
     896    putField( "TOTAL_BANDWIDTH", r, bw ) ;
     897    putField( "REF_FREQUENCY", r, reffreq ) ;
     898    putField( "NET_SIDEBAND", r, netsb ) ;
     899    defineField( "RESOLUTION", r, res ) ;
     900    defineField( "CHAN_WIDTH", r, res ) ;
     901    defineField( "EFFECTIVE_BW", r, res ) ;
     902    defineField( "CHAN_FREQ", r, chanf ) ;
     903    tr.put( sid ) ;
     904  }
     905  void addFeed( Int fid, Int sid )
     906  {
     907    Int idx = -1 ;
     908    uInt nEntry = feedEntry.nrow() ;
     909    Vector<Int> key( 2 ) ;
     910    key[0] = fid ;
     911    key[1] = sid ;
     912    for ( uInt i = 0 ; i < nEntry ; i++ ) {
     913      if ( allEQ( feedEntry.row(i), key ) ) {
     914        idx = i ;
     915        break ;
     916      }
     917    }
     918
     919    if ( idx == -1 ) {
     920      uInt nrow = feedtab.nrow() ;
     921      feedtab.addRow( 1, True ) ;
     922      Int numReceptors = 2 ;
     923      Vector<String> polType( numReceptors ) ;
     924      Matrix<Double> beamOffset( 2, numReceptors, 0.0 ) ;
     925      Vector<Double> receptorAngle( numReceptors, 0.0 ) ;
     926      if ( poltype == "linear" ) {
     927        polType[0] = "X" ;
     928        polType[1] = "Y" ;
     929      }
     930      else if ( poltype == "circular" ) {
     931        polType[0] = "R" ;
     932        polType[1] = "L" ;
     933      }
     934      else {
     935        polType[0] = "X" ;
     936        polType[1] = "Y" ;
     937      }
     938      Matrix<Complex> polResponse( numReceptors, numReceptors, 0.0 ) ;
     939     
     940      TableRow tr( feedtab ) ;
     941      TableRecord &r = tr.record() ;
     942      putField( "FEED_ID", r, fid ) ;
     943      putField( "BEAM_ID", r, fid ) ;
     944      Int tmp = 0 ;
     945      putField( "ANTENNA_ID", r, tmp ) ;
     946      putField( "SPECTRAL_WINDOW_ID", r, sid ) ;
     947      putField( "NUM_RECEPTORS", r, numReceptors ) ;
     948      defineField( "POLARIZATION_TYPE", r, polType ) ;
     949      defineField( "BEAM_OFFSET", r, beamOffset ) ;
     950      defineField( "RECEPTOR_ANGLE", r, receptorAngle ) ;
     951      defineField( "POL_RESPONSE", r, polResponse ) ;
     952      tr.put( nrow ) ;
     953
     954      feedEntry.resize( nEntry+1, 2, True ) ;
     955      feedEntry.row( nEntry ) = key ;
     956    }
     957  }
     958  void makePolMap()
     959  {
     960    const TableRecord &keys = table.keywordSet() ;
     961    poltype = keys.asString( "POLTYPE" ) ;
     962
     963    if ( poltype == "stokes" ) {
     964      polmap.resize( 4 ) ;
     965      polmap[0] = Stokes::I ;
     966      polmap[1] = Stokes::Q ;
     967      polmap[2] = Stokes::U ;
     968      polmap[3] = Stokes::V ;
     969    }
     970    else if ( poltype == "linear" ) {
     971      polmap.resize( 4 ) ;
     972      polmap[0] = Stokes::XX ;
     973      polmap[1] = Stokes::YY ;
     974      polmap[2] = Stokes::XY ;
     975      polmap[3] = Stokes::YX ;
     976    }
     977    else if ( poltype == "circular" ) {
     978      polmap.resize( 4 ) ;
     979      polmap[0] = Stokes::RR ;
     980      polmap[1] = Stokes::LL ;
     981      polmap[2] = Stokes::RL ;
     982      polmap[3] = Stokes::LR ;
     983    }
     984    else if ( poltype == "linpol" ) {
     985      polmap.resize( 2 ) ;
     986      polmap[0] = Stokes::Plinear ;
     987      polmap[1] = Stokes::Pangle ;
     988    }
     989    else {
     990      polmap.resize( 0 ) ;
     991    }
     992  }
     993  void initFrequencies()
     994  {
     995    const TableRecord &keys = table.keywordSet() ;
     996    Table tab = keys.asTable( "FREQUENCIES" ) ;
     997    ROScalarColumn<uInt> idcol( tab, "ID" ) ;
     998    ROScalarColumn<Double> rpcol( tab, "REFPIX" ) ;
     999    ROScalarColumn<Double> rvcol( tab, "REFVAL" ) ;
     1000    ROScalarColumn<Double> iccol( tab, "INCREMENT" ) ;
     1001    Vector<uInt> id = idcol.getColumn() ;
     1002    Vector<Double> rp = rpcol.getColumn() ;
     1003    Vector<Double> rv = rvcol.getColumn() ;
     1004    Vector<Double> ic = iccol.getColumn() ;
     1005    for ( uInt i = 0 ; i < id.nelements() ; i++ ) {
     1006      processedFreqId.insert( pair<uInt,Bool>( id[i], False ) ) ;
     1007      refpix.insert( pair<uInt,Double>( id[i], rp[i] ) ) ;
     1008      refval.insert( pair<uInt,Double>( id[i], rv[i] ) ) ;
     1009      increment.insert( pair<uInt,Double>( id[i], ic[i] ) ) ;
     1010    }
     1011    String frameStr = tab.keywordSet().asString( "BASEFRAME" ) ;
     1012    MFrequency::getType( freqframe, frameStr ) ;
     1013  }
     1014  void attachSubtables()
     1015  {
     1016    const TableRecord &keys = table.keywordSet() ;
     1017    TableRecord &mskeys = ms.rwKeywordSet() ;
     1018
     1019    // FIELD table
     1020    fieldtab = mskeys.asTable( "FIELD" ) ;
     1021
     1022    // SPECTRAL_WINDOW table
     1023    spwtab = mskeys.asTable( "SPECTRAL_WINDOW" ) ;
     1024
     1025    // POINTING table
     1026    potab = mskeys.asTable( "POINTING" ) ;
     1027
     1028    // POLARIZATION table
     1029    poltab = mskeys.asTable( "POLARIZATION" ) ;
     1030
     1031    // DATA_DESCRIPTION table
     1032    ddtab = mskeys.asTable( "DATA_DESCRIPTION" ) ;
     1033
     1034    // STATE table
     1035    statetab = mskeys.asTable( "STATE" ) ;
     1036
     1037    // FEED table
     1038    feedtab = mskeys.asTable( "FEED" ) ;
     1039  }
     1040  void attachMain()
     1041  {
     1042    TableRecord &r = row.record() ;
     1043    dataDescIdRF.attachToRecord( r, "DATA_DESC_ID" ) ;
     1044    flagRowRF.attachToRecord( r, "FLAG_ROW" ) ;
     1045    weightRF.attachToRecord( r, "WEIGHT" ) ;
     1046    sigmaRF.attachToRecord( r, "SIGMA" ) ;
     1047    flagCategoryRF.attachToRecord( r, "FLAG_CATEGORY" ) ;
     1048    flagRF.attachToRecord( r, "FLAG" ) ;
     1049    timeRF.attachToRecord( r, "TIME" ) ;
     1050    timeCentroidRF.attachToRecord( r, "TIME_CENTROID" ) ;
     1051    intervalRF.attachToRecord( r, "INTERVAL" ) ;
     1052    exposureRF.attachToRecord( r, "EXPOSURE" ) ;
     1053    fieldIdRF.attachToRecord( r, "FIELD_ID" ) ;
     1054    feed1RF.attachToRecord( r, "FEED1" ) ;
     1055    feed2RF.attachToRecord( r, "FEED2" ) ;
     1056    scanNumberRF.attachToRecord( r, "SCAN_NUMBER" ) ;
     1057    stateIdRF.attachToRecord( r, "STATE_ID" ) ;
     1058
     1059    // constant values
     1060    Int id = 0 ;
     1061    RecordFieldPtr<Int> intRF( r, "OBSERVATION_ID" ) ;
     1062    *intRF = 0 ;
     1063    intRF.attachToRecord( r, "ANTENNA1" ) ;
     1064    *intRF = 0 ;
     1065    intRF.attachToRecord( r, "ANTENNA2" ) ;
     1066    *intRF = 0 ;
     1067    intRF.attachToRecord( r, "ARRAY_ID" ) ;
     1068    *intRF = 0 ;
     1069    intRF.attachToRecord( r, "PROCESSOR_ID" ) ;
     1070    *intRF = 0 ;
     1071    RecordFieldPtr< Vector<Double> > arrayRF( r, "UVW" ) ;
     1072    arrayRF.define( Vector<Double>( 3, 0.0 ) ) ;
     1073  }
     1074  void attachPointing()
     1075  {
     1076    porow = TableRow( potab ) ;
     1077    TableRecord &r = porow.record() ;
     1078    poNumPolyRF.attachToRecord( r, "NUM_POLY" ) ;
     1079    poTimeRF.attachToRecord( r, "TIME" ) ;
     1080    poTimeOriginRF.attachToRecord( r, "TIME_ORIGIN" ) ;
     1081    poIntervalRF.attachToRecord( r, "INTERVAL" ) ;
     1082    poNameRF.attachToRecord( r, "NAME" ) ;
     1083    poDirectionRF.attachToRecord( r, "DIRECTION" ) ;
     1084    poTargetRF.attachToRecord( r, "TARGET" ) ;
     1085   
     1086    // constant values
     1087    RecordFieldPtr<Int> antIdRF( r, "ANTENNA_ID" ) ;
     1088    *antIdRF = 0 ;
     1089    RecordFieldPtr<Bool> trackingRF( r, "TRACKING" ) ;
     1090    *trackingRF = True ;
     1091  }
     1092  void queryType( Int type, String &stype, Bool &b, Double &t, Double &l )
     1093  {
     1094    t = 0.0 ;
     1095    l = 0.0 ;
     1096
     1097    String sep1="#" ;
     1098    String sep2="," ;
     1099    String target="OBSERVE_TARGET" ;
     1100    String atmcal="CALIBRATE_TEMPERATURE" ;
     1101    String onstr="ON_SOURCE" ;
     1102    String offstr="OFF_SOURCE" ;
     1103    String pswitch="POSITION_SWITCH" ;
     1104    String nod="NOD" ;
     1105    String fswitch="FREQUENCY_SWITCH" ;
     1106    String sigstr="SIG" ;
     1107    String refstr="REF" ;
     1108    String unspecified="UNSPECIFIED" ;
     1109    String ftlow="LOWER" ;
     1110    String fthigh="HIGHER" ;
     1111    switch ( type ) {
     1112    case SrcType::PSON:
     1113      stype = target+sep1+onstr+sep2+pswitch ;
     1114      b = True ;
     1115      break ;
     1116    case SrcType::PSOFF:
     1117      stype = target+sep1+offstr+sep2+pswitch ;
     1118      b = False ;
     1119      break ;
     1120    case SrcType::NOD:
     1121      stype = target+sep1+onstr+sep2+nod ;
     1122      b = True ;
     1123      break ;
     1124    case SrcType::FSON:
     1125      stype = target+sep1+onstr+sep2+fswitch+sep1+sigstr ;
     1126      b = True ;
     1127      break ;
     1128    case SrcType::FSOFF:
     1129      stype = target+sep1+onstr+sep2+fswitch+sep1+refstr ;
     1130      b = False ;
     1131      break ;
     1132    case SrcType::SKY:
     1133      stype = atmcal+sep1+offstr+sep2+unspecified ;
     1134      b = False ;
     1135      break ;
     1136    case SrcType::HOT:
     1137      stype = atmcal+sep1+offstr+sep2+unspecified ;
     1138      b = False ;
     1139      break ;
     1140    case SrcType::WARM:
     1141      stype = atmcal+sep1+offstr+sep2+unspecified ;
     1142      b = False ;
     1143      break ;
     1144    case SrcType::COLD:
     1145      stype = atmcal+sep1+offstr+sep2+unspecified ;
     1146      b = False ;
     1147      break ;
     1148    case SrcType::PONCAL:
     1149      stype = atmcal+sep1+onstr+sep2+pswitch ;
     1150      b = True ;
     1151      break ;
     1152    case SrcType::POFFCAL:
     1153      stype = atmcal+sep1+offstr+sep2+pswitch ;
     1154      b = False ;
     1155      break ;
     1156    case SrcType::NODCAL:
     1157      stype = atmcal+sep1+onstr+sep2+nod ;
     1158      b = True ;
     1159      break ;
     1160    case SrcType::FONCAL:
     1161      stype = atmcal+sep1+onstr+sep2+fswitch+sep1+sigstr ;
     1162      b = True ;
     1163      break ;
     1164    case SrcType::FOFFCAL:
     1165      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+refstr ;
     1166      b = False ;
     1167      break ;
     1168    case SrcType::FSLO:
     1169      stype = target+sep1+onstr+sep2+fswitch+sep1+ftlow ;
     1170      b = True ;
     1171      break ;
     1172    case SrcType::FLOOFF:
     1173      stype = target+sep1+offstr+sep2+fswitch+sep1+ftlow ;
     1174      b = False ;
     1175      break ;
     1176    case SrcType::FLOSKY:
     1177      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+ftlow ;
     1178      b = False ;
     1179      break ;
     1180    case SrcType::FLOHOT:
     1181      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+ftlow ;
     1182      b = False ;
     1183      break ;
     1184    case SrcType::FLOWARM:
     1185      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+ftlow ;
     1186      b = False ;
     1187      break ;
     1188    case SrcType::FLOCOLD:
     1189      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+ftlow ;
     1190      b = False ;
     1191      break ;
     1192    case SrcType::FSHI:
     1193      stype = target+sep1+onstr+sep2+fswitch+sep1+fthigh ;
     1194      b = True ;
     1195      break ;
     1196    case SrcType::FHIOFF:
     1197      stype = target+sep1+offstr+sep2+fswitch+sep1+fthigh ;
     1198      b = False ;
     1199      break ;
     1200    case SrcType::FHISKY:
     1201      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+fthigh ;
     1202      b = False ;
     1203      break ;
     1204    case SrcType::FHIHOT:
     1205      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+fthigh ;
     1206      b = False ;
     1207      break ;
     1208    case SrcType::FHIWARM:
     1209      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+fthigh ;
     1210      b = False ;
     1211      break ;
     1212    case SrcType::FHICOLD:
     1213      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+fthigh ;
     1214      b = False ;
     1215      break ;
     1216    case SrcType::SIG:
     1217      stype = target+sep1+onstr+sep2+unspecified ;
     1218      b = True ;
     1219      break ;
     1220    case SrcType::REF:
     1221      stype = target+sep1+offstr+sep2+unspecified ;
     1222      b = False ;
     1223      break ;
     1224    default:
     1225      stype = unspecified ;
     1226      b = True ;
     1227      break ;
     1228    }
     1229  }
     1230  void polProperty( Vector<uInt> &nos, Int &n, Vector<Int> &c, Matrix<Int> &cp )
     1231  {
     1232    n = nos.nelements() ;
     1233    c.resize( n ) ;
     1234    for ( Int i = 0 ; i < n ; i++ )
     1235      c[i] = (Int)polmap[nos[i]] ;
     1236    cp.resize( 2, n ) ;
     1237    if ( n == 1 )
     1238      cp = 0 ;
     1239    else if ( n == 2 ) {
     1240      cp.column( 0 ) = 0 ;
     1241      cp.column( 1 ) = 1 ;
     1242    }
     1243    else {
     1244      cp.column( 0 ) = 0 ;
     1245      cp.column( 1 ) = 1 ;
     1246      cp( 0, 1 ) = 0 ;
     1247      cp( 1, 1 ) = 1 ;
     1248      cp( 0, 2 ) = 1 ;
     1249      cp( 1, 2 ) = 0 ;
     1250    }
     1251  }
     1252  void initTcal()
     1253  {
     1254    const TableRecord &rec = table.keywordSet() ;
     1255    Table tcalTable = rec.asTable( "TCAL" ) ;
     1256    ROScalarColumn<uInt> idCol( tcalTable, "ID" ) ;
     1257    Vector<uInt> id = idCol.getColumn() ;
     1258    uInt maxId = max( id ) ;
     1259    tcalNotYet.resize( maxId+1 ) ;
     1260    tcalNotYet = True ;
     1261    tcalKey = -1 ;
     1262  }
     1263
     1264  Table &ms;
     1265  TableRow row;
     1266  uInt rowidx;
     1267  String fieldName;
     1268  Int fieldId;
     1269  Int srcId;
     1270  Int defaultFieldId;
     1271  Int spwId;
     1272  Int feedId;
     1273  Int subscan;
     1274  PolarizedComponentHolder holder;
     1275  String ptName;
     1276  Bool useFloat;
     1277  String poltype;
     1278  Vector<Stokes::StokesTypes> polmap;
     1279
     1280  // MS subtables
     1281  Table spwtab;
     1282  Table statetab;
     1283  Table ddtab;
     1284  Table poltab;
     1285  Table fieldtab;
     1286  Table feedtab;
     1287  Table potab;
     1288
     1289  // Scantable MAIN columns
     1290  ROArrayColumn<Float> spectraCol;
     1291  ROArrayColumn<Double> directionCol,scanRateCol,sourceDirectionCol;
     1292  ROArrayColumn<uChar> flagtraCol;
     1293  ROTableColumn tcalIdCol,intervalCol,flagRowCol,timeCol,freqIdCol,
     1294    sourceNameCol,fieldNameCol;
     1295
     1296  // MS MAIN columns
     1297  RecordFieldPtr<Int> dataDescIdRF,fieldIdRF,feed1RF,feed2RF,
     1298    scanNumberRF,stateIdRF;
     1299  RecordFieldPtr<Bool> flagRowRF;
     1300  RecordFieldPtr<Double> timeRF,timeCentroidRF,intervalRF,exposureRF;
     1301  RecordFieldPtr< Vector<Float> > weightRF,sigmaRF;
     1302  RecordFieldPtr< Cube<Bool> > flagCategoryRF;
     1303  RecordFieldPtr< Matrix<Bool> > flagRF;
     1304  RecordFieldPtr< Matrix<Float> > floatDataRF;
     1305  RecordFieldPtr< Matrix<Complex> > dataRF;
     1306
     1307  // MS POINTING columns
     1308  TableRow porow;
     1309  RecordFieldPtr<Int> poNumPolyRF ;
     1310  RecordFieldPtr<Double> poTimeRF,
     1311    poTimeOriginRF,
     1312    poIntervalRF ;
     1313  RecordFieldPtr<String> poNameRF ;
     1314  RecordFieldPtr< Matrix<Double> > poDirectionRF,
     1315    poTargetRF ;
     1316
     1317  Vector<String> stateEntry;
     1318  Matrix<Int> ddEntry;
     1319  Matrix<Int> feedEntry;
     1320  vector< Vector<uInt> > polEntry;
     1321  map<uInt,Bool> processedFreqId;
     1322  map<uInt,Double> refpix;
     1323  map<uInt,Double> refval;
     1324  map<uInt,Double> increment;
     1325  MFrequency::Types freqframe;
     1326  Record srcRec;
     1327  map< Int,Vector<uInt> > tcalIdRec;
     1328  map< Int,Vector<uInt> > tcalRowRec;
     1329  Int tcalKey;
     1330  Vector<Bool> tcalNotYet;
     1331};
    561332
    571333MSWriter::MSWriter(CountedPtr<Scantable> stable)
     
    791355    delete mstable_ ;
    801356}
    81  
     1357
    821358bool MSWriter::write(const string& filename, const Record& rec)
    831359{
    841360  os_.origin( LogOrigin( "MSWriter", "write()", WHERE ) ) ;
    85 //   double startSec = mathutil::gettimeofday_sec() ;
    86 //   os_ << "start MSWriter::write() startSec=" << startSec << LogIO::POST ;
     1361  //double startSec = mathutil::gettimeofday_sec() ;
     1362  //os_ << "start MSWriter::write() startSec=" << startSec << LogIO::POST ;
    871363
    881364  filename_ = filename ;
     
    1341410    fillWeather() ;
    1351411
    136   // MAIN
    137   // Iterate over several ids
    138   Vector<uInt> processedFreqId( 0 ) ;
    139   Int defaultFieldId = 0 ;
    140 
    141   // row based
    142   TableRow row( *mstable_ ) ;
    143   TableRecord &trec = row.record() ;
    144   NoticeTarget *dataRF = 0 ;
    145   if ( useFloatData_ )
    146     dataRF = new RecordFieldPtr< Array<Float> >( trec, "FLOAT_DATA" ) ;
    147   else if ( useData_ )
    148     dataRF = new RecordFieldPtr< Array<Complex> >( trec, "DATA" ) ;
    149   RecordFieldPtr< Array<Bool> > flagRF( trec, "FLAG" ) ;
    150   RecordFieldPtr<Bool> flagrowRF( trec, "FLAG_ROW" ) ;
    151   RecordFieldPtr<Double> timeRF( trec, "TIME" ) ;
    152   RecordFieldPtr<Double> timecRF( trec, "TIME_CENTROID" ) ;
    153   RecordFieldPtr<Double> intervalRF( trec, "INTERVAL" ) ;
    154   RecordFieldPtr<Double> exposureRF( trec, "EXPOSURE" ) ;
    155   RecordFieldPtr< Array<Float> > weightRF( trec, "WEIGHT" ) ;
    156   RecordFieldPtr< Array<Float> > sigmaRF( trec, "SIGMA" ) ;
    157   RecordFieldPtr<Int> ddidRF( trec, "DATA_DESC_ID" ) ;
    158   RecordFieldPtr<Int> stateidRF( trec, "STATE_ID" ) ;
    159   RecordFieldPtr< Array<Bool> > flagcatRF( trec, "FLAG_CATEGORY" ) ;
    160 
    161   // OBSERVATION_ID is always 0
    162   RecordFieldPtr<Int> intRF( trec, "OBSERVATION_ID" ) ;
    163   *intRF = 0 ;
    164  
    165   // ANTENNA1 and ANTENNA2 are always 0
    166   intRF.attachToRecord( trec, "ANTENNA1" ) ;
    167   *intRF = 0 ;
    168   intRF.attachToRecord( trec, "ANTENNA2" ) ;
    169   *intRF = 0 ;
    170  
    171   // ARRAY_ID is tentatively set to 0
    172   intRF.attachToRecord( trec, "ARRAY_ID" ) ;
    173   *intRF = 0 ;
    174 
    175   // PROCESSOR_ID is tentatively set to 0
    176   intRF.attachToRecord( trec, "PROCESSOR_ID" ) ;
    177   *intRF = 0 ;
    178 
    179   // UVW is always [0,0,0]
    180   RecordFieldPtr< Array<Double> > uvwRF( trec, "UVW" ) ;
    181   *uvwRF = Vector<Double>( 3, 0.0 ) ;
    182 
    183   //
    184   // ITERATION: FIELDNAME
    185   //
    186   TableIterator iter0( table_->table(), "FIELDNAME" ) ;
    187   while( !iter0.pastEnd() ) {
    188     //Table t0( iter0.table() ) ;
    189     Table t0 = iter0.table() ;
    190     ROTableColumn sharedCol( t0, "FIELDNAME" ) ;
    191     String fieldName = sharedCol.asString( 0 ) ;
    192     sharedCol.attach( t0, "SRCNAME" ) ;
    193     String srcName = sharedCol.asString( 0 ) ;
    194     sharedCol.attach( t0, "TIME" ) ;
    195     Double minTime = (Double)sharedCol.asdouble( 0 ) * 86400.0 ; // day->sec
    196     ROArrayColumn<Double> scanRateCol( t0, "SCANRATE" ) ;
    197     Vector<Double> scanRate = scanRateCol( 0 ) ;
    198     String::size_type pos = fieldName.find( "__" ) ;
    199     Int fieldId = -1 ;
    200     if ( pos != String::npos ) {
    201 //       os_ << "fieldName.substr( pos+2 )=" << fieldName.substr( pos+2 ) << LogIO::POST ;
    202       fieldId = String::toInt( fieldName.substr( pos+2 ) ) ;
    203       fieldName = fieldName.substr( 0, pos ) ;
    204     }
    205     else {
    206 //       os_ << "use default field id" << LogIO::POST ;
    207       fieldId = defaultFieldId ;
    208       defaultFieldId++ ;
    209     }
    210 //     os_ << "fieldId" << fieldId << ": " << fieldName << LogIO::POST ;
    211 
    212     // FIELD_ID
    213     intRF.attachToRecord( trec, "FIELD_ID" ) ;
    214     *intRF = fieldId ;
    215 
    216     //
    217     // ITERATION: BEAMNO
    218     //
    219     TableIterator iter1( t0, "BEAMNO" ) ;
    220     while( !iter1.pastEnd() ) {
    221       Table t1 = iter1.table() ;
    222       sharedCol.attach( t1, "BEAMNO" ) ;
    223       uInt beamNo = sharedCol.asuInt( 0 ) ;
    224 //       os_ << "beamNo = " << beamNo << LogIO::POST ;
    225 
    226       // FEED1 and FEED2
    227       intRF.attachToRecord( trec, "FEED1" ) ;
    228       *intRF = beamNo ;
    229       intRF.attachToRecord( trec, "FEED2" ) ;
    230       *intRF = beamNo ;
    231 
    232       //
    233       // ITERATION: SCANNO
    234       //
    235       TableIterator iter2( t1, "SCANNO" ) ;
    236       while( !iter2.pastEnd() ) {
    237         Table t2 = iter2.table() ;
    238         sharedCol.attach( t2, "SCANNO" ) ;
    239         uInt scanNo = sharedCol.asuInt( 0 ) ;
    240 //         os_ << "scanNo = " << scanNo << LogIO::POST ;
    241 
    242         // SCAN_NUMBER
    243         // MS: 1-based
    244         // Scantable: 0-based
    245         intRF.attachToRecord( trec, "SCAN_NUMBER" ) ;
    246         *intRF = scanNo + 1 ;
    247 
    248         //
    249         // ITERATION: IFNO
    250         //
    251         TableIterator iter3( t2, "IFNO" ) ;
    252         while( !iter3.pastEnd() ) {
    253           Table t3 = iter3.table() ;
    254           sharedCol.attach( t3, "IFNO" ) ;
    255           uInt ifNo = sharedCol.asuInt( 0 ) ;
    256 //           os_ << "ifNo = " << ifNo << LogIO::POST ;
    257           sharedCol.attach( t3, "FREQ_ID" ) ;
    258           uInt freqId = sharedCol.asuInt( 0 ) ;
    259 //           os_ << "freqId = " << freqId << LogIO::POST ;
    260           Int subscan = 1 ; // 1-base
    261           //
    262           // ITERATION: SRCTYPE
    263           //
    264           TableIterator iter4( t3, "SRCTYPE" ) ;
    265           while( !iter4.pastEnd() ) {
    266             Table t4 = iter4.table() ;
    267             sharedCol.attach( t4, "SRCTYPE" ) ;
    268             Int srcType = sharedCol.asInt( 0 ) ;
    269             Int stateId = addState( srcType, subscan ) ;
    270             *stateidRF = stateId ;
    271             //
    272             // ITERATION: CYCLENO and TIME
    273             //
    274             Block<String> cols( 2 ) ;
    275             cols[0] = "CYCLENO" ;
    276             cols[1] = "TIME" ;
    277             TableIterator iter5( t4, cols ) ;
    278             while( !iter5.pastEnd() ) {
    279               Table t5 =  iter5.table().sort("POLNO") ;
    280               //sharedCol.attach( t5, "CYCLENO" ) ;
    281               //uInt cycleNo = sharedCol.asuInt( 0 ) ;
    282               Int nrow = t5.nrow() ;
    283 //               os_ << "nrow = " << nrow << LogIO::POST ;
    284              
    285               Vector<Int> polnos( nrow ) ;
    286               indgen( polnos, 0 ) ;
    287               Int polid = addPolarization( polnos ) ;
    288 //               os_ << "polid = " << polid << LogIO::POST ;
    289              
    290               // DATA/FLOAT_DATA
    291               ROArrayColumn<Float> specCol( t5, "SPECTRA" ) ;
    292               ROArrayColumn<uChar> flagCol( t5, "FLAGTRA" ) ;
    293               uInt nchan = specCol( 0 ).size() ;
    294               IPosition cellshape( 2, nrow, nchan ) ;
    295               if ( useFloatData_ ) {
    296                 // FLOAT_DATA
    297                 Matrix<Float> dataArr( cellshape ) ;
    298                 Matrix<Bool> flagArr( cellshape ) ;
    299                 Vector<Bool> tmpB ;
    300                 for ( Int ipol = 0 ; ipol < nrow ; ipol++ ) {
    301                   dataArr.row( ipol ) = specCol( ipol ) ;
    302                   tmpB.reference( flagArr.row( ipol ) ) ;
    303                   convertArray( tmpB, flagCol( ipol ) ) ;
    304                 }
    305                 ((RecordFieldPtr< Array<Float> > *)dataRF)->define( dataArr ) ;
    306                
    307                 // FLAG
    308                 flagRF.define( flagArr ) ;
    309               }
    310               else if ( useData_ ) {
    311                 // DATA
    312                 // assume nrow = 4
    313                 Matrix<Complex> dataArr( cellshape ) ;
    314                 Vector<Float> zeroIm( nchan, 0 ) ;
    315                 Matrix<Float> dummy( IPosition( 2, 2, nchan ) ) ;
    316                 dummy.row( 0 ) = specCol( 0 ) ;
    317                 dummy.row( 1 ) = zeroIm ;
    318                 dataArr.row( 0 ) = RealToComplex( dummy ) ;
    319                 dummy.row( 0 ) = specCol( 1 ) ;
    320                 dataArr.row( 3 ) = RealToComplex( dummy ) ;
    321                 dummy.row( 0 ) = specCol( 2 ) ;
    322                 dummy.row( 1 ) = specCol( 3 ) ;
    323                 dataArr.row( 1 ) = RealToComplex( dummy ) ;
    324                 dataArr.row( 2 ) = conj( dataArr.row( 1 ) ) ;
    325                 ((RecordFieldPtr< Array<Complex> > *)dataRF)->define( dataArr ) ;
    326                
    327                
    328                 // FLAG
    329                 Matrix<Bool> flagArr( cellshape ) ;
    330                 Vector<Bool> tmpB ;
    331                 tmpB.reference( flagArr.row( 0 ) ) ;
    332                 convertArray( tmpB, flagCol( 0 ) ) ;
    333                 tmpB.reference( flagArr.row( 3 ) ) ;
    334                 convertArray( tmpB, flagCol( 3 ) ) ;
    335                 tmpB.reference( flagArr.row( 1 ) ) ;
    336                 convertArray( tmpB, ( flagCol( 2 ) | flagCol( 3 ) ) ) ;
    337                 flagArr.row( 2 ) = flagArr.row( 1 ) ;
    338                 flagRF.define( flagArr ) ;
    339               }
    340 
    341               // FLAG_ROW
    342               sharedCol.attach( t5, "FLAGROW" ) ;
    343               Vector<uInt> flagRowArr( nrow ) ;
    344               for ( Int irow = 0 ; irow < nrow ; irow++ )
    345                 flagRowArr[irow] = sharedCol.asuInt( irow ) ;
    346               *flagrowRF = anyNE( flagRowArr, (uInt)0 ) ;
    347 
    348               // TIME and TIME_CENTROID
    349               sharedCol.attach( t5, "TIME" ) ;
    350               Double mTimeV = (Double)sharedCol.asdouble( 0 ) * 86400.0 ; // day -> sec
    351               *timeRF = mTimeV ;
    352               *timecRF = mTimeV ;
    353 
    354               // INTERVAL and EXPOSURE
    355               sharedCol.attach( t5, "INTERVAL" ) ;
    356               Double interval = (Double)sharedCol.asdouble( 0 ) ;
    357               *intervalRF = interval ;
    358               *exposureRF = interval ;
    359              
    360               // WEIGHT and SIGMA
    361               // always 1 at the moment
    362               Vector<Float> wArr( nrow, 1.0 ) ;
    363               weightRF.define( wArr ) ;
    364               sigmaRF.define( wArr ) ;
    365              
    366               // add DATA_DESCRIPTION row
    367               Int ddid = addDataDescription( polid, ifNo ) ;
    368 //               os_ << "ddid = " << ddid << LogIO::POST ;
    369               *ddidRF = ddid ;
    370              
    371               // for SYSCAL table
    372               sharedCol.attach( t5, "TCAL_ID" ) ;
    373               Vector<uInt> tcalIdArr( nrow ) ;
    374               for ( Int irow = 0 ; irow < nrow ; irow++ )
    375                 tcalIdArr[irow] = sharedCol.asuInt( irow ) ;
    376 //               os_ << "tcalIdArr = " << tcalIdArr << LogIO::POST ;
    377               String key = String::toString( tcalIdArr[0] ) ;
    378               if ( !tcalIdRec_.isDefined( key ) ) {
    379                 tcalIdRec_.define( key, tcalIdArr ) ;
    380                 tcalRowRec_.define( key, t5.rowNumbers() ) ;
    381               }
    382               else {
    383                 Vector<uInt> pastrows = tcalRowRec_.asArrayuInt( key ) ;
    384                 tcalRowRec_.define( key, concatenateArray( pastrows, t5.rowNumbers() ) ) ;
    385               }
    386                            
    387               // for POINTING table
    388               if ( ptTabName_ == "" ) {
    389                 ROArrayColumn<Double> dirCol( t5, "DIRECTION" ) ;
    390                 Vector<Double> dir = dirCol( 0 ) ;
    391                 dirCol.attach( t5, "SCANRATE" ) ;
    392                 Vector<Double> rate = dirCol( 0 ) ;
    393                 Matrix<Double> msDir( 2, 1 ) ;
    394                 msDir.column( 0 ) = dir ;
    395                 if ( anyNE( rate, 0.0 ) ) {
    396                   msDir.resize( 2, 2, True ) ;
    397                   msDir.column( 1 ) = rate ;
    398                 }
    399                 addPointing( fieldName, mTimeV, interval, msDir ) ;
    400               }
    401              
    402               // FLAG_CATEGORY is tentatively set
    403               flagcatRF.define( Cube<Bool>( nrow, nchan, 1, False ) ) ;
    404              
    405               // add row
    406               mstable_->addRow( 1, True ) ;
    407               row.put( mstable_->nrow()-1 ) ;
    408              
    409               iter5.next() ;
    410             }
    411            
    412             iter4.next() ;
    413           }
    414 
    415           // add SPECTRAL_WINDOW row
    416           if ( allNE( processedFreqId, freqId ) ) {
    417             uInt vsize = processedFreqId.size() ;
    418             processedFreqId.resize( vsize+1, True ) ;
    419             processedFreqId[vsize] = freqId ;
    420             addSpectralWindow( ifNo, freqId ) ;
    421           }
    422          
    423           iter3.next() ;
    424         }
    425        
    426         iter2.next() ;
    427       }
    428      
    429       // add FEED row
    430       addFeed( beamNo ) ;
    431      
    432       iter1.next() ;
    433     }
    434    
    435     // add FIELD row
    436     addField( fieldId, fieldName, srcName, minTime, scanRate ) ;
    437 
    438     iter0.next() ;
    439   }
    440 
    441 //   delete tpoolr ;
    442   delete dataRF ;
    443 
    444   // SYSCAL
    445   if ( isTcal_ )
    446     fillSysCal() ;
    447 
    448   // fill empty SPECTRAL_WINDOW rows
    449   infillSpectralWindow() ;
     1412  /***
     1413   * Start iteration using TableVisitor
     1414   ***/
     1415  {
     1416    static const char *cols[] = {
     1417      "FIELDNAME", "BEAMNO", "SCANNO", "IFNO", "SRCTYPE", "CYCLENO", "TIME",
     1418      "POLNO",
     1419      NULL
     1420    };
     1421    static const TypeManagerImpl<uInt> tmUInt;
     1422    static const TypeManagerImpl<Int> tmInt;
     1423    static const TypeManagerImpl<Double> tmDouble;
     1424    static const TypeManagerImpl<String> tmString;
     1425    static const TypeManager *const tms[] = {
     1426      &tmString, &tmUInt, &tmUInt, &tmUInt, &tmInt, &tmUInt, &tmDouble, &tmInt, NULL
     1427    };
     1428    //double t0 = mathutil::gettimeofday_sec() ;
     1429    MSWriterVisitor myVisitor(table_->table(),*mstable_);
     1430    //double t1 = mathutil::gettimeofday_sec() ;
     1431    //cout << "MSWriterVisitor(): elapsed time " << t1-t0 << " sec" << endl ;
     1432    String dataColName = "FLOAT_DATA" ;
     1433    if ( useData_ )
     1434      dataColName = "DATA" ;
     1435    myVisitor.dataColumnName( dataColName ) ;
     1436    myVisitor.pointingTableName( ptTabName_ ) ;
     1437    myVisitor.setSourceRecord( srcRec_ ) ;
     1438    //double t2 = mathutil::gettimeofday_sec() ;
     1439    traverseTable(table_->table(), cols, tms, &myVisitor);
     1440    //double t3 = mathutil::gettimeofday_sec() ;
     1441    //cout << "traverseTable(): elapsed time " << t3-t2 << " sec" << endl ;
     1442    map< Int,Vector<uInt> > &idRec = myVisitor.getTcalIdRecord() ;
     1443    map< Int,Vector<uInt> > &rowRec = myVisitor.getTcalRowRecord() ;
     1444
     1445    // SYSCAL
     1446    if ( isTcal_ )
     1447      fillSysCal( idRec, rowRec ) ;
     1448  }
     1449  /***
     1450   * End iteration using TableVisitor
     1451   ***/
    4501452
    4511453  // ASDM tables
     
    4751477  }
    4761478
    477 //   double endSec = mathutil::gettimeofday_sec() ;
    478 //   os_ << "end MSWriter::write() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
     1479  //double endSec = mathutil::gettimeofday_sec() ;
     1480  //os_ << "end MSWriter::write() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    4791481
    4801482  return True ;
    4811483}
    482  
     1484
    4831485void MSWriter::init()
    4841486{
     
    6971699void MSWriter::fillObservation()
    6981700{
    699 //   double startSec = mathutil::gettimeofday_sec() ;
    700 //   os_ << "start MSWriter::fillObservation() startSec=" << startSec << LogIO::POST ;
     1701  //double startSec = mathutil::gettimeofday_sec() ;
     1702  //os_ << "start MSWriter::fillObservation() startSec=" << startSec << LogIO::POST ;
    7011703
    7021704  // only 1 row
     
    7261728  msObsCols.timeRangeMeas().put( 0, trange ) ;
    7271729
    728 //   double endSec = mathutil::gettimeofday_sec() ;
    729 //   os_ << "end MSWriter::fillObservation() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
     1730  //double endSec = mathutil::gettimeofday_sec() ;
     1731  //os_ << "end MSWriter::fillObservation() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    7301732}
     1733
     1734void MSWriter::antennaProperty( String &name, String &m, String &t, Double &d )
     1735{
     1736  name.upcase() ;
     1737 
     1738  m = "ALT-AZ" ;
     1739  t = "GROUND-BASED" ;
     1740  if ( name.matches( Regex( "DV[0-9]+$" ) )
     1741       || name.matches( Regex( "DA[0-9]+$" ) )
     1742       || name.matches( Regex( "PM[0-9]+$" ) ) )
     1743    d = 12.0 ;
     1744  else if ( name.matches( Regex( "CM[0-9]+$" ) ) )
     1745    d = 7.0 ;
     1746  else if ( name.contains( "GBT" ) )
     1747    d = 104.9 ;
     1748  else if ( name.contains( "MOPRA" ) )
     1749    d = 22.0 ;
     1750  else if ( name.contains( "PKS" ) || name.contains( "PARKS" ) )
     1751    d = 64.0 ;
     1752  else if ( name.contains( "TIDBINBILLA" ) )
     1753    d = 70.0 ;
     1754  else if ( name.contains( "CEDUNA" ) )
     1755    d = 30.0 ;
     1756  else if ( name.contains( "HOBART" ) )
     1757    d = 26.0 ;
     1758  else if ( name.contains( "APEX" ) )
     1759    d = 12.0 ;
     1760  else if ( name.contains( "ASTE" ) )
     1761    d = 10.0 ;
     1762  else if ( name.contains( "NRO" ) )
     1763    d = 45.0 ;
     1764  else
     1765    d = 1.0 ;
     1766}
    7311767
    7321768void MSWriter::fillAntenna()
    7331769{
    734 //   double startSec = mathutil::gettimeofday_sec() ;
    735 //   os_ << "start MSWriter::fillAntenna() startSec=" << startSec << LogIO::POST ;
     1770  //double startSec = mathutil::gettimeofday_sec() ;
     1771  //os_ << "start MSWriter::fillAntenna() startSec=" << startSec << LogIO::POST ;
    7361772
    7371773  // only 1 row
    738   mstable_->antenna().addRow( 1, True ) ;
    739   MSAntennaColumns msAntCols( mstable_->antenna() ) ;
    740 
    741   String hAntennaName = header_.antennaname ;
    742   String::size_type pos = hAntennaName.find( "//" ) ;
     1774  Table anttab = mstable_->antenna() ;
     1775  anttab.addRow( 1, True ) ;
     1776 
     1777  Table &table = table_->table() ;
     1778  const TableRecord &keys = table.keywordSet() ;
     1779  String hAntName = keys.asString( "AntennaName" ) ;
     1780  String::size_type pos = hAntName.find( "//" ) ;
    7431781  String antennaName ;
    7441782  String stationName ;
    7451783  if ( pos != String::npos ) {
    746     hAntennaName = hAntennaName.substr( pos+2 ) ;
    747   }
    748   pos = hAntennaName.find( "@" ) ;
     1784    stationName = hAntName.substr( 0, pos ) ;
     1785    hAntName = hAntName.substr( pos+2 ) ;
     1786  }
     1787  pos = hAntName.find( "@" ) ;
    7491788  if ( pos != String::npos ) {
    750     antennaName = hAntennaName.substr( 0, pos ) ;
    751     stationName = hAntennaName.substr( pos+1 ) ;
     1789    antennaName = hAntName.substr( 0, pos ) ;
     1790    stationName = hAntName.substr( pos+1 ) ;
    7521791  }
    7531792  else {
    754     antennaName = hAntennaName ;
    755     stationName = hAntennaName ;
    756   }
    757 //   os_ << "antennaName = " << antennaName << LogIO::POST ;
    758 //   os_ << "stationName = " << stationName << LogIO::POST ;
     1793    antennaName = hAntName ;
     1794  }
     1795  Vector<Double> antpos = keys.asArrayDouble( "AntennaPosition" ) ;
    7591796 
    760   msAntCols.name().put( 0, antennaName ) ;
    761   msAntCols.station().put( 0, stationName ) ;
    762 
    763 //   os_ << "antennaPosition = " << header_.antennaposition << LogIO::POST ;
     1797  String mount, atype ;
     1798  Double diameter ;
     1799  antennaProperty( antennaName, mount, atype, diameter ) ;
    7641800 
    765   msAntCols.position().put( 0, header_.antennaposition ) ;
    766 
    767   // MOUNT is set to "ALT-AZ"
    768   msAntCols.mount().put( 0, "ALT-AZ" ) ;
    769 
    770   Double diameter = getDishDiameter( antennaName ) ;
    771   msAntCols.dishDiameterQuant().put( 0, Quantity( diameter, "m" ) ) ;
    772 
    773 //   double endSec = mathutil::gettimeofday_sec() ;
    774 //   os_ << "end MSWriter::fillAntenna() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
     1801  TableRow tr( anttab ) ;
     1802  TableRecord &r = tr.record() ;
     1803  RecordFieldPtr<String> nameRF( r, "NAME" ) ;
     1804  RecordFieldPtr<String> stationRF( r, "STATION" ) ;
     1805  RecordFieldPtr<String> mountRF( r, "NAME" ) ;
     1806  RecordFieldPtr<String> typeRF( r, "TYPE" ) ;
     1807  RecordFieldPtr<Double> dishDiameterRF( r, "DISH_DIAMETER" ) ;
     1808  RecordFieldPtr< Vector<Double> > positionRF( r, "POSITION" ) ;
     1809  *nameRF = antennaName ;
     1810  *mountRF = mount ;
     1811  *typeRF = atype ;
     1812  *dishDiameterRF = diameter ;
     1813  *positionRF = antpos ;
     1814 
     1815  tr.put( 0 ) ;
     1816
     1817  //double endSec = mathutil::gettimeofday_sec() ;
     1818  //os_ << "end MSWriter::fillAntenna() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    7751819}
     1820 
     1821// void MSWriter::fillAntenna()
     1822// {
     1823// //   double startSec = mathutil::gettimeofday_sec() ;
     1824// //   os_ << "start MSWriter::fillAntenna() startSec=" << startSec << LogIO::POST ;
     1825
     1826//   // only 1 row
     1827//   mstable_->antenna().addRow( 1, True ) ;
     1828//   MSAntennaColumns msAntCols( mstable_->antenna() ) ;
     1829
     1830//   String hAntennaName = header_.antennaname ;
     1831//   String::size_type pos = hAntennaName.find( "//" ) ;
     1832//   String antennaName ;
     1833//   String stationName ;
     1834//   if ( pos != String::npos ) {
     1835//     hAntennaName = hAntennaName.substr( pos+2 ) ;
     1836//   }
     1837//   pos = hAntennaName.find( "@" ) ;
     1838//   if ( pos != String::npos ) {
     1839//     antennaName = hAntennaName.substr( 0, pos ) ;
     1840//     stationName = hAntennaName.substr( pos+1 ) ;
     1841//   }
     1842//   else {
     1843//     antennaName = hAntennaName ;
     1844//     stationName = hAntennaName ;
     1845//   }
     1846// //   os_ << "antennaName = " << antennaName << LogIO::POST ;
     1847// //   os_ << "stationName = " << stationName << LogIO::POST ;
     1848 
     1849//   msAntCols.name().put( 0, antennaName ) ;
     1850//   msAntCols.station().put( 0, stationName ) ;
     1851
     1852// //   os_ << "antennaPosition = " << header_.antennaposition << LogIO::POST ;
     1853 
     1854//   msAntCols.position().put( 0, header_.antennaposition ) ;
     1855
     1856//   // MOUNT is set to "ALT-AZ"
     1857//   msAntCols.mount().put( 0, "ALT-AZ" ) ;
     1858
     1859//   Double diameter = getDishDiameter( antennaName ) ;
     1860//   msAntCols.dishDiameterQuant().put( 0, Quantity( diameter, "m" ) ) ;
     1861
     1862// //   double endSec = mathutil::gettimeofday_sec() ;
     1863// //   os_ << "end MSWriter::fillAntenna() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
     1864// }
    7761865
    7771866void MSWriter::fillProcessor()
     
    8361925    ROScalarColumn<Double> srcVelCol( t0, "SRCVELOCITY" ) ;
    8371926    Double srcVel = srcVelCol( 0 ) ;
     1927    srcRec_.define( srcName, srcId ) ;
    8381928
    8391929    // NAME
     
    9902080}
    9912081
    992 void MSWriter::fillSysCal()
     2082void MSWriter::fillSysCal( map< Int,Vector<uInt> > &idRec,
     2083                           map< Int,Vector<uInt> > &rowRec )
    9932084{
    994 //   double startSec = mathutil::gettimeofday_sec() ;
    995 //   os_ << "start MSWriter::fillSysCal() startSec=" << startSec << LogIO::POST ;
    996 
    997   //tcalIdRec_.print( cout ) ;
     2085  //double startSec = mathutil::gettimeofday_sec() ;
     2086  //os_ << "start MSWriter::fillSysCal() startSec=" << startSec << LogIO::POST ;
     2087
     2088  //idRec.print( cout ) ;
    9982089
    9992090  // access to MS SYSCAL subtable
     
    10172108    return ;
    10182109
    1019   nrow = tcalIdRec_.nfields() ;
     2110  //nrow = idRec.nfields() ;
     2111  nrow = idRec.size() ;
    10202112
    10212113  Double midTime ;
     
    10522144  ROTableColumn beamnoCol( tab, "BEAMNO" ) ;
    10532145  ROTableColumn ifnoCol( tab, "IFNO" ) ;
     2146  map< Int,Vector<uInt> >::iterator itr0 = idRec.begin() ;
     2147  map< Int,Vector<uInt> >::iterator itr1 = rowRec.begin() ;
    10542148  for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
    10552149//     double t1 = mathutil::gettimeofday_sec() ;
    1056     Vector<uInt> ids = tcalIdRec_.asArrayuInt( irow ) ;
     2150    Vector<uInt> ids = itr0->second ;
     2151    itr0++ ;
    10572152//     os_ << "ids = " << ids << LogIO::POST ;
    10582153    uInt npol = ids.size() ;
    1059     Vector<uInt> rows = tcalRowRec_.asArrayuInt( irow ) ;
     2154    Vector<uInt> rows = itr1->second ;
     2155    itr1++ ;
    10602156//     os_ << "rows = " << rows << LogIO::POST ;
    10612157    Vector<Double> atime( rows.nelements() ) ;
     
    11532249    if ( tcalSpec_ ) {
    11542250      // put TCAL_SPECTRUM
    1155       //*tcalspRF = tcal ;
    11562251      tcalspRF.define( tcal ) ;
    11572252      // set TCAL (mean of TCAL_SPECTRUM)
     
    11612256      }
    11622257      // put TCAL
    1163       *tcalRF = tcalMean ;
     2258      tcalRF.define( tcalMean ) ;
    11642259    }
    11652260    else {
    11662261      // put TCAL
    1167       *tcalRF = tcal ;
     2262      tcalRF.define( tcal ) ;
    11682263    }
    11692264   
    11702265    if ( tsysSpec_ ) {
    11712266      // put TSYS_SPECTRUM
    1172       //*tsysspRF = tsys ;
    11732267      tsysspRF.define( tsys ) ;
    11742268      // set TSYS (mean of TSYS_SPECTRUM)
     
    11782272      }
    11792273      // put TSYS
    1180       *tsysRF = tsysMean ;
     2274      tsysRF.define( tsysMean ) ;
    11812275    }
    11822276    else {
    11832277      // put TSYS
    1184       *tsysRF = tsys ;
     2278      tsysRF.define( tsys ) ;
    11852279    }
    11862280
     
    11932287  }
    11942288 
    1195 //   double endSec = mathutil::gettimeofday_sec() ;
    1196 //   os_ << "end MSWriter::fillSysCal() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
     2289  //double endSec = mathutil::gettimeofday_sec() ;
     2290  //os_ << "end MSWriter::fillSysCal() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
    11972291}
    11982292
Note: See TracChangeset for help on using the changeset viewer.