source: trunk/src/MSWriter.cpp @ 2309

Last change on this file since 2309 was 2309, checked in by Takeshi Nakazato, 13 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: test_sdsave, regressions/fls_3a_hi_regression.py

Put in Release Notes: No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Fill SysCal? table properly.


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