source: tags/asap-4.1.0/src/MSWriter.cpp @ 2662

Last change on this file since 2662 was 2643, checked in by ShinnosukeKawakami, 12 years ago

hpc34 to trunk 24th Aug. 2012

File size: 76.8 KB
Line 
1//
2// C++ Interface: MSWriter
3//
4// Description:
5//
6// This class is specific writer for MS format
7//
8// Takeshi Nakazato <takeshi.nakazato@nao.ac.jp>, (C) 2010
9//
10// Copyright: See COPYING file that comes with this distribution
11//
12//
13#include <assert.h>
14
15#include <casa/OS/File.h>
16#include <casa/OS/RegularFile.h>
17#include <casa/OS/Directory.h>
18#include <casa/OS/SymLink.h>
19#include <casa/BasicSL/String.h>
20#include <casa/Arrays/Cube.h>
21#include <casa/Containers/RecordField.h>
22
23#include <tables/Tables/ExprNode.h>
24#include <tables/Tables/TableDesc.h>
25#include <tables/Tables/SetupNewTab.h>
26#include <tables/Tables/TableIter.h>
27#include <tables/Tables/RefRows.h>
28#include <tables/Tables/TableRow.h>
29
30#include <ms/MeasurementSets/MeasurementSet.h>
31#include <ms/MeasurementSets/MSColumns.h>
32#include <ms/MeasurementSets/MSPolIndex.h>
33#include <ms/MeasurementSets/MSDataDescIndex.h>
34#include <ms/MeasurementSets/MSSourceIndex.h>
35
36#include "MSWriter.h"
37#include "STHeader.h"
38#include "STFrequencies.h"
39#include "STMolecules.h"
40#include "STTcal.h"
41#include "MathUtils.h"
42#include "TableTraverse.h"
43
44using namespace casa ;
45using namespace std ;
46
47namespace asap {
48
49class CorrTypeHandler {
50public:
51  CorrTypeHandler()
52  {}
53  virtual ~CorrTypeHandler() {}
54  virtual Vector<Stokes::StokesTypes> corrType() = 0 ;
55  virtual void reset()
56  {
57    npol = 0 ;
58  }
59  void append( uInt polno )
60  {
61    polnos[npol] = polno ;
62    npol++ ;
63  }
64  uInt nPol() { return npol ; }
65protected:
66  Vector<Stokes::StokesTypes> polmap ;
67  uInt polnos[4] ;
68  uInt npol ;
69};
70
71class LinearHandler : public CorrTypeHandler {
72public:
73  LinearHandler()
74    : CorrTypeHandler()
75  {
76    initMap() ;
77  }
78  virtual ~LinearHandler() {}
79  virtual Vector<Stokes::StokesTypes> corrType()
80  {
81    Vector<Stokes::StokesTypes> ret( npol, Stokes::Undefined ) ;
82    if ( npol < 4 ) {
83      for ( uInt ipol = 0 ; ipol < npol ; ipol++ )
84        ret[ipol] = polmap[polnos[ipol]] ;
85    }
86    else if ( npol == 4 ) {
87      ret[0] = polmap[0] ;
88      ret[1] = polmap[2] ;
89      ret[2] = polmap[3] ;
90      ret[4] = polmap[1] ;
91    }
92    else {
93      throw( AipsError("npol > 4") ) ;
94    }
95    return ret ;
96  }
97protected:
98  void initMap()
99  {
100    polmap.resize( 4 ) ;
101    polmap[0] = Stokes::XX ;
102    polmap[1] = Stokes::YY ;
103    polmap[2] = Stokes::XY ;
104    polmap[3] = Stokes::YX ;
105  }
106};
107class CircularHandler : public CorrTypeHandler {
108public:
109  CircularHandler()
110    : CorrTypeHandler()
111  {
112    initMap() ;
113  }
114  virtual ~CircularHandler() {}
115  virtual Vector<Stokes::StokesTypes> corrType()
116  {
117    Vector<Stokes::StokesTypes> ret( npol, Stokes::Undefined ) ;
118    if ( npol < 4 ) {
119      for ( uInt ipol = 0 ; ipol < npol ; ipol++ )
120        ret[ipol] = polmap[polnos[ipol]] ;
121    }
122    else if ( npol == 4 ) {
123      ret[0] = polmap[0] ;
124      ret[1] = polmap[2] ;
125      ret[2] = polmap[3] ;
126      ret[3] = polmap[1] ;
127    }
128    else {
129      throw( AipsError("npol > 4") ) ;
130    }
131    return ret ;
132  }
133private:
134  void initMap()
135  {
136    polmap.resize( 4 ) ;
137    polmap[0] = Stokes::RR ;
138    polmap[1] = Stokes::LL ;
139    polmap[2] = Stokes::RL ;
140    polmap[3] = Stokes::LR ;
141  }
142};
143class StokesHandler : public CorrTypeHandler {
144public:
145  StokesHandler()
146    : CorrTypeHandler()
147  {
148    initMap() ;
149  }
150  virtual ~StokesHandler() {}
151  virtual Vector<Stokes::StokesTypes> corrType()
152  {
153    Vector<Stokes::StokesTypes> ret( npol, Stokes::Undefined ) ;
154    if ( npol <= 4 ) {
155      for ( uInt ipol = 0 ; ipol < npol ; ipol++ )
156        ret[ipol] = polmap[polnos[ipol]] ;
157    }
158    else {
159      throw( AipsError("npol > 4") ) ;
160    }
161    return ret ;
162  }
163private:
164  void initMap()
165  {
166    polmap.resize( 4 ) ;
167    polmap[0] = Stokes::I ;
168    polmap[1] = Stokes::Q ;
169    polmap[2] = Stokes::U ;
170    polmap[3] = Stokes::V ;
171  }
172};
173class LinPolHandler : public CorrTypeHandler {
174public:
175  LinPolHandler()
176    : CorrTypeHandler()
177  {
178    initMap() ;
179  }
180  virtual ~LinPolHandler() {}
181  virtual Vector<Stokes::StokesTypes> corrType()
182  {
183    Vector<Stokes::StokesTypes> ret( npol, Stokes::Undefined ) ;
184    if ( npol <= 2 ) {
185      for ( uInt ipol = 0 ; ipol < npol ; ipol++ )
186        ret[ipol] = polmap[polnos[ipol]] ;
187    }
188    else {
189      throw( AipsError("npol > 4") ) ;
190    }
191    return ret ;
192  }
193private:
194  void initMap()
195  {
196    polmap.resize( 2 ) ;
197    polmap[0] = Stokes::Plinear ;
198    polmap[1] = Stokes::Pangle ;
199  }
200};
201
202class DataHolder {
203public:
204  DataHolder( TableRow &tableRow, String polType )
205    : row( tableRow )
206  {
207    nchan = 0 ;
208    npol = 0 ;
209    makeCorrTypeHandler( polType ) ;
210    attach() ;
211    flagRow.resize( 4 ) ;
212    reset() ;
213    sigmaTemplate.resize( 4 ) ;
214    sigmaTemplate = 1.0 ;
215  }
216  virtual ~DataHolder() {}
217  virtual void post() = 0 ;
218  virtual void reset()
219  {
220    corr->reset() ;
221    flagRow = False ;
222    npol = 0 ;
223  }
224  virtual void accumulate( uInt id, Vector<Float> &sp, Vector<Bool> &fl, Bool &flr )
225  {
226    accumulateCorrType( id ) ;
227    accumulateData( id, sp ) ;
228    accumulateFlag( id, fl ) ;
229    accumulateFlagRow( id, flr ) ;
230  }
231  uInt nPol() { return npol ; }
232  uInt nChan() { return nchan ; }
233  Vector<Int> corrTypeInt()
234  {
235    Vector<Int> v( npol ) ;
236    convertArray( v, corr->corrType() ) ;
237    return v ;
238  }
239  Vector<Stokes::StokesTypes> corrType() { return corr->corrType() ; }
240  void setNchan( uInt num )
241  {
242    nchan = num ;
243    resize() ;
244  }
245protected:
246  void postAuxiliary()
247  {
248    Vector<Float> w = sigmaTemplate( IPosition(1,0), IPosition(1,npol-1) ) ;
249    sigmaRF.define( w ) ;
250    weightRF.define( w ) ;
251    Cube<Bool> c( npol, nchan, 1, False ) ;
252    flagCategoryRF.define( c ) ;
253  }
254  inline void accumulateCorrType( uInt &id )
255  {
256    corr->append( id ) ;
257    npol = corr->nPol() ;
258  }
259  inline void accumulateFlagRow( uInt &id, Bool &flr )
260  {
261    flagRow[id] = flr ;
262  }
263  void postFlagRow()
264  {
265    *flagRowRF = anyEQ( flagRow, True ) ;
266  }
267  inline void accumulateFlag( uInt &id, Vector<Bool> &fl )
268  {
269    flag.row( id ) = fl ;
270  }
271  virtual void postFlag() = 0 ;
272  inline void accumulateData( uInt &id, Vector<Float> &sp )
273  {
274    data.row( id ) = sp ;
275  }
276  virtual void postData() = 0 ;
277  TableRow &row ;
278  uInt nchan ;
279  uInt npol ;
280  CountedPtr<CorrTypeHandler> corr;
281  RecordFieldPtr< Vector<Float> > sigmaRF ;
282  RecordFieldPtr< Vector<Float> > weightRF ;
283  RecordFieldPtr< Array<Bool> > flagRF ;
284  RecordFieldPtr<Bool> flagRowRF ;
285  RecordFieldPtr< Cube<Bool> > flagCategoryRF ;
286  Vector<Bool> flagRow ;
287  Matrix<Bool> flag ;
288  Matrix<Float> data ;
289  Vector<Float> sigmaTemplate ;
290private:
291  void makeCorrTypeHandler( String &polType )
292  {
293    if ( polType == "linear" )
294      corr = new LinearHandler() ;
295    else if ( polType == "circular" )
296      corr = new CircularHandler() ;
297    else if ( polType == "stokes" )
298      corr = new StokesHandler() ;
299    else if ( polType == "linpol" )
300      corr = new LinPolHandler() ;
301    else
302      throw( AipsError("Invalid polarization type") ) ;
303  }
304  void attach()
305  {
306    TableRecord &rec = row.record() ;
307    sigmaRF.attachToRecord( rec, "SIGMA" ) ;
308    weightRF.attachToRecord( rec, "WEIGHT" ) ;
309    flagRF.attachToRecord( rec, "FLAG" ) ;
310    flagRowRF.attachToRecord( rec, "FLAG_ROW" ) ;
311    flagCategoryRF.attachToRecord( rec, "FLAG_CATEGORY" ) ;
312  }
313  void resize()
314  {
315    flag.resize( 4, nchan ) ;
316    data.resize( 4, nchan ) ;
317  }
318};
319
320class FloatDataHolder : public DataHolder {
321public:
322  FloatDataHolder( TableRow &tableRow, String polType )
323    : DataHolder( tableRow, polType )
324  {
325    attachData() ;
326  }
327  virtual ~FloatDataHolder() {}
328  virtual void post()
329  {
330    postData() ;
331    postFlag() ;
332    postFlagRow() ;
333    postAuxiliary() ;
334  }
335protected:
336  virtual void postFlag()
337  {
338    flagRF.define( flag( IPosition( 2, 0, 0 ), IPosition( 2, npol-1, nchan-1 ) ) ) ;
339  }
340  virtual void postData()
341  {
342    dataRF.define( data( IPosition( 2, 0, 0 ), IPosition( 2, npol-1, nchan-1 ) ) ) ;
343  }
344private:
345  void attachData()
346  {
347    dataRF.attachToRecord( row.record(), "FLOAT_DATA" ) ;
348  }
349  RecordFieldPtr< Matrix<Float> > dataRF;
350};
351
352class ComplexDataHolder : public DataHolder {
353public:
354  ComplexDataHolder( TableRow &tableRow, String polType )
355    : DataHolder( tableRow, polType )
356  {
357    attachData() ;
358  }
359  virtual ~ComplexDataHolder() {}
360  virtual void accumulate( uInt id, Vector<Float> &sp, Vector<Bool> &fl, Bool &flr )
361  {
362    DataHolder::accumulate( id, sp, fl, flr ) ;
363    isFilled[id] = True ;
364  }
365  virtual void post()
366  {
367    postData() ;
368    postFlag() ;
369    postFlagRow() ;
370    postAuxiliary() ;
371  }
372  virtual void reset()
373  {
374    DataHolder::reset() ;
375    for ( uInt i = 0 ; i < 4 ; i++ )
376      isFilled[i] = False ;
377  }
378protected:
379  virtual void postFlag()
380  {
381    if ( npol == 4 ) {
382      Vector<Bool> tmp = flag.row( 3 ) ;
383      flag.row( 3 ) = flag.row( 1 ) ;
384      flag.row( 2 ) = flag.row( 2 ) || tmp ;
385      flag.row( 1 ) = flag.row( 2 ) ;
386      flagRF.define( flag ) ;
387    }
388    else {
389      flagRF.define( flag( IPosition( 2, 0, 0 ), IPosition( 2, npol-1, nchan-1 ) ) ) ;
390    }
391  }
392  virtual void postData()
393  {
394    Matrix<Float> tmp( 2, nchan, 0.0 ) ;
395    Matrix<Complex> v( npol, nchan ) ;
396    if ( isFilled[0] ) {
397      tmp.row( 0 ) = data.row( 0 ) ;
398      v.row( 0 ) = RealToComplex( tmp ) ;
399    }
400    if ( isFilled[1] ) {
401      tmp.row( 0 ) = data.row( 1 ) ;
402      v.row( npol-1 ) = RealToComplex( tmp ) ;
403    }
404    if ( isFilled[2] && isFilled[3] ) {
405      tmp.row( 0 ) = data.row( 2 ) ;
406      tmp.row( 1 ) = data.row( 3 ) ;
407      v.row( 1 ) = RealToComplex( tmp ) ;
408      v.row( 2 ) = conj( v.row( 1 ) ) ;
409    }
410    dataRF.define( v ) ;
411  }
412private:
413  void attachData()
414  {
415    dataRF.attachToRecord( row.record(), "DATA" ) ;
416  }
417  RecordFieldPtr< Matrix<Complex> > dataRF;
418  Bool isFilled[4] ;
419};
420
421class BaseMSWriterVisitor: public TableVisitor {
422  const String *lastFieldName;
423  uInt lastRecordNo;
424  uInt lastBeamNo, lastScanNo, lastIfNo, lastPolNo;
425  Int lastSrcType;
426  uInt lastCycleNo;
427  Double lastTime;
428protected:
429  const Table &table;
430  uInt count;
431public:
432  BaseMSWriterVisitor(const Table &table)
433    : table(table)
434  {
435    static const String dummy;
436    lastFieldName = &dummy;
437    count = 0;
438  }
439 
440  virtual void enterFieldName(const uInt recordNo, const String &columnValue) {
441  }
442  virtual void leaveFieldName(const uInt recordNo, const String &columnValue) {
443  }
444  virtual void enterBeamNo(const uInt recordNo, uInt columnValue) { }
445  virtual void leaveBeamNo(const uInt recordNo, uInt columnValue) { }
446  virtual void enterScanNo(const uInt recordNo, uInt columnValue) { }
447  virtual void leaveScanNo(const uInt recordNo, uInt columnValue) { }
448  virtual void enterIfNo(const uInt recordNo, uInt columnValue) { }
449  virtual void leaveIfNo(const uInt recordNo, uInt columnValue) { }
450  virtual void enterSrcType(const uInt recordNo, Int columnValue) { }
451  virtual void leaveSrcType(const uInt recordNo, Int columnValue) { }
452  virtual void enterCycleNo(const uInt recordNo, uInt columnValue) { }
453  virtual void leaveCycleNo(const uInt recordNo, uInt columnValue) { }
454  virtual void enterTime(const uInt recordNo, Double columnValue) { }
455  virtual void leaveTime(const uInt recordNo, Double columnValue) { }
456  virtual void enterPolNo(const uInt recordNo, uInt columnValue) { }
457  virtual void leavePolNo(const uInt recordNo, uInt columnValue) { }
458
459  virtual Bool visitRecord(const uInt recordNo,
460                           const String &fieldName,
461                           const uInt beamNo,
462                           const uInt scanNo,
463                           const uInt ifNo,
464                           const Int srcType,
465                           const uInt cycleNo,
466                           const Double time,
467                           const uInt polNo) { return True ;}
468
469  virtual Bool visit(Bool isFirst, const uInt recordNo,
470                     const uInt nCols, void const *const colValues[]) {
471    const String *fieldName = NULL;
472    uInt beamNo, scanNo, ifNo;
473    Int srcType;
474    uInt cycleNo;
475    Double time;
476    uInt polNo;
477    { // prologue
478      uInt i = 0;
479      {
480        const String *col = (const String*)colValues[i++];
481        fieldName = &col[recordNo];
482      }
483      {
484        const uInt *col = (const uInt *)colValues[i++];
485        beamNo = col[recordNo];
486      }
487      {
488        const uInt *col = (const uInt *)colValues[i++];
489        scanNo = col[recordNo];
490      }
491      {
492        const uInt *col = (const uInt *)colValues[i++];
493        ifNo = col[recordNo];
494      }
495      {
496        const Int *col = (const Int *)colValues[i++];
497        srcType = col[recordNo];
498      }
499      {
500        const uInt *col = (const uInt *)colValues[i++];
501        cycleNo = col[recordNo];
502      }
503      {
504        const Double *col = (const Double *)colValues[i++];
505        time = col[recordNo];
506      }
507      {
508        const Int *col = (const Int *)colValues[i++];
509        polNo = col[recordNo];
510      }
511      assert(nCols == i);
512    }
513
514    if (isFirst) {
515      enterFieldName(recordNo, *fieldName);
516      enterBeamNo(recordNo, beamNo);
517      enterScanNo(recordNo, scanNo);
518      enterIfNo(recordNo, ifNo);
519      enterSrcType(recordNo, srcType);
520      enterCycleNo(recordNo, cycleNo);
521      enterTime(recordNo, time);
522      enterPolNo(recordNo, polNo);
523    } else {
524      if (lastFieldName->compare(*fieldName) != 0) {
525        leavePolNo(lastRecordNo, lastPolNo);
526        leaveTime(lastRecordNo, lastTime);
527        leaveCycleNo(lastRecordNo, lastCycleNo);
528        leaveSrcType(lastRecordNo, lastSrcType);
529        leaveIfNo(lastRecordNo, lastIfNo);
530        leaveScanNo(lastRecordNo, lastScanNo);
531        leaveBeamNo(lastRecordNo, lastBeamNo);
532        leaveFieldName(lastRecordNo, *lastFieldName);
533
534        enterFieldName(recordNo, *fieldName);
535        enterBeamNo(recordNo, beamNo);
536        enterScanNo(recordNo, scanNo);
537        enterIfNo(recordNo, ifNo);
538        enterSrcType(recordNo, srcType);
539        enterCycleNo(recordNo, cycleNo);
540        enterTime(recordNo, time);
541        enterPolNo(recordNo, polNo);
542      } else if (lastBeamNo != beamNo) {
543        leavePolNo(lastRecordNo, lastPolNo);
544        leaveTime(lastRecordNo, lastTime);
545        leaveCycleNo(lastRecordNo, lastCycleNo);
546        leaveSrcType(lastRecordNo, lastSrcType);
547        leaveIfNo(lastRecordNo, lastIfNo);
548        leaveScanNo(lastRecordNo, lastScanNo);
549        leaveBeamNo(lastRecordNo, lastBeamNo);
550
551        enterBeamNo(recordNo, beamNo);
552        enterScanNo(recordNo, scanNo);
553        enterIfNo(recordNo, ifNo);
554        enterSrcType(recordNo, srcType);
555        enterCycleNo(recordNo, cycleNo);
556        enterTime(recordNo, time);
557        enterPolNo(recordNo, polNo);
558      } else if (lastScanNo != scanNo) {
559        leavePolNo(lastRecordNo, lastPolNo);
560        leaveTime(lastRecordNo, lastTime);
561        leaveCycleNo(lastRecordNo, lastCycleNo);
562        leaveSrcType(lastRecordNo, lastSrcType);
563        leaveIfNo(lastRecordNo, lastIfNo);
564        leaveScanNo(lastRecordNo, lastScanNo);
565
566        enterScanNo(recordNo, scanNo);
567        enterIfNo(recordNo, ifNo);
568        enterSrcType(recordNo, srcType);
569        enterCycleNo(recordNo, cycleNo);
570        enterTime(recordNo, time);
571        enterPolNo(recordNo, polNo);
572      } else if (lastIfNo != ifNo) {
573        leavePolNo(lastRecordNo, lastPolNo);
574        leaveTime(lastRecordNo, lastTime);
575        leaveCycleNo(lastRecordNo, lastCycleNo);
576        leaveSrcType(lastRecordNo, lastSrcType);
577        leaveIfNo(lastRecordNo, lastIfNo);
578
579        enterIfNo(recordNo, ifNo);
580        enterSrcType(recordNo, srcType);
581        enterCycleNo(recordNo, cycleNo);
582        enterTime(recordNo, time);
583        enterPolNo(recordNo, polNo);
584      } else if (lastSrcType != srcType) {
585        leavePolNo(lastRecordNo, lastPolNo);
586        leaveTime(lastRecordNo, lastTime);
587        leaveCycleNo(lastRecordNo, lastCycleNo);
588        leaveSrcType(lastRecordNo, lastSrcType);
589
590        enterSrcType(recordNo, srcType);
591        enterCycleNo(recordNo, cycleNo);
592        enterTime(recordNo, time);
593        enterPolNo(recordNo, polNo);
594      } else if (lastCycleNo != cycleNo) {
595        leavePolNo(lastRecordNo, lastPolNo);
596        leaveTime(lastRecordNo, lastTime);
597        leaveCycleNo(lastRecordNo, lastCycleNo);
598
599        enterCycleNo(recordNo, cycleNo);
600        enterTime(recordNo, time);
601        enterPolNo(recordNo, polNo);
602      } else if (lastTime != time) {
603        leavePolNo(lastRecordNo, lastPolNo);
604        leaveTime(lastRecordNo, lastTime);
605
606        enterTime(recordNo, time);
607        enterPolNo(recordNo, polNo);
608      } else if (lastPolNo != polNo) {
609        leavePolNo(lastRecordNo, lastPolNo);
610        enterPolNo(recordNo, polNo);
611      }
612    }
613    count++;
614    Bool result = visitRecord(recordNo, *fieldName, beamNo, scanNo, ifNo, srcType,
615                              cycleNo, time, polNo);
616
617    { // epilogue
618      lastRecordNo = recordNo;
619
620      lastFieldName = fieldName;
621      lastBeamNo = beamNo;
622      lastScanNo = scanNo;
623      lastIfNo = ifNo;
624      lastSrcType = srcType;
625      lastCycleNo = cycleNo;
626      lastTime = time;
627      lastPolNo = polNo;
628    }
629    return result ;
630  }
631
632  virtual void finish() {
633    if (count > 0) {
634      leavePolNo(lastRecordNo, lastPolNo);
635      leaveTime(lastRecordNo, lastTime);
636      leaveCycleNo(lastRecordNo, lastCycleNo);
637      leaveSrcType(lastRecordNo, lastSrcType);
638      leaveIfNo(lastRecordNo, lastIfNo);
639      leaveScanNo(lastRecordNo, lastScanNo);
640      leaveBeamNo(lastRecordNo, lastBeamNo);
641      leaveFieldName(lastRecordNo, *lastFieldName);
642    }
643  }
644};
645
646class MSWriterVisitor: public BaseMSWriterVisitor, public MSWriterUtils {
647public:
648  MSWriterVisitor(const Table &table, Table &mstable)
649    : BaseMSWriterVisitor(table),
650      ms(mstable)
651  {
652    rowidx = 0 ;
653    fieldName = "" ;
654    defaultFieldId = 0 ;
655    spwId = -1 ;
656    subscan = 1 ;
657    ptName = "" ;
658    srcId = 0 ;
659   
660    row = TableRow( ms ) ;
661
662    initPolarization() ;
663    initFrequencies() ;
664
665    //
666    // add rows to MS
667    //
668    uInt addrow = table.nrow() ;
669    ms.addRow( addrow ) ;
670
671    // attach to Scantable columns
672    spectraCol.attach( table, "SPECTRA" ) ;
673    flagtraCol.attach( table, "FLAGTRA" ) ;
674    flagRowCol.attach( table, "FLAGROW" ) ;
675    tcalIdCol.attach( table, "TCAL_ID" ) ;
676    intervalCol.attach( table, "INTERVAL" ) ;
677    directionCol.attach( table, "DIRECTION" ) ;
678    scanRateCol.attach( table, "SCANRATE" ) ;
679    timeCol.attach( table, "TIME" ) ;
680    freqIdCol.attach( table, "FREQ_ID" ) ;
681    sourceNameCol.attach( table, "SRCNAME" ) ;
682    sourceDirectionCol.attach( table, "SRCDIRECTION" ) ;
683    fieldNameCol.attach( table, "FIELDNAME" ) ;
684
685    // MS subtables
686    attachSubtables() ;
687
688    // attach to MS columns
689    attachMain() ;
690    attachPointing() ;
691  }
692 
693  virtual void enterFieldName(const uInt recordNo, const String &columnValue) {
694    //printf("%u: FieldName: %s\n", recordNo, columnValue.c_str());
695    fieldName = fieldNameCol.asString( recordNo ) ;
696    String::size_type pos = fieldName.find( "__" ) ;
697    if ( pos != String::npos ) {
698      fieldId = String::toInt( fieldName.substr( pos+2 ) ) ;
699      fieldName = fieldName.substr( 0, pos ) ;
700    }
701    else {
702      fieldId = defaultFieldId ;
703      defaultFieldId++ ;
704    }
705    Double tSec = timeCol.asdouble( recordNo ) * 86400.0 ;
706    Vector<Double> srcDir = sourceDirectionCol( recordNo ) ;
707    Vector<Double> srate = scanRateCol( recordNo ) ;
708    String srcName = sourceNameCol.asString( recordNo ) ;
709
710    addField( fieldId, fieldName, srcName, srcDir, srate, tSec ) ;
711
712    // put value
713    *fieldIdRF = fieldId ;
714  }
715  virtual void leaveFieldName(const uInt recordNo, const String &columnValue) {
716  }
717  virtual void enterBeamNo(const uInt recordNo, uInt columnValue) {
718    //printf("%u: BeamNo: %u\n", recordNo, columnValue);
719   
720    feedId = (Int)columnValue ;
721
722    // put value
723    *feed1RF = feedId ;
724    *feed2RF = feedId ;
725  }
726  virtual void leaveBeamNo(const uInt recordNo, uInt columnValue) {
727  }
728  virtual void enterScanNo(const uInt recordNo, uInt columnValue) {
729    //printf("%u: ScanNo: %u\n", recordNo, columnValue);
730
731    // put value
732    // SCAN_NUMBER is 0-based in Scantable while 1-based in MS
733    *scanNumberRF = (Int)columnValue + 1 ;
734  }
735  virtual void leaveScanNo(const uInt recordNo, uInt columnValue) {
736    subscan = 1 ;
737  }
738  virtual void enterIfNo(const uInt recordNo, uInt columnValue) {
739    //printf("%u: IfNo: %u\n", recordNo, columnValue);
740
741    spwId = (Int)columnValue ;
742    uInt freqId = freqIdCol.asuInt( recordNo ) ;
743
744    Vector<Float> sp = spectraCol( recordNo ) ;
745    uInt nchan = sp.nelements() ;
746    holder->setNchan( nchan ) ;
747
748    addSpectralWindow( spwId, freqId ) ;
749
750    addFeed( feedId, spwId ) ;
751  }
752  virtual void leaveIfNo(const uInt recordNo, uInt columnValue) {
753  }
754  virtual void enterSrcType(const uInt recordNo, Int columnValue) {
755    //printf("%u: SrcType: %d\n", recordNo, columnValue);
756
757    Int stateId = addState( columnValue ) ;
758
759    // put value
760    *stateIdRF = stateId ;
761  }
762  virtual void leaveSrcType(const uInt recordNo, Int columnValue) {
763  }
764  virtual void enterCycleNo(const uInt recordNo, uInt columnValue) {
765    //printf("%u: CycleNo: %u\n", recordNo, columnValue);
766  }
767  virtual void leaveCycleNo(const uInt recordNo, uInt columnValue) {
768  }
769  virtual void enterTime(const uInt recordNo, Double columnValue) {
770    //printf("%u: Time: %f\n", recordNo, columnValue);
771
772    Double timeSec = columnValue * 86400.0 ;
773    Double interval = intervalCol.asdouble( recordNo ) ;
774
775    if ( ptName.empty() ) {
776      Vector<Double> dir = directionCol( recordNo ) ;
777      Vector<Double> rate = scanRateCol( recordNo ) ;
778      if ( anyNE( rate, 0.0 ) ) {
779        Matrix<Double> msdir( 2, 2 ) ;
780        msdir.column( 0 ) = dir ;
781        msdir.column( 1 ) = rate ;
782        addPointing( timeSec, interval, msdir ) ;
783      }
784      else {
785        Matrix<Double> msdir( 2, 1 ) ;
786        msdir.column( 0 ) = dir ;
787        addPointing( timeSec, interval, msdir ) ;
788      }
789    }
790
791    // put value
792    *timeRF = timeSec ;
793    *timeCentroidRF = timeSec ;
794    *intervalRF = interval ;
795    *exposureRF = interval ;
796  }
797  virtual void leaveTime(const uInt recordNo, Double columnValue) {
798    if ( holder->nPol() > 0 ) {
799      Int polId = addPolarization() ;
800      Int ddId = addDataDescription( polId, spwId ) ;
801       
802      // put field
803      *dataDescIdRF = ddId ;
804      holder->post() ;
805     
806      // commit row
807      row.put( rowidx ) ;
808      rowidx++ ;
809
810      // reset holder
811      holder->reset() ;
812    }
813  }
814  virtual void enterPolNo(const uInt recordNo, uInt columnValue) {
815    //printf("%u: PolNo: %d\n", recordNo, columnValue);
816  }
817  virtual void leavePolNo(const uInt recordNo, uInt columnValue) {
818  }
819
820  virtual Bool visitRecord(const uInt recordNo,
821                           const String &fieldName,
822                           const uInt beamNo,
823                           const uInt scanNo,
824                           const uInt ifNo,
825                           const Int srcType,
826                           const uInt cycleNo,
827                           const Double time,
828                           const uInt polNo) {
829    //printf("%u: %s, %u, %u, %u, %d, %u, %f, %d\n", recordNo,
830    //       fieldName.c_str(), beamNo, scanNo, ifNo, srcType, cycleNo, time, polNo);
831
832    Vector<Float> sp = spectraCol( recordNo ) ;
833    Vector<uChar> tmp = flagtraCol( recordNo ) ;
834    Vector<Bool> fl( tmp.shape() ) ;
835    convertArray( fl, tmp ) ;
836    Bool flr = (Bool)flagRowCol.asuInt( recordNo ) ;
837    holder->accumulate( polNo, sp, fl, flr ) ;
838
839    return True ;
840  }
841
842  virtual void finish() {
843    BaseMSWriterVisitor::finish();
844    //printf("Total: %u\n", count);
845
846    // remove rows
847    if ( ms.nrow() > rowidx ) {
848      uInt numRemove = ms.nrow() - rowidx ;
849      //cout << "numRemove = " << numRemove << endl ;
850      Vector<uInt> rows( numRemove ) ;
851      indgen( rows, rowidx ) ;
852      ms.removeRow( rows ) ;
853    }
854
855    // fill empty SPECTRAL_WINDOW rows
856    infillSpectralWindow() ;
857  }
858
859  void dataColumnName( String name )
860  {
861    if ( name == "DATA" )
862      holder = new ComplexDataHolder( row, poltype ) ;
863    else if ( name == "FLOAT_DATA" )
864      holder = new FloatDataHolder( row, poltype ) ;
865  }
866  void pointingTableName( String name ) {
867    ptName = name ;
868  }
869  void setSourceRecord( Record &r ) {
870    srcRec = r ;
871  }
872private:
873  void addField( Int &fid, String &fname, String &srcName,
874                 Vector<Double> &sdir, Vector<Double> &srate,
875                 Double &tSec )
876  {
877    uInt nrow = fieldtab.nrow() ;
878    while( (Int)nrow <= fid ) {
879      fieldtab.addRow( 1, True ) ;
880      nrow++ ;
881    }
882
883    Matrix<Double> dir ;
884    Int numPoly = 0 ;
885    if ( anyNE( srate, 0.0 ) ) {
886      dir.resize( 2, 2 ) ;
887      dir.column( 0 ) = sdir ;
888      dir.column( 1 ) = srate ;
889      numPoly = 1 ;
890    }
891    else {
892      dir.resize( 2, 1 ) ;
893      dir.column( 0 ) = sdir ;
894    }
895    srcId = srcRec.asInt( srcName ) ;
896
897    TableRow tr( fieldtab ) ;
898    TableRecord &r = tr.record() ;
899    putField( "NAME", r, fname ) ;
900    putField( "NUM_POLY", r, numPoly ) ;
901    putField( "TIME", r, tSec ) ;
902    putField( "SOURCE_ID", r, srcId ) ;
903    defineField( "DELAY_DIR", r, dir ) ;
904    defineField( "REFERENCE_DIR", r, dir ) ;
905    defineField( "PHASE_DIR", r, dir ) ;
906    tr.put( fid ) ;
907
908    // for POINTING table
909    *poNameRF = fname ;
910  }
911  Int addState( Int &id )
912  {
913    String obsMode ;
914    Bool isSignal ;
915    Double tnoise ;
916    Double tload ;
917    queryType( id, obsMode, isSignal, tnoise, tload ) ;
918
919    String key = obsMode+"_"+String::toString( subscan ) ;
920    Int idx = -1 ;
921    uInt nEntry = stateEntry.nelements() ;
922    for ( uInt i = 0 ; i < nEntry ; i++ ) {
923      if ( stateEntry[i] == key ) {
924        idx = i ;
925        break ;
926      }
927    }
928    if ( idx == -1 ) {
929      uInt nrow = statetab.nrow() ;
930      statetab.addRow( 1, True ) ;
931      TableRow tr( statetab ) ;
932      TableRecord &r = tr.record() ;
933      putField( "OBS_MODE", r, obsMode ) ;
934      putField( "SIG", r, isSignal ) ;
935      isSignal = !isSignal ;
936      putField( "REF", r, isSignal ) ;
937      putField( "CAL", r, tnoise ) ;
938      putField( "LOAD", r, tload ) ;
939      tr.put( nrow ) ;
940      idx = nrow ;
941
942      stateEntry.resize( nEntry+1, True ) ;
943      stateEntry[nEntry] = key ;
944    }
945    subscan++ ;
946
947    return idx ;
948  }
949  void addPointing( Double &tSec, Double &interval, Matrix<Double> &dir )
950  {
951    uInt nrow = potab.nrow() ;
952    potab.addRow() ;
953
954    *poNumPolyRF = dir.ncolumn() - 1 ;
955    *poTimeRF = tSec ;
956    *poTimeOriginRF = tSec ;
957    *poIntervalRF = interval ;
958    poDirectionRF.define( dir ) ;
959    poTargetRF.define( dir ) ;
960    porow.put( nrow ) ;
961  }
962  Int addPolarization()
963  {
964    Int idx = -1 ;
965    Vector<Int> corrType = holder->corrTypeInt() ;
966    uInt nEntry = polEntry.size() ;
967    for ( uInt i = 0 ; i < nEntry ; i++ ) {
968      if ( polEntry[i].conform( corrType ) && allEQ( polEntry[i], corrType ) ) {
969        idx = i ;
970        break ;
971      }
972    }
973   
974    Int numCorr = holder->nPol() ;
975    Matrix<Int> corrProduct = corrProductTemplate[numCorr] ;
976
977    if ( idx == -1 ) {
978      uInt nrow = poltab.nrow() ;
979      poltab.addRow( 1, True ) ;
980      TableRow tr( poltab ) ;
981      TableRecord &r = tr.record() ;
982      putField( "NUM_CORR", r, numCorr ) ;
983      defineField( "CORR_TYPE", r, corrType ) ;
984      defineField( "CORR_PRODUCT", r, corrProduct ) ;
985      tr.put( nrow ) ;
986      idx = nrow ;
987
988      polEntry.resize( nEntry+1 ) ;
989      polEntry[nEntry] = corrType ;
990    }
991
992    return idx ;
993  }
994  Int addDataDescription( Int pid, Int sid )
995  {
996    Int idx = -1 ;
997    uInt nItem = 2 ;
998    uInt len = ddEntry.nelements() ;
999    uInt nEntry = len / nItem ;
1000    const Int *dd_p = ddEntry.storage() ;
1001    for ( uInt i = 0 ; i < nEntry ; i++ ) {
1002      Int pol = *dd_p ;
1003      dd_p++ ;
1004      Int spw = *dd_p ;
1005      dd_p++ ;
1006      if ( pid == pol && sid == spw ) {
1007        idx = i ;
1008        break ;
1009      }
1010    }
1011
1012    if ( idx == -1 ) {
1013      uInt nrow = ddtab.nrow() ;
1014      ddtab.addRow( 1, True ) ;
1015      TableRow tr( ddtab ) ;
1016      TableRecord &r = tr.record() ;
1017      putField( "POLARIZATION_ID", r, pid ) ;
1018      putField( "SPECTRAL_WINDOW_ID", r, sid ) ;
1019      tr.put( nrow ) ;
1020      idx = nrow ;
1021
1022      ddEntry.resize( len+nItem ) ;
1023      ddEntry[len] = pid ;
1024      ddEntry[len+1] = sid ;
1025    }
1026
1027    return idx ;
1028  }
1029  void infillSpectralWindow()
1030  {
1031    ROScalarColumn<Int> nchanCol( spwtab, "NUM_CHAN" ) ;
1032    Vector<Int> nchan = nchanCol.getColumn() ;
1033    TableRow tr( spwtab ) ;
1034    TableRecord &r = tr.record() ;
1035    Int mfr = 1 ;
1036    Vector<Double> dummy( 1, 0.0 ) ;
1037    putField( "MEAS_FREQ_REF", r, mfr ) ;
1038    defineField( "CHAN_FREQ", r, dummy ) ;
1039    defineField( "CHAN_WIDTH", r, dummy ) ;
1040    defineField( "EFFECTIVE_BW", r, dummy ) ;
1041    defineField( "RESOLUTION", r, dummy ) ;
1042
1043    for ( uInt i = 0 ; i < spwtab.nrow() ; i++ ) {
1044      if ( nchan[i] == 0 )
1045        tr.put( i ) ;
1046    }
1047  }
1048  void addSpectralWindow( Int sid, uInt fid )
1049  {
1050    if ( !processedFreqId[fid] ) {
1051      uInt nrow = spwtab.nrow() ;
1052      while( (Int)nrow <= sid ) {
1053        spwtab.addRow( 1, True ) ;
1054        nrow++ ;
1055      }
1056      processedFreqId[fid] = True ;
1057    }
1058    else {
1059      return ;
1060    }
1061
1062    Double rp = refpix[fid] ;
1063    Double rv = refval[fid] ;
1064    Double ic = increment[fid] ;
1065
1066    Int mfrInt = (Int)freqframe ;
1067    Int nchan = holder->nChan() ;
1068    Double bw = nchan * abs( ic ) ;
1069    Double reffreq = rv - rp * ic ;
1070    Int netsb = 0 ; // USB->0, LSB->1
1071    if ( ic < 0 )
1072      netsb = 1 ;
1073    Vector<Double> res( nchan, abs(ic) ) ;
1074    Vector<Double> cw( nchan, ic ) ;
1075    Vector<Double> chanf( nchan ) ;
1076    indgen( chanf, reffreq, ic ) ;
1077
1078    TableRow tr( spwtab ) ;
1079    TableRecord &r = tr.record() ;
1080    putField( "MEAS_FREQ_REF", r, mfrInt ) ;
1081    putField( "NUM_CHAN", r, nchan ) ;
1082    putField( "TOTAL_BANDWIDTH", r, bw ) ;
1083    putField( "REF_FREQUENCY", r, reffreq ) ;
1084    putField( "NET_SIDEBAND", r, netsb ) ;
1085    defineField( "RESOLUTION", r, res ) ;
1086//     defineField( "CHAN_WIDTH", r, res ) ;
1087    defineField( "CHAN_WIDTH", r, cw ) ;
1088    defineField( "EFFECTIVE_BW", r, res ) ;
1089    defineField( "CHAN_FREQ", r, chanf ) ;
1090    tr.put( sid ) ;
1091  }
1092  void addFeed( Int fid, Int sid )
1093  {
1094    Int idx = -1 ;
1095    uInt nItem = 2 ;
1096    uInt len = feedEntry.nelements() ;
1097    uInt nEntry = len / nItem ;
1098    const Int *fe_p = feedEntry.storage() ;
1099    for ( uInt i = 0 ; i < nEntry ; i++ ) {
1100      Int feed = *fe_p ;
1101      fe_p++ ;
1102      Int spw = *fe_p ;
1103      fe_p++ ;
1104      if ( fid == feed && sid == spw ) {
1105        idx = i ;
1106        break ;
1107      }
1108    }
1109
1110
1111    if ( idx == -1 ) {
1112      uInt nrow = feedtab.nrow() ;
1113      feedtab.addRow( 1, True ) ;
1114      Int numReceptors = 2 ;
1115      Vector<String> polType( numReceptors ) ;
1116      Matrix<Double> beamOffset( 2, numReceptors, 0.0 ) ;
1117      Vector<Double> receptorAngle( numReceptors, 0.0 ) ;
1118      if ( poltype == "linear" ) {
1119        polType[0] = "X" ;
1120        polType[1] = "Y" ;
1121      }
1122      else if ( poltype == "circular" ) {
1123        polType[0] = "R" ;
1124        polType[1] = "L" ;
1125      }
1126      else {
1127        polType[0] = "X" ;
1128        polType[1] = "Y" ;
1129      }
1130      Matrix<Complex> polResponse( numReceptors, numReceptors, 0.0 ) ;
1131     
1132      TableRow tr( feedtab ) ;
1133      TableRecord &r = tr.record() ;
1134      putField( "FEED_ID", r, fid ) ;
1135      putField( "BEAM_ID", r, fid ) ;
1136      Int tmp = 0 ;
1137      putField( "ANTENNA_ID", r, tmp ) ;
1138      putField( "SPECTRAL_WINDOW_ID", r, sid ) ;
1139      putField( "NUM_RECEPTORS", r, numReceptors ) ;
1140      defineField( "POLARIZATION_TYPE", r, polType ) ;
1141      defineField( "BEAM_OFFSET", r, beamOffset ) ;
1142      defineField( "RECEPTOR_ANGLE", r, receptorAngle ) ;
1143      defineField( "POL_RESPONSE", r, polResponse ) ;
1144      tr.put( nrow ) ;
1145
1146      feedEntry.resize( len+nItem ) ;
1147      feedEntry[len] = fid ;
1148      feedEntry[len+1] = sid ;
1149    }
1150  }
1151  void initPolarization()
1152  {
1153    const TableRecord &keys = table.keywordSet() ;
1154    poltype = keys.asString( "POLTYPE" ) ;
1155
1156    initCorrProductTemplate() ;
1157  }
1158  void initFrequencies()
1159  {
1160    const TableRecord &keys = table.keywordSet() ;
1161    Table tab = keys.asTable( "FREQUENCIES" ) ;
1162    ROScalarColumn<uInt> idcol( tab, "ID" ) ;
1163    ROScalarColumn<Double> rpcol( tab, "REFPIX" ) ;
1164    ROScalarColumn<Double> rvcol( tab, "REFVAL" ) ;
1165    ROScalarColumn<Double> iccol( tab, "INCREMENT" ) ;
1166    Vector<uInt> id = idcol.getColumn() ;
1167    Vector<Double> rp = rpcol.getColumn() ;
1168    Vector<Double> rv = rvcol.getColumn() ;
1169    Vector<Double> ic = iccol.getColumn() ;
1170    for ( uInt i = 0 ; i < id.nelements() ; i++ ) {
1171      processedFreqId.insert( pair<uInt,Bool>( id[i], False ) ) ;
1172      refpix.insert( pair<uInt,Double>( id[i], rp[i] ) ) ;
1173      refval.insert( pair<uInt,Double>( id[i], rv[i] ) ) ;
1174      increment.insert( pair<uInt,Double>( id[i], ic[i] ) ) ;
1175    }
1176    String frameStr = tab.keywordSet().asString( "BASEFRAME" ) ;
1177    MFrequency::getType( freqframe, frameStr ) ;
1178  }
1179  void attachSubtables()
1180  {
1181    const TableRecord &keys = table.keywordSet() ;
1182    TableRecord &mskeys = ms.rwKeywordSet() ;
1183
1184    // FIELD table
1185    fieldtab = mskeys.asTable( "FIELD" ) ;
1186
1187    // SPECTRAL_WINDOW table
1188    spwtab = mskeys.asTable( "SPECTRAL_WINDOW" ) ;
1189
1190    // POINTING table
1191    potab = mskeys.asTable( "POINTING" ) ;
1192
1193    // POLARIZATION table
1194    poltab = mskeys.asTable( "POLARIZATION" ) ;
1195
1196    // DATA_DESCRIPTION table
1197    ddtab = mskeys.asTable( "DATA_DESCRIPTION" ) ;
1198
1199    // STATE table
1200    statetab = mskeys.asTable( "STATE" ) ;
1201
1202    // FEED table
1203    feedtab = mskeys.asTable( "FEED" ) ;
1204  }
1205  void attachMain()
1206  {
1207    TableRecord &r = row.record() ;
1208    dataDescIdRF.attachToRecord( r, "DATA_DESC_ID" ) ;
1209    timeRF.attachToRecord( r, "TIME" ) ;
1210    timeCentroidRF.attachToRecord( r, "TIME_CENTROID" ) ;
1211    intervalRF.attachToRecord( r, "INTERVAL" ) ;
1212    exposureRF.attachToRecord( r, "EXPOSURE" ) ;
1213    fieldIdRF.attachToRecord( r, "FIELD_ID" ) ;
1214    feed1RF.attachToRecord( r, "FEED1" ) ;
1215    feed2RF.attachToRecord( r, "FEED2" ) ;
1216    scanNumberRF.attachToRecord( r, "SCAN_NUMBER" ) ;
1217    stateIdRF.attachToRecord( r, "STATE_ID" ) ;
1218
1219    // constant values
1220    Int id = 0 ;
1221    RecordFieldPtr<Int> intRF( r, "OBSERVATION_ID" ) ;
1222    *intRF = 0 ;
1223    intRF.attachToRecord( r, "ANTENNA1" ) ;
1224    *intRF = 0 ;
1225    intRF.attachToRecord( r, "ANTENNA2" ) ;
1226    *intRF = 0 ;
1227    intRF.attachToRecord( r, "ARRAY_ID" ) ;
1228    *intRF = 0 ;
1229    intRF.attachToRecord( r, "PROCESSOR_ID" ) ;
1230    *intRF = 0 ;
1231    RecordFieldPtr< Vector<Double> > arrayRF( r, "UVW" ) ;
1232    arrayRF.define( Vector<Double>( 3, 0.0 ) ) ;
1233  }
1234  void attachPointing()
1235  {
1236    porow = TableRow( potab ) ;
1237    TableRecord &r = porow.record() ;
1238    poNumPolyRF.attachToRecord( r, "NUM_POLY" ) ;
1239    poTimeRF.attachToRecord( r, "TIME" ) ;
1240    poTimeOriginRF.attachToRecord( r, "TIME_ORIGIN" ) ;
1241    poIntervalRF.attachToRecord( r, "INTERVAL" ) ;
1242    poNameRF.attachToRecord( r, "NAME" ) ;
1243    poDirectionRF.attachToRecord( r, "DIRECTION" ) ;
1244    poTargetRF.attachToRecord( r, "TARGET" ) ;
1245   
1246    // constant values
1247    RecordFieldPtr<Int> antIdRF( r, "ANTENNA_ID" ) ;
1248    *antIdRF = 0 ;
1249    RecordFieldPtr<Bool> trackingRF( r, "TRACKING" ) ;
1250    *trackingRF = True ;
1251  }
1252  void queryType( Int type, String &stype, Bool &b, Double &t, Double &l )
1253  {
1254    t = 0.0 ;
1255    l = 0.0 ;
1256
1257    String sep1="#" ;
1258    String sep2="," ;
1259    String target="OBSERVE_TARGET" ;
1260    String atmcal="CALIBRATE_TEMPERATURE" ;
1261    String onstr="ON_SOURCE" ;
1262    String offstr="OFF_SOURCE" ;
1263    String pswitch="POSITION_SWITCH" ;
1264    String nod="NOD" ;
1265    String fswitch="FREQUENCY_SWITCH" ;
1266    String sigstr="SIG" ;
1267    String refstr="REF" ;
1268    String unspecified="UNSPECIFIED" ;
1269    String ftlow="LOWER" ;
1270    String fthigh="HIGHER" ;
1271    switch ( type ) {
1272    case SrcType::PSON:
1273      stype = target+sep1+onstr+sep2+pswitch ;
1274      b = True ;
1275      break ;
1276    case SrcType::PSOFF:
1277      stype = target+sep1+offstr+sep2+pswitch ;
1278      b = False ;
1279      break ;
1280    case SrcType::NOD:
1281      stype = target+sep1+onstr+sep2+nod ;
1282      b = True ;
1283      break ;
1284    case SrcType::FSON:
1285      stype = target+sep1+onstr+sep2+fswitch+sep1+sigstr ;
1286      b = True ;
1287      break ;
1288    case SrcType::FSOFF:
1289      stype = target+sep1+onstr+sep2+fswitch+sep1+refstr ;
1290      b = False ;
1291      break ;
1292    case SrcType::SKY:
1293      stype = atmcal+sep1+offstr+sep2+unspecified ;
1294      b = False ;
1295      break ;
1296    case SrcType::HOT:
1297      stype = atmcal+sep1+offstr+sep2+unspecified ;
1298      b = False ;
1299      break ;
1300    case SrcType::WARM:
1301      stype = atmcal+sep1+offstr+sep2+unspecified ;
1302      b = False ;
1303      break ;
1304    case SrcType::COLD:
1305      stype = atmcal+sep1+offstr+sep2+unspecified ;
1306      b = False ;
1307      break ;
1308    case SrcType::PONCAL:
1309      stype = atmcal+sep1+onstr+sep2+pswitch ;
1310      b = True ;
1311      break ;
1312    case SrcType::POFFCAL:
1313      stype = atmcal+sep1+offstr+sep2+pswitch ;
1314      b = False ;
1315      break ;
1316    case SrcType::NODCAL:
1317      stype = atmcal+sep1+onstr+sep2+nod ;
1318      b = True ;
1319      break ;
1320    case SrcType::FONCAL:
1321      stype = atmcal+sep1+onstr+sep2+fswitch+sep1+sigstr ;
1322      b = True ;
1323      break ;
1324    case SrcType::FOFFCAL:
1325      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+refstr ;
1326      b = False ;
1327      break ;
1328    case SrcType::FSLO:
1329      stype = target+sep1+onstr+sep2+fswitch+sep1+ftlow ;
1330      b = True ;
1331      break ;
1332    case SrcType::FLOOFF:
1333      stype = target+sep1+offstr+sep2+fswitch+sep1+ftlow ;
1334      b = False ;
1335      break ;
1336    case SrcType::FLOSKY:
1337      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+ftlow ;
1338      b = False ;
1339      break ;
1340    case SrcType::FLOHOT:
1341      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+ftlow ;
1342      b = False ;
1343      break ;
1344    case SrcType::FLOWARM:
1345      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+ftlow ;
1346      b = False ;
1347      break ;
1348    case SrcType::FLOCOLD:
1349      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+ftlow ;
1350      b = False ;
1351      break ;
1352    case SrcType::FSHI:
1353      stype = target+sep1+onstr+sep2+fswitch+sep1+fthigh ;
1354      b = True ;
1355      break ;
1356    case SrcType::FHIOFF:
1357      stype = target+sep1+offstr+sep2+fswitch+sep1+fthigh ;
1358      b = False ;
1359      break ;
1360    case SrcType::FHISKY:
1361      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+fthigh ;
1362      b = False ;
1363      break ;
1364    case SrcType::FHIHOT:
1365      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+fthigh ;
1366      b = False ;
1367      break ;
1368    case SrcType::FHIWARM:
1369      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+fthigh ;
1370      b = False ;
1371      break ;
1372    case SrcType::FHICOLD:
1373      stype = atmcal+sep1+offstr+sep2+fswitch+sep1+fthigh ;
1374      b = False ;
1375      break ;
1376    case SrcType::SIG:
1377      stype = target+sep1+onstr+sep2+unspecified ;
1378      b = True ;
1379      break ;
1380    case SrcType::REF:
1381      stype = target+sep1+offstr+sep2+unspecified ;
1382      b = False ;
1383      break ;
1384    default:
1385      stype = unspecified ;
1386      b = True ;
1387      break ;
1388    }
1389  }
1390  void initCorrProductTemplate()
1391  {
1392    Int n = 1 ;
1393    {
1394      Matrix<Int> c( 2, n, 0 ) ;
1395      corrProductTemplate[n] = c ;
1396    }
1397    n = 2 ;
1398    {
1399      Matrix<Int> c( 2, n, 0 ) ;
1400      c.column( 1 ) = 1 ;
1401      corrProductTemplate[n] = c ;
1402    }
1403    n = 4 ;
1404    {
1405      Matrix<Int> c( 2, n, 0 ) ;
1406      c( 0, 2 ) = 1 ;
1407      c( 0, 3 ) = 1 ;
1408      c( 1, 1 ) = 1 ;
1409      c( 1, 3 ) = 1 ;
1410      corrProductTemplate[n] = c ;
1411    }
1412  }
1413
1414  Table &ms;
1415  TableRow row;
1416  uInt rowidx;
1417  String fieldName;
1418  Int fieldId;
1419  Int srcId;
1420  Int defaultFieldId;
1421  Int spwId;
1422  Int feedId;
1423  Int subscan;
1424  CountedPtr<DataHolder> holder;
1425  String ptName;
1426  Bool useFloat;
1427  String poltype;
1428
1429  // MS subtables
1430  Table spwtab;
1431  Table statetab;
1432  Table ddtab;
1433  Table poltab;
1434  Table fieldtab;
1435  Table feedtab;
1436  Table potab;
1437
1438  // Scantable MAIN columns
1439  ROArrayColumn<Float> spectraCol;
1440  ROArrayColumn<Double> directionCol,scanRateCol,sourceDirectionCol;
1441  ROArrayColumn<uChar> flagtraCol;
1442  ROTableColumn tcalIdCol,intervalCol,flagRowCol,timeCol,freqIdCol,
1443    sourceNameCol,fieldNameCol;
1444
1445  // MS MAIN columns
1446  RecordFieldPtr<Int> dataDescIdRF,fieldIdRF,feed1RF,feed2RF,
1447    scanNumberRF,stateIdRF;
1448  RecordFieldPtr<Double> timeRF,timeCentroidRF,intervalRF,exposureRF;
1449
1450  // MS POINTING columns
1451  TableRow porow;
1452  RecordFieldPtr<Int> poNumPolyRF ;
1453  RecordFieldPtr<Double> poTimeRF,
1454    poTimeOriginRF,
1455    poIntervalRF ;
1456  RecordFieldPtr<String> poNameRF ;
1457  RecordFieldPtr< Matrix<Double> > poDirectionRF,
1458    poTargetRF ;
1459
1460  Vector<String> stateEntry;
1461  Block<Int> ddEntry;
1462  Block<Int> feedEntry;
1463  vector< Vector<Int> > polEntry;
1464  map<uInt,Bool> processedFreqId;
1465  map<uInt,Double> refpix;
1466  map<uInt,Double> refval;
1467  map<uInt,Double> increment;
1468  MFrequency::Types freqframe;
1469  Record srcRec;
1470  map< Int, Matrix<Int> > corrProductTemplate;
1471};
1472
1473class BaseMSSysCalVisitor: public TableVisitor {
1474  uInt lastRecordNo;
1475  uInt lastBeamNo, lastIfNo, lastPolNo;
1476  Double lastTime;
1477protected:
1478  const Table &table;
1479  uInt count;
1480public:
1481  BaseMSSysCalVisitor(const Table &table)
1482    : table(table)
1483  {
1484    count = 0;
1485  }
1486 
1487  virtual void enterBeamNo(const uInt recordNo, uInt columnValue) { }
1488  virtual void leaveBeamNo(const uInt recordNo, uInt columnValue) { }
1489  virtual void enterIfNo(const uInt recordNo, uInt columnValue) { }
1490  virtual void leaveIfNo(const uInt recordNo, uInt columnValue) { }
1491  virtual void enterPolNo(const uInt recordNo, uInt columnValue) { }
1492  virtual void leavePolNo(const uInt recordNo, uInt columnValue) { }
1493  virtual void enterTime(const uInt recordNo, Double columnValue) { }
1494  virtual void leaveTime(const uInt recordNo, Double columnValue) { }
1495
1496  virtual Bool visitRecord(const uInt recordNo,
1497                           const uInt beamNo,
1498                           const uInt ifNo,
1499                           const uInt polNo,
1500                           const Double time) { return True ;}
1501
1502  virtual Bool visit(Bool isFirst, const uInt recordNo,
1503                     const uInt nCols, void const *const colValues[]) {
1504    uInt beamNo, ifNo, polNo;
1505    Double time;
1506    { // prologue
1507      uInt i = 0;
1508      {
1509        const uInt *col = (const uInt *)colValues[i++];
1510        beamNo = col[recordNo];
1511      }
1512      {
1513        const uInt *col = (const uInt *)colValues[i++];
1514        ifNo = col[recordNo];
1515      }
1516      {
1517        const Double *col = (const Double *)colValues[i++];
1518        time = col[recordNo];
1519      }
1520      {
1521        const uInt *col = (const uInt *)colValues[i++];
1522        polNo = col[recordNo];
1523      }
1524      assert(nCols == i);
1525    }
1526
1527    if (isFirst) {
1528      enterBeamNo(recordNo, beamNo);
1529      enterIfNo(recordNo, ifNo);
1530      enterTime(recordNo, time);
1531      enterPolNo(recordNo, polNo);
1532    } else {
1533      if (lastBeamNo != beamNo) {
1534        leavePolNo(lastRecordNo, lastPolNo);
1535        leaveTime(lastRecordNo, lastTime);
1536        leaveIfNo(lastRecordNo, lastIfNo);
1537        leaveBeamNo(lastRecordNo, lastBeamNo);
1538
1539        enterBeamNo(recordNo, beamNo);
1540        enterIfNo(recordNo, ifNo);
1541        enterTime(recordNo, time);
1542        enterPolNo(recordNo, polNo);
1543      } else if (lastIfNo != ifNo) {
1544        leavePolNo(lastRecordNo, lastPolNo);
1545        leaveTime(lastRecordNo, lastTime);
1546        leaveIfNo(lastRecordNo, lastIfNo);
1547       
1548        enterIfNo(recordNo, ifNo);
1549        enterTime(recordNo, time);
1550        enterPolNo(recordNo, polNo);
1551      } else if (lastTime != time) {
1552        leavePolNo(lastRecordNo, lastPolNo);
1553        leaveTime(lastRecordNo, lastTime);
1554
1555        enterTime(recordNo, time);
1556        enterPolNo(recordNo, polNo);
1557      } else if (lastPolNo != polNo) {
1558        leavePolNo(lastRecordNo, lastPolNo);
1559        enterPolNo(recordNo, polNo);
1560      }
1561    }
1562    count++;
1563    Bool result = visitRecord(recordNo, beamNo, ifNo, polNo, time);
1564
1565    { // epilogue
1566      lastRecordNo = recordNo;
1567
1568      lastBeamNo = beamNo;
1569      lastIfNo = ifNo;
1570      lastPolNo = polNo;
1571      lastTime = time;
1572    }
1573    return result ;
1574  }
1575
1576  virtual void finish() {
1577    if (count > 0) {
1578      leavePolNo(lastRecordNo, lastPolNo);
1579      leaveTime(lastRecordNo, lastTime);
1580      leaveIfNo(lastRecordNo, lastIfNo);
1581      leaveBeamNo(lastRecordNo, lastBeamNo);
1582    }
1583  }
1584};
1585
1586class BaseTsysHolder
1587{
1588public:
1589  BaseTsysHolder( ROArrayColumn<Float> &tsysCol )
1590    : col( tsysCol ),
1591      nchan(0)
1592  {
1593    reset() ;
1594  }
1595  virtual ~BaseTsysHolder() {}
1596  virtual Array<Float> getTsys() = 0 ;
1597  void setNchan( uInt n ) { nchan = n ; }
1598  void appendTsys( uInt row )
1599  {
1600    Vector<Float> v = col( row ) ;
1601    uInt len = tsys.nrow() ;
1602    tsys.resize( len+1, nchan, True ) ;
1603    if ( v.nelements() == nchan )
1604      tsys.row( len ) = v ;
1605    else
1606      tsys.row( len ) = v[0] ;
1607  }
1608  void setTsys( uInt row, uInt idx )
1609  {
1610    if ( idx >= nrow() )
1611      appendTsys( row ) ;
1612    else {
1613      Vector<Float> v = col( row ) ;
1614      if ( v.nelements() == nchan )
1615        tsys.row( idx ) = v ;
1616      else
1617        tsys.row( idx ) = v[0] ;
1618    }
1619  }
1620  void reset()
1621  {
1622    tsys.resize() ;
1623  }
1624  uInt nrow() { return tsys.nrow() ; }
1625  Bool isEffective()
1626  {
1627    return ( !(tsys.empty()) && anyNE( tsys, (Float)1.0 ) ) ;
1628  }
1629  BaseTsysHolder &operator= ( const BaseTsysHolder &v )
1630  {
1631    if ( this != &v )
1632      tsys.assign( v.tsys ) ;
1633    return *this ;
1634  }
1635protected:
1636  ROArrayColumn<Float> col ;
1637  Matrix<Float> tsys ;
1638  uInt nchan ;
1639};
1640
1641class TsysHolder : public BaseTsysHolder
1642{
1643public:
1644  TsysHolder( ROArrayColumn<Float> &tsysCol )
1645    : BaseTsysHolder( tsysCol )
1646  {}
1647  virtual ~TsysHolder() {}
1648  virtual Array<Float> getTsys()
1649  {
1650    return tsys.column( 0 ) ;
1651  }
1652};
1653
1654class TsysSpectrumHolder : public BaseTsysHolder
1655{
1656public:
1657  TsysSpectrumHolder( ROArrayColumn<Float> &tsysCol )
1658    : BaseTsysHolder( tsysCol )
1659  {}
1660  virtual ~TsysSpectrumHolder() {}
1661  virtual Array<Float> getTsys()
1662  {
1663    return tsys ;
1664  }
1665};
1666
1667class BaseTcalProcessor
1668{
1669public:
1670  BaseTcalProcessor( ROArrayColumn<Float> &tcalCol )
1671    : col( tcalCol )
1672  {}
1673  virtual ~BaseTcalProcessor() {}
1674  void setTcalId( Vector<uInt> &tcalId ) { id.assign( tcalId ) ; }
1675  virtual Array<Float> getTcal() = 0 ;
1676protected:
1677  ROArrayColumn<Float> col ;
1678  Vector<uInt> id ;
1679};
1680
1681class TcalProcessor : public BaseTcalProcessor
1682{
1683public:
1684  TcalProcessor( ROArrayColumn<Float> &tcalCol )
1685    : BaseTcalProcessor( tcalCol )
1686  {}
1687  virtual ~TcalProcessor() {}
1688  virtual Array<Float> getTcal()
1689  {
1690    uInt npol = id.nelements() ;
1691    Vector<Float> tcal( npol ) ;
1692    for ( uInt ipol = 0 ; ipol < npol ; ipol++ )
1693      tcal[ipol] = col( id[ipol] ).data()[0] ;
1694    //cout << "TcalProcessor: tcal = " << tcal << endl ;
1695    return tcal ;
1696  }
1697};
1698
1699class TcalSpectrumProcessor : public BaseTcalProcessor
1700{
1701public:
1702  TcalSpectrumProcessor( ROArrayColumn<Float> &tcalCol )
1703    : BaseTcalProcessor( tcalCol )
1704  {}
1705  virtual ~TcalSpectrumProcessor() {}
1706  virtual Array<Float> getTcal()
1707  {
1708    uInt npol = id.nelements() ;
1709    Vector<Float> tcal0 = col( 0 ) ;
1710    uInt nchan = tcal0.nelements() ;
1711    Matrix<Float> tcal( npol, nchan ) ;
1712    tcal.row( 0 ) = tcal0 ;
1713    for ( uInt ipol = 1 ; ipol < npol ; ipol++ )
1714      tcal.row( ipol ) = col( id[ipol] ) ;
1715    return tcal ;
1716  }
1717};
1718
1719class MSSysCalVisitor : public BaseMSSysCalVisitor
1720{
1721public:
1722  MSSysCalVisitor( const Table &from, Table &to )
1723    : BaseMSSysCalVisitor( from ),
1724      sctab( to ),
1725      rowidx( 0 )
1726  {
1727    scrow = TableRow( sctab ) ;
1728
1729    lastTcalId.resize() ;
1730    theTcalId.resize() ;
1731    startTime = 0.0 ;
1732    endTime = 0.0 ;
1733
1734    const TableRecord &keys = table.keywordSet() ;
1735    Table tcalTable = keys.asTable( "TCAL" ) ;
1736    tcalCol.attach( tcalTable, "TCAL" ) ;
1737    tsysCol.attach( table, "TSYS" ) ;
1738    tcalIdCol.attach( table, "TCAL_ID" ) ;
1739    intervalCol.attach( table, "INTERVAL" ) ;
1740    effectiveTcal.resize( tcalTable.nrow() ) ;
1741    for ( uInt irow = 0 ; irow < tcalTable.nrow() ; irow++ ) {
1742      if ( allEQ( tcalCol( irow ), (Float)1.0 ) )
1743        effectiveTcal[irow] = False ;
1744      else
1745        effectiveTcal[irow] = True ;
1746    }
1747   
1748    TableRecord &r = scrow.record() ;
1749    RecordFieldPtr<Int> antennaIdRF( r, "ANTENNA_ID" ) ;
1750    *antennaIdRF = 0 ;
1751    feedIdRF.attachToRecord( r, "FEED_ID" ) ;
1752    specWinIdRF.attachToRecord( r, "SPECTRAL_WINDOW_ID" ) ;
1753    timeRF.attachToRecord( r, "TIME" ) ;
1754    intervalRF.attachToRecord( r, "INTERVAL" ) ;
1755    if ( r.isDefined( "TCAL" ) ) {
1756      tcalRF.attachToRecord( r, "TCAL" ) ;
1757      tcalProcessor = new TcalProcessor( tcalCol ) ;
1758    }
1759    else if ( r.isDefined( "TCAL_SPECTRUM" ) ) {
1760      tcalRF.attachToRecord( r, "TCAL_SPECTRUM" ) ;
1761      tcalProcessor = new TcalSpectrumProcessor( tcalCol ) ;
1762    }
1763    if ( r.isDefined( "TSYS" ) ) {
1764      tsysRF.attachToRecord( r, "TSYS" ) ;
1765      theTsys = new TsysHolder( tsysCol ) ;
1766      lastTsys = new TsysHolder( tsysCol ) ;
1767    }
1768    else {
1769      tsysRF.attachToRecord( r, "TSYS_SPECTRUM" ) ;
1770      theTsys = new TsysSpectrumHolder( tsysCol ) ;
1771      lastTsys = new TsysSpectrumHolder( tsysCol ) ;
1772    }
1773
1774  }
1775
1776  virtual void enterBeamNo(const uInt recordNo, uInt columnValue)
1777  {
1778    *feedIdRF = (Int)columnValue ;
1779  }
1780  virtual void leaveBeamNo(const uInt recordNo, uInt columnValue)
1781  {
1782  }
1783  virtual void enterIfNo(const uInt recordNo, uInt columnValue)
1784  {
1785    //cout << "enterIfNo" << endl ;
1786    ROArrayColumn<Float> sp( table, "SPECTRA" ) ;
1787    uInt nchan = sp( recordNo ).nelements() ;
1788    theTsys->setNchan( nchan ) ;
1789    lastTsys->setNchan( nchan ) ;
1790
1791    *specWinIdRF = (Int)columnValue ;
1792  }
1793  virtual void leaveIfNo(const uInt recordNo, uInt columnValue)
1794  {
1795    //cout << "leaveIfNo" << endl ;
1796    post() ;
1797    lastTsys->reset() ;
1798    lastTcalId.resize() ;
1799    theTsys->reset() ;
1800    theTcalId.resize() ;
1801    startTime = 0.0 ;
1802    endTime = 0.0 ;
1803  }
1804  virtual void enterTime(const uInt recordNo, Double columnValue)
1805  {
1806    //cout << "enterTime" << endl ;
1807    interval = intervalCol.asdouble( recordNo ) ;
1808    // start time and end time
1809    if ( startTime == 0.0 ) {
1810      startTime = columnValue * 86400.0 - 0.5 * interval ;
1811      endTime = columnValue * 86400.0 + 0.5 * interval ;
1812    }
1813  }
1814  virtual void leaveTime(const uInt recordNo, Double columnValue)
1815  {
1816    //cout << "leaveTime" << endl ;
1817    if ( isUpdated() ) {
1818      post() ;
1819      *lastTsys = *theTsys ;
1820      lastTcalId = theTcalId ;
1821      theTsys->reset() ;
1822      theTcalId.resize() ;
1823      startTime = columnValue * 86400.0 - 0.5 * interval ;
1824      endTime = columnValue * 86400.0 + 0.5 * interval ;
1825    }
1826    else {
1827      endTime = columnValue * 86400.0 + 0.5 * interval ;
1828    }
1829  }
1830  virtual void enterPolNo(const uInt recordNo, uInt columnValue)
1831  {
1832    //cout << "enterPolNo" << endl ;
1833    Vector<Float> tsys = tsysCol( recordNo ) ;
1834    uInt tcalId = tcalIdCol.asuInt( recordNo ) ;
1835    // lastTsys.nrow() must be npol
1836    if ( lastTsys->nrow() == columnValue )
1837      lastTsys->appendTsys( recordNo ) ;
1838    // lastTcalId.nelements() must be npol
1839    if ( lastTcalId.nelements() == columnValue )
1840      appendTcalId( lastTcalId, tcalId, columnValue ) ;
1841    // theTsys.nrow() must be npol
1842    if ( theTsys->nrow() == columnValue )
1843      theTsys->appendTsys( recordNo ) ;
1844    else {
1845      theTsys->setTsys( recordNo, columnValue ) ;
1846    }
1847    if ( theTcalId.nelements() == columnValue )
1848      appendTcalId( theTcalId, tcalId, columnValue ) ;
1849    else
1850      setTcalId( theTcalId, tcalId, columnValue ) ;
1851  }
1852  virtual void leavePolNo( const uInt recordNo, uInt columnValue )
1853  {
1854  }
1855   
1856private:
1857  void appendTcalId( Vector<uInt> &v, uInt &elem, uInt &polId )
1858  {
1859    v.resize( polId+1, True ) ;
1860    v[polId] = elem ;
1861  }
1862  void setTcalId( Vector<uInt> &v, uInt &elem, uInt &polId )
1863  {
1864    v[polId] = elem ;
1865  }
1866  void post()
1867  {
1868    // check if given Tcal and Tsys is effective
1869    Bool isEffective = False ;
1870    for ( uInt ipol = 0 ; ipol < lastTcalId.nelements() ; ipol++ ) {
1871      if ( effectiveTcal[lastTcalId[ipol]] ) {
1872        isEffective = True ;
1873        break ;
1874      }
1875    }
1876    if ( !isEffective ) {
1877      if ( !(lastTsys->isEffective()) )
1878        return ;
1879    }
1880
1881    //cout << " interval: " << (endTime-startTime) << " lastTcalId = " << lastTcalId << endl ;
1882    Double midTime = 0.5 * ( startTime + endTime ) ;
1883    Double interval = endTime - startTime ;
1884    *timeRF = midTime ;
1885    *intervalRF = interval ;
1886    tcalProcessor->setTcalId( lastTcalId ) ;
1887    Array<Float> tcal = tcalProcessor->getTcal() ;
1888    tcalRF.define( tcal ) ;
1889    tsysRF.define( lastTsys->getTsys() ) ;
1890    sctab.addRow( 1, True ) ;
1891    scrow.put( rowidx ) ;
1892    rowidx++ ;
1893  }
1894 
1895  Bool isUpdated()
1896  {
1897    Bool ret = False ;
1898    ret = anyNE( theTcalId, lastTcalId ) ;
1899    if ( !ret )
1900      ret = anyNE( theTsys->getTsys(), lastTsys->getTsys() ) ;
1901    return ret ;
1902  }
1903
1904  Table &sctab;
1905  TableRow scrow;
1906  uInt rowidx;
1907
1908  Double startTime,endTime,interval;
1909 
1910  CountedPtr<BaseTsysHolder> lastTsys,theTsys;
1911  Vector<uInt> lastTcalId,theTcalId;
1912  CountedPtr<BaseTcalProcessor> tcalProcessor ;
1913  Vector<Bool> effectiveTcal;
1914
1915  RecordFieldPtr<Int> feedIdRF,specWinIdRF;
1916  RecordFieldPtr<Double> timeRF,intervalRF;
1917  RecordFieldPtr< Array<Float> > tcalRF,tsysRF;
1918
1919  ROArrayColumn<Float> tsysCol,tcalCol;
1920  ROTableColumn tcalIdCol,intervalCol;
1921};
1922
1923MSWriter::MSWriter(CountedPtr<Scantable> stable)
1924  : table_(stable),
1925    isWeather_(False),
1926    tcalSpec_(False),
1927    tsysSpec_(False),
1928    mstable_(NULL),
1929    ptTabName_("")
1930{
1931  os_ = LogIO() ;
1932  os_.origin( LogOrigin( "MSWriter", "MSWriter()", WHERE ) ) ;
1933//   os_ << "MSWriter::MSWriter()" << LogIO::POST ;
1934
1935  // initialize writer
1936  init() ;
1937}
1938
1939MSWriter::~MSWriter()
1940{
1941  os_.origin( LogOrigin( "MSWriter", "~MSWriter()", WHERE ) ) ;
1942//   os_ << "MSWriter::~MSWriter()" << LogIO::POST ;
1943
1944  if ( mstable_ != 0 )
1945    delete mstable_ ;
1946}
1947
1948bool MSWriter::write(const string& filename, const Record& rec)
1949{
1950  os_.origin( LogOrigin( "MSWriter", "write()", WHERE ) ) ;
1951  //double startSec = mathutil::gettimeofday_sec() ;
1952  //os_ << "start MSWriter::write() startSec=" << startSec << LogIO::POST ;
1953
1954  filename_ = filename ;
1955
1956  // parsing MS options
1957  Bool overwrite = False ;
1958  if ( rec.isDefined( "ms" ) ) {
1959    Record msrec = rec.asRecord( "ms" ) ;
1960    if ( msrec.isDefined( "overwrite" ) ) {
1961      overwrite = msrec.asBool( "overwrite" ) ;
1962    }
1963  }
1964
1965  os_ << "Parsing MS options" << endl ;
1966  os_ << "   overwrite = " << overwrite << LogIO::POST ;
1967
1968  File file( filename_ ) ;
1969  if ( file.exists() ) {
1970    if ( overwrite ) {
1971      os_ << filename_ << " exists. Overwrite existing data... " << LogIO::POST ;
1972      if ( file.isRegular() ) RegularFile(file).remove() ;
1973      else if ( file.isDirectory() ) Directory(file).removeRecursive() ;
1974      else SymLink(file).remove() ;
1975    }
1976    else {
1977      os_ << LogIO::SEVERE << "ERROR: " << filename_ << " exists..." << LogIO::POST ;
1978      return False ;
1979    }
1980  }
1981
1982  // set up MS
1983  setupMS() ;
1984 
1985  // subtables
1986  // OBSERVATION
1987  fillObservation() ;
1988
1989  // ANTENNA
1990  fillAntenna() ;
1991
1992  // PROCESSOR
1993  fillProcessor() ;
1994
1995  // SOURCE
1996  fillSource() ;
1997
1998  // WEATHER
1999  if ( isWeather_ )
2000    fillWeather() ;
2001
2002  // SYSCAL
2003  fillSysCal() ;
2004
2005  /***
2006   * Start iteration using TableVisitor
2007   ***/
2008  {
2009    static const char *cols[] = {
2010      "FIELDNAME", "BEAMNO", "SCANNO", "IFNO", "SRCTYPE", "CYCLENO", "TIME",
2011      "POLNO",
2012      NULL
2013    };
2014    static const TypeManagerImpl<uInt> tmUInt;
2015    static const TypeManagerImpl<Int> tmInt;
2016    static const TypeManagerImpl<Double> tmDouble;
2017    static const TypeManagerImpl<String> tmString;
2018    static const TypeManager *const tms[] = {
2019      &tmString, &tmUInt, &tmUInt, &tmUInt, &tmInt, &tmUInt, &tmDouble, &tmUInt, NULL
2020    };
2021    //double t0 = mathutil::gettimeofday_sec() ;
2022    MSWriterVisitor myVisitor(table_->table(),*mstable_);
2023    //double t1 = mathutil::gettimeofday_sec() ;
2024    //cout << "MSWriterVisitor(): elapsed time " << t1-t0 << " sec" << endl ;
2025    String dataColName = "FLOAT_DATA" ;
2026    if ( useData_ )
2027      dataColName = "DATA" ;
2028    myVisitor.dataColumnName( dataColName ) ;
2029    myVisitor.pointingTableName( ptTabName_ ) ;
2030    myVisitor.setSourceRecord( srcRec_ ) ;
2031    //double t2 = mathutil::gettimeofday_sec() ;
2032    traverseTable(table_->table(), cols, tms, &myVisitor);
2033    //double t3 = mathutil::gettimeofday_sec() ;
2034    //cout << "traverseTable(): elapsed time " << t3-t2 << " sec" << endl ;
2035  }
2036  /***
2037   * End iteration using TableVisitor
2038   ***/
2039
2040  // ASDM tables
2041  const TableRecord &stKeys = table_->table().keywordSet() ;
2042  TableRecord &msKeys = mstable_->rwKeywordSet() ;
2043  uInt nfields = stKeys.nfields() ;
2044  for ( uInt ifield = 0 ; ifield < nfields ; ifield++ ) {
2045    String kname = stKeys.name( ifield ) ;
2046    if ( kname.find( "ASDM" ) != String::npos ) {
2047      String asdmpath = stKeys.asString( ifield ) ;
2048      os_ << "found ASDM table: " << asdmpath << LogIO::POST ;
2049      if ( Table::isReadable( asdmpath ) ) {
2050        Table newAsdmTab( asdmpath, Table::Old ) ;
2051        newAsdmTab.copy( filename_+"/"+kname, Table::New ) ;
2052        os_ << "add subtable: " << kname << LogIO::POST ;
2053        msKeys.defineTable( kname, Table( filename_+"/"+kname, Table::Old ) ) ;
2054      }
2055    }
2056  }
2057
2058  // replace POINTING table with original one if exists
2059  if ( ptTabName_ != "" ) {
2060    delete mstable_ ;
2061    mstable_ = 0 ;
2062    Table newPtTab( ptTabName_, Table::Old ) ;
2063    newPtTab.copy( filename_+"/POINTING", Table::New ) ;
2064  }
2065
2066  //double endSec = mathutil::gettimeofday_sec() ;
2067  //os_ << "end MSWriter::write() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2068
2069  os_ << "Exported data as MS" << LogIO::POST ;
2070
2071  return True ;
2072}
2073
2074void MSWriter::init()
2075{
2076//   os_.origin( LogOrigin( "MSWriter", "init()", WHERE ) ) ;
2077//   double startSec = mathutil::gettimeofday_sec() ;
2078//   os_ << "start MSWriter::init() startSec=" << startSec << LogIO::POST ;
2079 
2080  // access to scantable
2081  header_ = table_->getHeader() ;
2082
2083  // FLOAT_DATA? or DATA?
2084  if ( header_.npol > 2 ) {
2085    useFloatData_ = False ;
2086    useData_ = True ;
2087  }
2088  else {
2089    useFloatData_ = True ;
2090    useData_ = False ;
2091  }
2092
2093  // polarization type
2094  polType_ = header_.poltype ;
2095  if ( polType_ == "" )
2096    polType_ = "stokes" ;
2097  else if ( polType_.find( "linear" ) != String::npos )
2098    polType_ = "linear" ;
2099  else if ( polType_.find( "circular" ) != String::npos )
2100    polType_ = "circular" ;
2101  else if ( polType_.find( "stokes" ) != String::npos )
2102    polType_ = "stokes" ;
2103  else if ( polType_.find( "linpol" ) != String::npos )
2104    polType_ = "linpol" ;
2105  else
2106    polType_ = "notype" ;
2107
2108  // Check if some subtables are exists
2109  Bool isTcal = False ;
2110  if ( table_->tcal().table().nrow() != 0 ) {
2111    ROTableColumn col( table_->tcal().table(), "TCAL" ) ;
2112    if ( col.isDefined( 0 ) ) {
2113      os_ << "TCAL table exists: nrow=" << table_->tcal().table().nrow() << LogIO::POST ;
2114      isTcal = True ;
2115    }
2116    else {
2117      os_ << "No TCAL rows" << LogIO::POST ;
2118    }
2119  }
2120  else {
2121    os_ << "No TCAL rows" << LogIO::POST ;
2122  }
2123  if ( table_->weather().table().nrow() != 0 ) {
2124    ROTableColumn col( table_->weather().table(), "TEMPERATURE" ) ;
2125    if ( col.isDefined( 0 ) ) {
2126      os_ << "WEATHER table exists: nrow=" << table_->weather().table().nrow() << LogIO::POST ;
2127      isWeather_ =True ;
2128    }
2129    else {
2130      os_ << "No WEATHER rows" << LogIO::POST ;
2131    }
2132  }
2133  else {
2134    os_ << "No WEATHER rows" << LogIO::POST ;
2135  }
2136
2137  // Are TCAL_SPECTRUM and TSYS_SPECTRUM necessary?
2138  if ( header_.nchan != 1 ) {
2139    if ( isTcal ) {
2140      // examine TCAL subtable
2141      Table tcaltab = table_->tcal().table() ;
2142      ROArrayColumn<Float> tcalCol( tcaltab, "TCAL" ) ;
2143      for ( uInt irow = 0 ; irow < tcaltab.nrow() ; irow++ ) {
2144        if ( tcalCol( irow ).size() != 1 )
2145          tcalSpec_ = True ;
2146      }
2147    }
2148    // examine spectral data
2149    TableIterator iter0( table_->table(), "IFNO" ) ;
2150    while( !iter0.pastEnd() ) {
2151      Table t0( iter0.table() ) ;
2152      ROArrayColumn<Float> sharedFloatArrCol( t0, "SPECTRA" ) ;
2153      uInt len = sharedFloatArrCol( 0 ).size() ;
2154      if ( len != 1 ) {
2155        sharedFloatArrCol.attach( t0, "TSYS" ) ;
2156        if ( sharedFloatArrCol( 0 ).size() != 1 )
2157          tsysSpec_ = True ;
2158      }
2159      iter0.next() ;
2160    }
2161  }
2162
2163  // check if reference for POINTING table exists
2164  const TableRecord &rec = table_->table().keywordSet() ;
2165  if ( rec.isDefined( "POINTING" ) ) {
2166    ptTabName_ = rec.asString( "POINTING" ) ;
2167    if ( !Table::isReadable( ptTabName_ ) ) {
2168      ptTabName_ = "" ;
2169    }
2170  }
2171
2172//   double endSec = mathutil::gettimeofday_sec() ;
2173//   os_ << "end MSWriter::init() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2174}
2175
2176void MSWriter::setupMS()
2177{
2178//   os_.origin( LogOrigin( "MSWriter", "setupMS()", WHERE ) ) ;
2179//   double startSec = mathutil::gettimeofday_sec() ;
2180//   os_ << "start MSWriter::setupMS() startSec=" << startSec << LogIO::POST ;
2181 
2182  String dunit = table_->getHeader().fluxunit ;
2183
2184  TableDesc msDesc = MeasurementSet::requiredTableDesc() ;
2185  if ( useFloatData_ )
2186    MeasurementSet::addColumnToDesc( msDesc, MSMainEnums::FLOAT_DATA, 2 ) ;
2187  else if ( useData_ )
2188    MeasurementSet::addColumnToDesc( msDesc, MSMainEnums::DATA, 2 ) ;
2189
2190  SetupNewTable newtab( filename_, msDesc, Table::New ) ;
2191
2192  mstable_ = new MeasurementSet( newtab ) ;
2193
2194  TableColumn col ;
2195  if ( useFloatData_ )
2196    col.attach( *mstable_, "FLOAT_DATA" ) ;
2197  else if ( useData_ )
2198    col.attach( *mstable_, "DATA" ) ;
2199  col.rwKeywordSet().define( "UNIT", dunit ) ;
2200
2201  // create subtables
2202  TableDesc antennaDesc = MSAntenna::requiredTableDesc() ;
2203  SetupNewTable antennaTab( mstable_->antennaTableName(), antennaDesc, Table::New ) ;
2204  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::ANTENNA ), Table( antennaTab ) ) ;
2205
2206  TableDesc dataDescDesc = MSDataDescription::requiredTableDesc() ;
2207  SetupNewTable dataDescTab( mstable_->dataDescriptionTableName(), dataDescDesc, Table::New ) ;
2208  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::DATA_DESCRIPTION ), Table( dataDescTab ) ) ;
2209
2210  TableDesc dopplerDesc = MSDoppler::requiredTableDesc() ;
2211  SetupNewTable dopplerTab( mstable_->dopplerTableName(), dopplerDesc, Table::New ) ;
2212  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::DOPPLER ), Table( dopplerTab ) ) ;
2213
2214  TableDesc feedDesc = MSFeed::requiredTableDesc() ;
2215  SetupNewTable feedTab( mstable_->feedTableName(), feedDesc, Table::New ) ;
2216  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::FEED ), Table( feedTab ) ) ;
2217
2218  TableDesc fieldDesc = MSField::requiredTableDesc() ;
2219  SetupNewTable fieldTab( mstable_->fieldTableName(), fieldDesc, Table::New ) ;
2220  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::FIELD ), Table( fieldTab ) ) ;
2221
2222  TableDesc flagCmdDesc = MSFlagCmd::requiredTableDesc() ;
2223  SetupNewTable flagCmdTab( mstable_->flagCmdTableName(), flagCmdDesc, Table::New ) ;
2224  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::FLAG_CMD ), Table( flagCmdTab ) ) ;
2225
2226  TableDesc freqOffsetDesc = MSFreqOffset::requiredTableDesc() ;
2227  SetupNewTable freqOffsetTab( mstable_->freqOffsetTableName(), freqOffsetDesc, Table::New ) ;
2228  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::FREQ_OFFSET ), Table( freqOffsetTab ) ) ;
2229
2230  TableDesc historyDesc = MSHistory::requiredTableDesc() ;
2231  SetupNewTable historyTab( mstable_->historyTableName(), historyDesc, Table::New ) ;
2232  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::HISTORY ), Table( historyTab ) ) ;
2233
2234  TableDesc observationDesc = MSObservation::requiredTableDesc() ;
2235  SetupNewTable observationTab( mstable_->observationTableName(), observationDesc, Table::New ) ;
2236  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::OBSERVATION ), Table( observationTab ) ) ;
2237
2238  TableDesc pointingDesc = MSPointing::requiredTableDesc() ;
2239  SetupNewTable pointingTab( mstable_->pointingTableName(), pointingDesc, Table::New ) ;
2240  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::POINTING ), Table( pointingTab ) ) ;
2241
2242  TableDesc polarizationDesc = MSPolarization::requiredTableDesc() ;
2243  SetupNewTable polarizationTab( mstable_->polarizationTableName(), polarizationDesc, Table::New ) ;
2244  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::POLARIZATION ), Table( polarizationTab ) ) ;
2245
2246  TableDesc processorDesc = MSProcessor::requiredTableDesc() ;
2247  SetupNewTable processorTab( mstable_->processorTableName(), processorDesc, Table::New ) ;
2248  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::PROCESSOR ), Table( processorTab ) ) ;
2249
2250  TableDesc sourceDesc = MSSource::requiredTableDesc() ;
2251  MSSource::addColumnToDesc( sourceDesc, MSSourceEnums::TRANSITION, 1 ) ;
2252  MSSource::addColumnToDesc( sourceDesc, MSSourceEnums::REST_FREQUENCY, 1 ) ;
2253  MSSource::addColumnToDesc( sourceDesc, MSSourceEnums::SYSVEL, 1 ) ;
2254  SetupNewTable sourceTab( mstable_->sourceTableName(), sourceDesc, Table::New ) ;
2255  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::SOURCE ), Table( sourceTab ) ) ;
2256
2257  TableDesc spwDesc = MSSpectralWindow::requiredTableDesc() ;
2258  SetupNewTable spwTab( mstable_->spectralWindowTableName(), spwDesc, Table::New ) ;
2259  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::SPECTRAL_WINDOW ), Table( spwTab ) ) ;
2260
2261  TableDesc stateDesc = MSState::requiredTableDesc() ;
2262  SetupNewTable stateTab( mstable_->stateTableName(), stateDesc, Table::New ) ;
2263  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::STATE ), Table( stateTab ) ) ;
2264
2265  TableDesc sysCalDesc = MSSysCal::requiredTableDesc() ;
2266  if ( tcalSpec_ )
2267    MSSysCal::addColumnToDesc( sysCalDesc, MSSysCalEnums::TCAL_SPECTRUM, 2 ) ;
2268  else
2269    MSSysCal::addColumnToDesc( sysCalDesc, MSSysCalEnums::TCAL, 1 ) ;
2270  if ( tsysSpec_ )
2271    MSSysCal::addColumnToDesc( sysCalDesc, MSSysCalEnums::TSYS_SPECTRUM, 2 ) ;
2272  else
2273    MSSysCal::addColumnToDesc( sysCalDesc, MSSysCalEnums::TSYS, 1 ) ;
2274  SetupNewTable sysCalTab( mstable_->sysCalTableName(), sysCalDesc, Table::New ) ;
2275  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::SYSCAL ), Table( sysCalTab ) ) ;
2276
2277  TableDesc weatherDesc = MSWeather::requiredTableDesc() ;
2278  MSWeather::addColumnToDesc( weatherDesc, MSWeatherEnums::TEMPERATURE ) ;
2279  MSWeather::addColumnToDesc( weatherDesc, MSWeatherEnums::PRESSURE ) ;
2280  MSWeather::addColumnToDesc( weatherDesc, MSWeatherEnums::REL_HUMIDITY ) ;
2281  MSWeather::addColumnToDesc( weatherDesc, MSWeatherEnums::WIND_SPEED ) ;
2282  MSWeather::addColumnToDesc( weatherDesc, MSWeatherEnums::WIND_DIRECTION ) ;
2283  SetupNewTable weatherTab( mstable_->weatherTableName(), weatherDesc, Table::New ) ;
2284  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::WEATHER ), Table( weatherTab ) ) ;
2285
2286  mstable_->initRefs() ;
2287
2288//   double endSec = mathutil::gettimeofday_sec() ;
2289//   os_ << "end MSWriter::setupMS() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2290}
2291
2292void MSWriter::fillObservation()
2293{
2294  //double startSec = mathutil::gettimeofday_sec() ;
2295  //os_ << "start MSWriter::fillObservation() startSec=" << startSec << LogIO::POST ;
2296
2297  // only 1 row
2298  mstable_->observation().addRow( 1, True ) ;
2299  MSObservationColumns msObsCols( mstable_->observation() ) ;
2300  msObsCols.observer().put( 0, header_.observer ) ;
2301  // tentatively put antennaname (from ANTENNA subtable)
2302  String hAntennaName = header_.antennaname ;
2303  String::size_type pos = hAntennaName.find( "//" ) ;
2304  String telescopeName ;
2305  if ( pos != String::npos ) {
2306    telescopeName = hAntennaName.substr( 0, pos ) ;
2307  }
2308  else {
2309    pos = hAntennaName.find( "@" ) ;
2310    telescopeName = hAntennaName.substr( 0, pos ) ;
2311  }
2312//   os_ << "telescopeName = " << telescopeName << LogIO::POST ;
2313  msObsCols.telescopeName().put( 0, telescopeName ) ;
2314  msObsCols.project().put( 0, header_.project ) ;
2315  //ScalarMeasColumn<MEpoch> timeCol( table_->table().sort("TIME"), "TIME" ) ;
2316  Table sortedtable = table_->table().sort("TIME") ;
2317  ScalarMeasColumn<MEpoch> timeCol( sortedtable, "TIME" ) ;
2318  Vector<MEpoch> trange( 2 ) ;
2319  trange[0] = timeCol( 0 ) ;
2320  trange[1] = timeCol( table_->nrow()-1 ) ;
2321  msObsCols.timeRangeMeas().put( 0, trange ) ;
2322
2323  //double endSec = mathutil::gettimeofday_sec() ;
2324  //os_ << "end MSWriter::fillObservation() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2325}
2326
2327void MSWriter::antennaProperty( String &name, String &m, String &t, Double &d )
2328{
2329  name.upcase() ;
2330 
2331  m = "ALT-AZ" ;
2332  t = "GROUND-BASED" ;
2333  if ( name.matches( Regex( "DV[0-9]+$" ) )
2334       || name.matches( Regex( "DA[0-9]+$" ) )
2335       || name.matches( Regex( "PM[0-9]+$" ) ) )
2336    d = 12.0 ;
2337  else if ( name.matches( Regex( "CM[0-9]+$" ) ) )
2338    d = 7.0 ;
2339  else if ( name.contains( "GBT" ) )
2340    d = 104.9 ;
2341  else if ( name.contains( "MOPRA" ) )
2342    d = 22.0 ;
2343  else if ( name.contains( "PKS" ) || name.contains( "PARKS" ) )
2344    d = 64.0 ;
2345  else if ( name.contains( "TIDBINBILLA" ) )
2346    d = 70.0 ;
2347  else if ( name.contains( "CEDUNA" ) )
2348    d = 30.0 ;
2349  else if ( name.contains( "HOBART" ) )
2350    d = 26.0 ;
2351  else if ( name.contains( "APEX" ) )
2352    d = 12.0 ;
2353  else if ( name.contains( "ASTE" ) )
2354    d = 10.0 ;
2355  else if ( name.contains( "NRO" ) )
2356    d = 45.0 ;
2357  else
2358    d = 1.0 ;
2359}
2360
2361void MSWriter::fillAntenna()
2362{
2363  //double startSec = mathutil::gettimeofday_sec() ;
2364  //os_ << "start MSWriter::fillAntenna() startSec=" << startSec << LogIO::POST ;
2365
2366  // only 1 row
2367  Table anttab = mstable_->antenna() ;
2368  anttab.addRow( 1, True ) ;
2369 
2370  Table &table = table_->table() ;
2371  const TableRecord &keys = table.keywordSet() ;
2372  String hAntName = keys.asString( "AntennaName" ) ;
2373  String::size_type pos = hAntName.find( "//" ) ;
2374  String antennaName ;
2375  String stationName ;
2376  if ( pos != String::npos ) {
2377    stationName = hAntName.substr( 0, pos ) ;
2378    hAntName = hAntName.substr( pos+2 ) ;
2379  }
2380  pos = hAntName.find( "@" ) ;
2381  if ( pos != String::npos ) {
2382    antennaName = hAntName.substr( 0, pos ) ;
2383    stationName = hAntName.substr( pos+1 ) ;
2384  }
2385  else {
2386    antennaName = hAntName ;
2387  }
2388  Vector<Double> antpos = keys.asArrayDouble( "AntennaPosition" ) ;
2389 
2390  String mount, atype ;
2391  Double diameter ;
2392  antennaProperty( antennaName, mount, atype, diameter ) ;
2393 
2394  TableRow tr( anttab ) ;
2395  TableRecord &r = tr.record() ;
2396  RecordFieldPtr<String> nameRF( r, "NAME" ) ;
2397  RecordFieldPtr<String> stationRF( r, "STATION" ) ;
2398  RecordFieldPtr<String> mountRF( r, "MOUNT" ) ;
2399  RecordFieldPtr<String> typeRF( r, "TYPE" ) ;
2400  RecordFieldPtr<Double> dishDiameterRF( r, "DISH_DIAMETER" ) ;
2401  RecordFieldPtr< Vector<Double> > positionRF( r, "POSITION" ) ;
2402  *nameRF = antennaName ;
2403  *mountRF = mount ;
2404  *typeRF = atype ;
2405  *dishDiameterRF = diameter ;
2406  *positionRF = antpos ;
2407  *stationRF = stationName ;
2408 
2409  tr.put( 0 ) ;
2410
2411  //double endSec = mathutil::gettimeofday_sec() ;
2412  //os_ << "end MSWriter::fillAntenna() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2413}
2414 
2415void MSWriter::fillProcessor()
2416{
2417//   double startSec = mathutil::gettimeofday_sec() ;
2418//   os_ << "start MSWriter::fillProcessor() startSec=" << startSec << LogIO::POST ;
2419 
2420  // only add empty 1 row
2421  MSProcessor msProc = mstable_->processor() ;
2422  msProc.addRow( 1, True ) ;
2423
2424//   double endSec = mathutil::gettimeofday_sec() ;
2425//   os_ << "end MSWriter::fillProcessor() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2426}
2427
2428void MSWriter::fillSource()
2429{
2430//   double startSec = mathutil::gettimeofday_sec() ;
2431//   os_ << "start MSWriter::fillSource() startSec=" << startSec << LogIO::POST ;
2432 
2433  // access to MS SOURCE subtable
2434  MSSource msSrc = mstable_->source() ;
2435
2436  // access to MOLECULE subtable
2437  STMolecules stm = table_->molecules() ;
2438
2439  Int srcId = 0 ;
2440  Vector<Double> restFreq ;
2441  Vector<String> molName ;
2442  Vector<String> fMolName ;
2443
2444  // row based
2445  TableRow row( msSrc ) ;
2446  TableRecord &rec = row.record() ;
2447  RecordFieldPtr<Int> srcidRF( rec, "SOURCE_ID" ) ;
2448  RecordFieldPtr<String> nameRF( rec, "NAME" ) ;
2449  RecordFieldPtr< Array<Double> > srcpmRF( rec, "PROPER_MOTION" ) ;
2450  RecordFieldPtr< Array<Double> > srcdirRF( rec, "DIRECTION" ) ;
2451  RecordFieldPtr<Int> numlineRF( rec, "NUM_LINES" ) ;
2452  RecordFieldPtr< Array<Double> > restfreqRF( rec, "REST_FREQUENCY" ) ;
2453  RecordFieldPtr< Array<Double> > sysvelRF( rec, "SYSVEL" ) ;
2454  RecordFieldPtr< Array<String> > transitionRF( rec, "TRANSITION" ) ;
2455  RecordFieldPtr<Double> timeRF( rec, "TIME" ) ;
2456  RecordFieldPtr<Double> intervalRF( rec, "INTERVAL" ) ;
2457  RecordFieldPtr<Int> spwidRF( rec, "SPECTRAL_WINDOW_ID" ) ;
2458
2459  //
2460  // ITERATION: SRCNAME
2461  //
2462  TableIterator iter0( table_->table(), "SRCNAME" ) ;
2463  while( !iter0.pastEnd() ) {
2464    //Table t0( iter0.table() ) ;
2465    Table t0 =  iter0.table()  ;
2466
2467    // get necessary information
2468    ROScalarColumn<String> srcNameCol( t0, "SRCNAME" ) ;
2469    String srcName = srcNameCol( 0 ) ;
2470    ROArrayColumn<Double> sharedDArrRCol( t0, "SRCPROPERMOTION" ) ;
2471    Vector<Double> srcPM = sharedDArrRCol( 0 ) ;
2472    sharedDArrRCol.attach( t0, "SRCDIRECTION" ) ;
2473    Vector<Double> srcDir = sharedDArrRCol( 0 ) ;
2474    ROScalarColumn<Double> srcVelCol( t0, "SRCVELOCITY" ) ;
2475    Double srcVel = srcVelCol( 0 ) ;
2476    srcRec_.define( srcName, srcId ) ;
2477
2478    // NAME
2479    *nameRF = srcName ;
2480
2481    // SOURCE_ID
2482    *srcidRF = srcId ;
2483
2484    // PROPER_MOTION
2485    *srcpmRF = srcPM ;
2486   
2487    // DIRECTION
2488    *srcdirRF = srcDir ;
2489
2490    //
2491    // ITERATION: MOLECULE_ID
2492    //
2493    TableIterator iter1( t0, "MOLECULE_ID" ) ;
2494    while( !iter1.pastEnd() ) {
2495      //Table t1( iter1.table() ) ;
2496      Table t1 = iter1.table() ;
2497
2498      // get necessary information
2499      ROScalarColumn<uInt> molIdCol( t1, "MOLECULE_ID" ) ;
2500      uInt molId = molIdCol( 0 ) ;
2501      stm.getEntry( restFreq, molName, fMolName, molId ) ;
2502
2503      uInt numFreq = restFreq.size() ;
2504     
2505      // NUM_LINES
2506      *numlineRF = numFreq ;
2507
2508      // REST_FREQUENCY
2509      *restfreqRF = restFreq ;
2510
2511      // TRANSITION
2512      //*transitionRF = fMolName ;
2513      Vector<String> transition ;
2514      if ( fMolName.size() != 0 ) {
2515        transition = fMolName ;
2516      }
2517      else if ( molName.size() != 0 ) {
2518        transition = molName ;
2519      }
2520      else {
2521        transition.resize( numFreq ) ;
2522        transition = "" ;
2523      }
2524      *transitionRF = transition ;
2525
2526      // SYSVEL
2527      Vector<Double> sysvelArr( numFreq, srcVel ) ;
2528      *sysvelRF = sysvelArr ;
2529
2530      //
2531      // ITERATION: IFNO
2532      //
2533      TableIterator iter2( t1, "IFNO" ) ;
2534      while( !iter2.pastEnd() ) {
2535        //Table t2( iter2.table() ) ;
2536        Table t2 = iter2.table() ;
2537        uInt nrow = msSrc.nrow() ;
2538
2539        // get necessary information
2540        ROScalarColumn<uInt> ifNoCol( t2, "IFNO" ) ;
2541        uInt ifno = ifNoCol( 0 ) ; // IFNO = SPECTRAL_WINDOW_ID
2542        Double midTime ;
2543        Double interval ;
2544        getValidTimeRange( midTime, interval, t2 ) ;
2545
2546        // fill SPECTRAL_WINDOW_ID
2547        *spwidRF = ifno ;
2548
2549        // fill TIME, INTERVAL
2550        *timeRF = midTime ;
2551        *intervalRF = interval ;
2552
2553        // add row
2554        msSrc.addRow( 1, True ) ;
2555        row.put( nrow ) ;
2556
2557        iter2.next() ;
2558      }
2559
2560      iter1.next() ;
2561    }
2562
2563    // increment srcId if SRCNAME changed
2564    srcId++ ;
2565
2566    iter0.next() ;
2567  }
2568
2569//   double endSec = mathutil::gettimeofday_sec() ;
2570//   os_ << "end MSWriter::fillSource() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2571}
2572
2573void MSWriter::fillWeather()
2574{
2575//   double startSec = mathutil::gettimeofday_sec() ;
2576//   os_ << "start MSWriter::fillWeather() startSec=" << startSec << LogIO::POST ;
2577
2578  // access to MS WEATHER subtable
2579  MSWeather msw = mstable_->weather() ;
2580
2581  // access to WEATHER subtable
2582  Table stw = table_->weather().table() ;
2583  uInt nrow = stw.nrow() ;
2584
2585  if ( nrow == 0 )
2586    return ;
2587
2588  msw.addRow( nrow, True ) ;
2589  MSWeatherColumns mswCols( msw ) ;
2590
2591  // ANTENNA_ID is always 0
2592  Vector<Int> antIdArr( nrow, 0 ) ;
2593  mswCols.antennaId().putColumn( antIdArr ) ;
2594
2595  // fill weather status
2596  ROScalarColumn<Float> sharedFloatCol( stw, "TEMPERATURE" ) ;
2597  mswCols.temperature().putColumn( sharedFloatCol ) ;
2598  sharedFloatCol.attach( stw, "PRESSURE" ) ;
2599  mswCols.pressure().putColumn( sharedFloatCol ) ;
2600  sharedFloatCol.attach( stw, "HUMIDITY" ) ;
2601  mswCols.relHumidity().putColumn( sharedFloatCol ) ;
2602  sharedFloatCol.attach( stw, "WINDSPEED" ) ;
2603  mswCols.windSpeed().putColumn( sharedFloatCol ) ;
2604  sharedFloatCol.attach( stw, "WINDAZ" ) ;
2605  mswCols.windDirection().putColumn( sharedFloatCol ) ;
2606
2607  // fill TIME and INTERVAL
2608  Double midTime ;
2609  Double interval ;
2610  Vector<Double> intervalArr( nrow, 0.0 ) ;
2611  TableIterator iter( table_->table(), "WEATHER_ID" ) ;
2612  while( !iter.pastEnd() ) {
2613    //Table tab( iter.table() ) ;
2614    Table tab = iter.table() ;
2615
2616    ROScalarColumn<uInt> widCol( tab, "WEATHER_ID" ) ;
2617    uInt wid = widCol( 0 ) ;
2618
2619    getValidTimeRange( midTime, interval, tab ) ;
2620    mswCols.time().put( wid, midTime ) ;
2621    intervalArr[wid] = interval ;
2622
2623    iter.next() ;
2624  }
2625  mswCols.interval().putColumn( intervalArr ) ;
2626
2627//   double endSec = mathutil::gettimeofday_sec() ;
2628//   os_ << "end MSWriter::fillWeather() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2629}
2630
2631void MSWriter::fillSysCal()
2632{
2633  Table mssc = mstable_->sysCal() ;
2634
2635  {
2636    static const char *cols[] = {
2637      "BEAMNO", "IFNO", "TIME", "POLNO",
2638      NULL
2639    };
2640    static const TypeManagerImpl<uInt> tmUInt;
2641    static const TypeManagerImpl<Double> tmDouble;
2642    static const TypeManager *const tms[] = {
2643      &tmUInt, &tmUInt, &tmDouble, &tmUInt, NULL
2644    };
2645    //double t0 = mathutil::gettimeofday_sec() ;
2646    MSSysCalVisitor myVisitor(table_->table(),mssc);
2647    //double t1 = mathutil::gettimeofday_sec() ;
2648    //cout << "MSWriterVisitor(): elapsed time " << t1-t0 << " sec" << endl ;
2649    traverseTable(table_->table(), cols, tms, &myVisitor);
2650    //double t3 = mathutil::gettimeofday_sec() ;
2651    //cout << "traverseTable(): elapsed time " << t3-t2 << " sec" << endl ;
2652  }
2653 
2654}
2655
2656void MSWriter::getValidTimeRange( Double &me, Double &interval, Table &tab )
2657{
2658//   double startSec = mathutil::gettimeofday_sec() ;
2659//   os_ << "start MSWriter::getVaridTimeRange() startSec=" << startSec << LogIO::POST ;
2660
2661  // sort table
2662  //Table stab = tab.sort( "TIME" ) ;
2663
2664  ROScalarColumn<Double> timeCol( tab, "TIME" ) ;
2665  Vector<Double> timeArr = timeCol.getColumn() ;
2666  Double minTime ;
2667  Double maxTime ;
2668  minMax( minTime, maxTime, timeArr ) ;
2669  Double midTime = 0.5 * ( minTime + maxTime ) * 86400.0 ;
2670  // unit for TIME
2671  // Scantable: "d"
2672  // MS: "s"
2673  me = midTime ;
2674  interval = ( maxTime - minTime ) * 86400.0 ;
2675
2676//   double endSec = mathutil::gettimeofday_sec() ;
2677//   os_ << "end MSWriter::getValidTimeRange() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2678}
2679
2680void MSWriter::getValidTimeRange( Double &me, Double &interval, Vector<Double> &atime, Vector<Double> &ainterval )
2681{
2682//   double startSec = mathutil::gettimeofday_sec() ;
2683//   os_ << "start MSWriter::getVaridTimeRange() startSec=" << startSec << LogIO::POST ;
2684
2685  // sort table
2686  //Table stab = tab.sort( "TIME" ) ;
2687
2688  Double minTime ;
2689  Double maxTime ;
2690  minMax( minTime, maxTime, atime ) ;
2691  Double midTime = 0.5 * ( minTime + maxTime ) * 86400.0 ;
2692  // unit for TIME
2693  // Scantable: "d"
2694  // MS: "s"
2695  me = midTime ;
2696  interval = ( maxTime - minTime ) * 86400.0 + mean( ainterval ) ;
2697
2698//   double endSec = mathutil::gettimeofday_sec() ;
2699//   os_ << "end MSWriter::getValidTimeRange() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
2700}
2701
2702}
Note: See TracBrowser for help on using the repository browser.