source: branches/casa-prerelease/pre-asap/src/MSWriter.cpp @ 2191

Last change on this file since 2191 was 2191, checked in by Kana Sugimoto, 13 years ago

Reverted codes to r2187 to save snap shot for CASA3.2.0 and 3.2.1

File size: 61.1 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
14#include <casa/OS/File.h>
15#include <casa/OS/RegularFile.h>
16#include <casa/OS/Directory.h>
17#include <casa/OS/SymLink.h>
18#include <casa/BasicSL/String.h>
19#include <casa/Containers/RecordField.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
41#include <ctime>
42#include <sys/time.h>
43
44using namespace casa ;
45using namespace std ;
46
47namespace asap {
48double MSWriter::gettimeofday_sec()
49{
50  struct timeval tv ;
51  gettimeofday( &tv, NULL ) ;
52  return tv.tv_sec + (double)tv.tv_usec*1.0e-6 ;
53}
54
55MSWriter::MSWriter(CountedPtr<Scantable> stable)
56  : table_(stable),
57    isTcal_(False),
58    isWeather_(False),
59    tcalSpec_(False),
60    tsysSpec_(False),
61    ptTabName_("")
62{
63  os_ = LogIO() ;
64  os_.origin( LogOrigin( "MSWriter", "MSWriter()", WHERE ) ) ;
65//   os_ << "MSWriter::MSWriter()" << LogIO::POST ;
66
67  // initialize writer
68  init() ;
69}
70
71MSWriter::~MSWriter()
72{
73  os_.origin( LogOrigin( "MSWriter", "~MSWriter()", WHERE ) ) ;
74//   os_ << "MSWriter::~MSWriter()" << LogIO::POST ;
75
76  if ( mstable_ != 0 )
77    delete mstable_ ;
78}
79 
80bool MSWriter::write(const string& filename, const Record& rec)
81{
82  os_.origin( LogOrigin( "MSWriter", "write()", WHERE ) ) ;
83//   double startSec = gettimeofday_sec() ;
84//   os_ << "start MSWriter::write() startSec=" << startSec << LogIO::POST ;
85
86  filename_ = filename ;
87
88  // parsing MS options
89  Bool overwrite = False ;
90  if ( rec.isDefined( "ms" ) ) {
91    Record msrec = rec.asRecord( "ms" ) ;
92    if ( msrec.isDefined( "overwrite" ) ) {
93      overwrite = msrec.asBool( "overwrite" ) ;
94    }
95  }
96
97  os_ << "Parsing MS options" << endl ;
98  os_ << "   overwrite = " << overwrite << LogIO::POST ;
99
100  File file( filename_ ) ;
101  if ( file.exists() ) {
102    if ( overwrite ) {
103      os_ << filename_ << " exists. Overwrite existing data... " << LogIO::POST ;
104      if ( file.isRegular() ) RegularFile(file).remove() ;
105      else if ( file.isDirectory() ) Directory(file).removeRecursive() ;
106      else SymLink(file).remove() ;
107    }
108    else {
109      os_ << LogIO::SEVERE << "ERROR: " << filename_ << " exists..." << LogIO::POST ;
110      return False ;
111    }
112  }
113
114  // set up MS
115  setupMS() ;
116 
117  // subtables
118  // OBSERVATION
119  fillObservation() ;
120
121  // ANTENNA
122  fillAntenna() ;
123
124  // PROCESSOR
125  fillProcessor() ;
126
127  // SOURCE
128  fillSource() ;
129
130  // WEATHER
131  if ( isWeather_ )
132    fillWeather() ;
133
134  // MAIN
135  // Iterate over several ids
136  Vector<uInt> processedFreqId( 0 ) ;
137  Int defaultFieldId = 0 ;
138
139  // row based
140  TableRow row( *mstable_ ) ;
141  TableRecord &trec = row.record() ;
142  NoticeTarget *dataRF = 0 ;
143  if ( useFloatData_ )
144    dataRF = new RecordFieldPtr< Array<Float> >( trec, "FLOAT_DATA" ) ;
145  else if ( useData_ )
146    dataRF = new RecordFieldPtr< Array<Complex> >( trec, "DATA" ) ;
147  RecordFieldPtr< Array<Bool> > flagRF( trec, "FLAG" ) ;
148  RecordFieldPtr<Bool> flagrowRF( trec, "FLAG_ROW" ) ;
149  RecordFieldPtr<Double> timeRF( trec, "TIME" ) ;
150  RecordFieldPtr<Double> timecRF( trec, "TIME_CENTROID" ) ;
151  RecordFieldPtr<Double> intervalRF( trec, "INTERVAL" ) ;
152  RecordFieldPtr<Double> exposureRF( trec, "EXPOSURE" ) ;
153  RecordFieldPtr< Array<Float> > weightRF( trec, "WEIGHT" ) ;
154  RecordFieldPtr< Array<Float> > sigmaRF( trec, "SIGMA" ) ;
155  RecordFieldPtr<Int> ddidRF( trec, "DATA_DESC_ID" ) ;
156  RecordFieldPtr<Int> stateidRF( trec, "STATE_ID" ) ;
157  RecordFieldPtr< Array<Bool> > flagcatRF( trec, "FLAG_CATEGORY" ) ;
158
159  // OBSERVATION_ID is always 0
160  RecordFieldPtr<Int> intRF( trec, "OBSERVATION_ID" ) ;
161  *intRF = 0 ;
162 
163  // ANTENNA1 and ANTENNA2 are always 0
164  intRF.attachToRecord( trec, "ANTENNA1" ) ;
165  *intRF = 0 ;
166  intRF.attachToRecord( trec, "ANTENNA2" ) ;
167  *intRF = 0 ;
168 
169  // ARRAY_ID is tentatively set to 0
170  intRF.attachToRecord( trec, "ARRAY_ID" ) ;
171  *intRF = 0 ;
172
173  // PROCESSOR_ID is tentatively set to 0
174  intRF.attachToRecord( trec, "PROCESSOR_ID" ) ;
175  *intRF = 0 ;
176
177  // UVW is always [0,0,0]
178  RecordFieldPtr< Array<Double> > uvwRF( trec, "UVW" ) ;
179  *uvwRF = Vector<Double>( 3, 0.0 ) ;
180
181  //
182  // ITERATION: FIELDNAME
183  //
184  TableIterator iter0( table_->table(), "FIELDNAME" ) ;
185  while( !iter0.pastEnd() ) {
186    //Table t0( iter0.table() ) ;
187    Table t0 = iter0.table() ;
188    ROTableColumn sharedCol( t0, "FIELDNAME" ) ;
189    String fieldName = sharedCol.asString( 0 ) ;
190    sharedCol.attach( t0, "SRCNAME" ) ;
191    String srcName = sharedCol.asString( 0 ) ;
192    sharedCol.attach( t0, "TIME" ) ;
193    Double minTime = (Double)sharedCol.asdouble( 0 ) * 86400.0 ; // day->sec
194    ROArrayColumn<Double> scanRateCol( t0, "SCANRATE" ) ;
195    Vector<Double> scanRate = scanRateCol( 0 ) ;
196    String::size_type pos = fieldName.find( "__" ) ;
197    Int fieldId = -1 ;
198    if ( pos != String::npos ) {
199//       os_ << "fieldName.substr( pos+2 )=" << fieldName.substr( pos+2 ) << LogIO::POST ;
200      fieldId = String::toInt( fieldName.substr( pos+2 ) ) ;
201      fieldName = fieldName.substr( 0, pos ) ;
202    }
203    else {
204//       os_ << "use default field id" << LogIO::POST ;
205      fieldId = defaultFieldId ;
206      defaultFieldId++ ;
207    }
208//     os_ << "fieldId" << fieldId << ": " << fieldName << LogIO::POST ;
209
210    // FIELD_ID
211    intRF.attachToRecord( trec, "FIELD_ID" ) ;
212    *intRF = fieldId ;
213
214    //
215    // ITERATION: BEAMNO
216    //
217    TableIterator iter1( t0, "BEAMNO" ) ;
218    while( !iter1.pastEnd() ) {
219      Table t1 = iter1.table() ;
220      sharedCol.attach( t1, "BEAMNO" ) ;
221      uInt beamNo = sharedCol.asuInt( 0 ) ;
222//       os_ << "beamNo = " << beamNo << LogIO::POST ;
223
224      // FEED1 and FEED2
225      intRF.attachToRecord( trec, "FEED1" ) ;
226      *intRF = beamNo ;
227      intRF.attachToRecord( trec, "FEED2" ) ;
228      *intRF = beamNo ;
229
230      //
231      // ITERATION: SCANNO
232      //
233      TableIterator iter2( t1, "SCANNO" ) ;
234      while( !iter2.pastEnd() ) {
235        Table t2 = iter2.table() ;
236        sharedCol.attach( t2, "SCANNO" ) ;
237        uInt scanNo = sharedCol.asuInt( 0 ) ;
238//         os_ << "scanNo = " << scanNo << LogIO::POST ;
239
240        // SCAN_NUMBER
241        // MS: 1-based
242        // Scantable: 0-based
243        intRF.attachToRecord( trec, "SCAN_NUMBER" ) ;
244        *intRF = scanNo + 1 ;
245
246        //
247        // ITERATION: IFNO
248        //
249        TableIterator iter3( t2, "IFNO" ) ;
250        while( !iter3.pastEnd() ) {
251          Table t3 = iter3.table() ;
252          sharedCol.attach( t3, "IFNO" ) ;
253          uInt ifNo = sharedCol.asuInt( 0 ) ;
254//           os_ << "ifNo = " << ifNo << LogIO::POST ;
255          sharedCol.attach( t3, "FREQ_ID" ) ;
256          uInt freqId = sharedCol.asuInt( 0 ) ;
257//           os_ << "freqId = " << freqId << LogIO::POST ;
258          Int subscan = 1 ; // 1-base
259          //
260          // ITERATION: SRCTYPE
261          //
262          TableIterator iter4( t3, "SRCTYPE" ) ;
263          while( !iter4.pastEnd() ) {
264            Table t4 = iter4.table() ;
265            sharedCol.attach( t4, "SRCTYPE" ) ;
266            Int srcType = sharedCol.asInt( 0 ) ;
267            Int stateId = addState( srcType, subscan ) ;
268            *stateidRF = stateId ;
269            //
270            // ITERATION: CYCLENO and TIME
271            //
272            Block<String> cols( 2 ) ;
273            cols[0] = "CYCLENO" ;
274            cols[1] = "TIME" ;
275            TableIterator iter5( t4, cols ) ;
276            while( !iter5.pastEnd() ) {
277              Table t5 =  iter5.table().sort("POLNO") ;
278              //sharedCol.attach( t5, "CYCLENO" ) ;
279              //uInt cycleNo = sharedCol.asuInt( 0 ) ;
280              Int nrow = t5.nrow() ;
281//               os_ << "nrow = " << nrow << LogIO::POST ;
282             
283              Vector<Int> polnos( nrow ) ;
284              indgen( polnos, 0 ) ;
285              Int polid = addPolarization( polnos ) ;
286//               os_ << "polid = " << polid << LogIO::POST ;
287             
288              // DATA/FLOAT_DATA
289              ROArrayColumn<Float> specCol( t5, "SPECTRA" ) ;
290              ROArrayColumn<uChar> flagCol( t5, "FLAGTRA" ) ;
291              uInt nchan = specCol( 0 ).size() ;
292              IPosition cellshape( 2, nrow, nchan ) ;
293              if ( useFloatData_ ) {
294                // FLOAT_DATA
295                Matrix<Float> dataArr( cellshape ) ;
296                Matrix<Bool> flagArr( cellshape ) ;
297                Vector<Bool> tmpB ;
298                for ( Int ipol = 0 ; ipol < nrow ; ipol++ ) {
299                  dataArr.row( ipol ) = specCol( ipol ) ;
300                  tmpB.reference( flagArr.row( ipol ) ) ;
301                  convertArray( tmpB, flagCol( ipol ) ) ;
302                }
303                ((RecordFieldPtr< Array<Float> > *)dataRF)->define( dataArr ) ;
304               
305                // FLAG
306                flagRF.define( flagArr ) ;
307              }
308              else if ( useData_ ) {
309                // DATA
310                // assume nrow = 4
311                Matrix<Complex> dataArr( cellshape ) ;
312                Vector<Float> zeroIm( nchan, 0 ) ;
313                Matrix<Float> dummy( IPosition( 2, 2, nchan ) ) ;
314                dummy.row( 0 ) = specCol( 0 ) ;
315                dummy.row( 1 ) = zeroIm ;
316                dataArr.row( 0 ) = RealToComplex( dummy ) ;
317                dummy.row( 0 ) = specCol( 1 ) ;
318                dataArr.row( 3 ) = RealToComplex( dummy ) ;
319                dummy.row( 0 ) = specCol( 2 ) ;
320                dummy.row( 1 ) = specCol( 3 ) ;
321                dataArr.row( 1 ) = RealToComplex( dummy ) ;
322                dataArr.row( 2 ) = conj( dataArr.row( 1 ) ) ;
323                ((RecordFieldPtr< Array<Complex> > *)dataRF)->define( dataArr ) ;
324               
325               
326                // FLAG
327                Matrix<Bool> flagArr( cellshape ) ;
328                Vector<Bool> tmpB ;
329                tmpB.reference( flagArr.row( 0 ) ) ;
330                convertArray( tmpB, flagCol( 0 ) ) ;
331                tmpB.reference( flagArr.row( 3 ) ) ;
332                convertArray( tmpB, flagCol( 3 ) ) ;
333                tmpB.reference( flagArr.row( 1 ) ) ;
334                convertArray( tmpB, ( flagCol( 2 ) | flagCol( 3 ) ) ) ;
335                flagArr.row( 2 ) = flagArr.row( 1 ) ;
336                flagRF.define( flagArr ) ;
337              }
338
339              // FLAG_ROW
340              sharedCol.attach( t5, "FLAGROW" ) ;
341              Vector<uInt> flagRowArr( nrow ) ;
342              for ( Int irow = 0 ; irow < nrow ; irow++ )
343                flagRowArr[irow] = sharedCol.asuInt( irow ) ;
344              *flagrowRF = anyNE( flagRowArr, (uInt)0 ) ;
345
346              // TIME and TIME_CENTROID
347              sharedCol.attach( t5, "TIME" ) ;
348              Double mTimeV = (Double)sharedCol.asdouble( 0 ) * 86400.0 ; // day -> sec
349              *timeRF = mTimeV ;
350              *timecRF = mTimeV ;
351
352              // INTERVAL and EXPOSURE
353              sharedCol.attach( t5, "INTERVAL" ) ;
354              Double interval = (Double)sharedCol.asdouble( 0 ) ;
355              *intervalRF = interval ;
356              *exposureRF = interval ;
357             
358              // WEIGHT and SIGMA
359              // always 1 at the moment
360              Vector<Float> wArr( nrow, 1.0 ) ;
361              weightRF.define( wArr ) ;
362              sigmaRF.define( wArr ) ;
363             
364              // add DATA_DESCRIPTION row
365              Int ddid = addDataDescription( polid, ifNo ) ;
366//               os_ << "ddid = " << ddid << LogIO::POST ;
367              *ddidRF = ddid ;
368             
369              // for SYSCAL table
370              sharedCol.attach( t5, "TCAL_ID" ) ;
371              Vector<uInt> tcalIdArr( nrow ) ;
372              for ( Int irow = 0 ; irow < nrow ; irow++ )
373                tcalIdArr[irow] = sharedCol.asuInt( irow ) ;
374//               os_ << "tcalIdArr = " << tcalIdArr << LogIO::POST ;
375              String key = String::toString( tcalIdArr[0] ) ;
376              if ( !tcalIdRec_.isDefined( key ) ) {
377                tcalIdRec_.define( key, tcalIdArr ) ;
378                tcalRowRec_.define( key, t5.rowNumbers() ) ;
379              }
380              else {
381                Vector<uInt> pastrows = tcalRowRec_.asArrayuInt( key ) ;
382                tcalRowRec_.define( key, concatenateArray( pastrows, t5.rowNumbers() ) ) ;
383              }
384                           
385              // for POINTING table
386              if ( ptTabName_ == "" ) {
387                ROArrayColumn<Double> dirCol( t5, "DIRECTION" ) ;
388                Vector<Double> dir = dirCol( 0 ) ;
389                dirCol.attach( t5, "SCANRATE" ) ;
390                Vector<Double> rate = dirCol( 0 ) ;
391                Matrix<Double> msDir( 2, 1 ) ;
392                msDir.column( 0 ) = dir ;
393                if ( anyNE( rate, 0.0 ) ) {
394                  msDir.resize( 2, 2 ) ;
395                  msDir.column( 1 ) = rate ;
396                }
397                addPointing( fieldName, mTimeV, interval, msDir ) ;
398              }
399             
400              // FLAG_CATEGORY is tentatively set
401              flagcatRF.define( Cube<Bool>( nrow, nchan, 1, False ) ) ;
402             
403              // add row
404              mstable_->addRow( 1, True ) ;
405              row.put( mstable_->nrow()-1 ) ;
406             
407              iter5.next() ;
408            }
409           
410            iter4.next() ;
411          }
412
413          // add SPECTRAL_WINDOW row
414          if ( allNE( processedFreqId, freqId ) ) {
415            uInt vsize = processedFreqId.size() ;
416            processedFreqId.resize( vsize+1, True ) ;
417            processedFreqId[vsize] = freqId ;
418            addSpectralWindow( ifNo, freqId ) ;
419          }
420         
421          iter3.next() ;
422        }
423       
424        iter2.next() ;
425      }
426     
427      // add FEED row
428      addFeed( beamNo ) ;
429     
430      iter1.next() ;
431    }
432   
433    // add FIELD row
434    addField( fieldId, fieldName, srcName, minTime, scanRate ) ;
435
436    iter0.next() ;
437  }
438
439//   delete tpoolr ;
440  delete dataRF ;
441
442  // SYSCAL
443  if ( isTcal_ )
444    fillSysCal() ;
445
446  // fill empty SPECTRAL_WINDOW rows
447  infillSpectralWindow() ;
448
449  // ASDM tables
450  const TableRecord &stKeys = table_->table().keywordSet() ;
451  TableRecord &msKeys = mstable_->rwKeywordSet() ;
452  uInt nfields = stKeys.nfields() ;
453  for ( uInt ifield = 0 ; ifield < nfields ; ifield++ ) {
454    String kname = stKeys.name( ifield ) ;
455    if ( kname.find( "ASDM" ) != String::npos ) {
456      String asdmpath = stKeys.asString( ifield ) ;
457      os_ << "found ASDM table: " << asdmpath << LogIO::POST ;
458      if ( Table::isReadable( asdmpath ) ) {
459        Table newAsdmTab( asdmpath, Table::Old ) ;
460        newAsdmTab.copy( filename_+"/"+kname, Table::New ) ;
461        os_ << "add subtable: " << kname << LogIO::POST ;
462        msKeys.defineTable( kname, Table( filename_+"/"+kname, Table::Old ) ) ;
463      }
464    }
465  }
466
467  // replace POINTING table with original one if exists
468  if ( ptTabName_ != "" ) {
469    delete mstable_ ;
470    mstable_ = 0 ;
471    Table newPtTab( ptTabName_, Table::Old ) ;
472    newPtTab.copy( filename_+"/POINTING", Table::New ) ;
473  }
474
475//   double endSec = gettimeofday_sec() ;
476//   os_ << "end MSWriter::write() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
477
478  return True ;
479}
480 
481void MSWriter::init()
482{
483//   os_.origin( LogOrigin( "MSWriter", "init()", WHERE ) ) ;
484//   double startSec = gettimeofday_sec() ;
485//   os_ << "start MSWriter::init() startSec=" << startSec << LogIO::POST ;
486 
487  // access to scantable
488  header_ = table_->getHeader() ;
489
490  // FLOAT_DATA? or DATA?
491  if ( header_.npol > 2 ) {
492    useFloatData_ = False ;
493    useData_ = True ;
494  }
495  else {
496    useFloatData_ = True ;
497    useData_ = False ;
498  }
499
500  // polarization type
501  polType_ = header_.poltype ;
502  if ( polType_ == "" )
503    polType_ = "stokes" ;
504  else if ( polType_.find( "linear" ) != String::npos )
505    polType_ = "linear" ;
506  else if ( polType_.find( "circular" ) != String::npos )
507    polType_ = "circular" ;
508  else if ( polType_.find( "stokes" ) != String::npos )
509    polType_ = "stokes" ;
510  else if ( polType_.find( "linpol" ) != String::npos )
511    polType_ = "linpol" ;
512  else
513    polType_ = "notype" ;
514
515  // Check if some subtables are exists
516  if ( table_->tcal().table().nrow() != 0 ) {
517    ROTableColumn col( table_->tcal().table(), "TCAL" ) ;
518    if ( col.isDefined( 0 ) ) {
519      os_ << "TCAL table exists: nrow=" << table_->tcal().table().nrow() << LogIO::POST ;
520      isTcal_ = True ;
521    }
522    else {
523      os_ << "No TCAL rows" << LogIO::POST ;
524    }
525  }
526  else {
527    os_ << "No TCAL rows" << LogIO::POST ;
528  }
529  if ( table_->weather().table().nrow() != 0 ) {
530    ROTableColumn col( table_->weather().table(), "TEMPERATURE" ) ;
531    if ( col.isDefined( 0 ) ) {
532      os_ << "WEATHER table exists: nrow=" << table_->weather().table().nrow() << LogIO::POST ;
533      isWeather_ =True ;
534    }
535    else {
536      os_ << "No WEATHER rows" << LogIO::POST ;
537    }
538  }
539  else {
540    os_ << "No WEATHER rows" << LogIO::POST ;
541  }
542
543  // Are TCAL_SPECTRUM and TSYS_SPECTRUM necessary?
544  if ( isTcal_ && header_.nchan != 1 ) {
545    // examine TCAL subtable
546    Table tcaltab = table_->tcal().table() ;
547    ROArrayColumn<Float> tcalCol( tcaltab, "TCAL" ) ;
548    for ( uInt irow = 0 ; irow < tcaltab.nrow() ; irow++ ) {
549      if ( tcalCol( irow ).size() != 1 )
550        tcalSpec_ = True ;
551    }
552    // examine spectral data
553    TableIterator iter0( table_->table(), "IFNO" ) ;
554    while( !iter0.pastEnd() ) {
555      Table t0( iter0.table() ) ;
556      ROArrayColumn<Float> sharedFloatArrCol( t0, "SPECTRA" ) ;
557      uInt len = sharedFloatArrCol( 0 ).size() ;
558      if ( len != 1 ) {
559        sharedFloatArrCol.attach( t0, "TSYS" ) ;
560        if ( sharedFloatArrCol( 0 ).size() != 1 )
561          tsysSpec_ = True ;
562      }
563      iter0.next() ;
564    }
565  }
566
567  // check if reference for POINTING table exists
568  const TableRecord &rec = table_->table().keywordSet() ;
569  if ( rec.isDefined( "POINTING" ) ) {
570    ptTabName_ = rec.asString( "POINTING" ) ;
571    if ( !Table::isReadable( ptTabName_ ) ) {
572      ptTabName_ = "" ;
573    }
574  }
575
576//   double endSec = gettimeofday_sec() ;
577//   os_ << "end MSWriter::init() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
578}
579
580void MSWriter::setupMS()
581{
582//   os_.origin( LogOrigin( "MSWriter", "setupMS()", WHERE ) ) ;
583//   double startSec = gettimeofday_sec() ;
584//   os_ << "start MSWriter::setupMS() startSec=" << startSec << LogIO::POST ;
585
586  TableDesc msDesc = MeasurementSet::requiredTableDesc() ;
587  if ( useFloatData_ )
588    MeasurementSet::addColumnToDesc( msDesc, MSMainEnums::FLOAT_DATA, 2 ) ;
589  else if ( useData_ )
590    MeasurementSet::addColumnToDesc( msDesc, MSMainEnums::DATA, 2 ) ;
591
592  SetupNewTable newtab( filename_, msDesc, Table::New ) ;
593
594  mstable_ = new MeasurementSet( newtab ) ;
595
596  // create subtables
597  TableDesc antennaDesc = MSAntenna::requiredTableDesc() ;
598  SetupNewTable antennaTab( mstable_->antennaTableName(), antennaDesc, Table::New ) ;
599  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::ANTENNA ), Table( antennaTab ) ) ;
600
601  TableDesc dataDescDesc = MSDataDescription::requiredTableDesc() ;
602  SetupNewTable dataDescTab( mstable_->dataDescriptionTableName(), dataDescDesc, Table::New ) ;
603  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::DATA_DESCRIPTION ), Table( dataDescTab ) ) ;
604
605  TableDesc dopplerDesc = MSDoppler::requiredTableDesc() ;
606  SetupNewTable dopplerTab( mstable_->dopplerTableName(), dopplerDesc, Table::New ) ;
607  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::DOPPLER ), Table( dopplerTab ) ) ;
608
609  TableDesc feedDesc = MSFeed::requiredTableDesc() ;
610  SetupNewTable feedTab( mstable_->feedTableName(), feedDesc, Table::New ) ;
611  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::FEED ), Table( feedTab ) ) ;
612
613  TableDesc fieldDesc = MSField::requiredTableDesc() ;
614  SetupNewTable fieldTab( mstable_->fieldTableName(), fieldDesc, Table::New ) ;
615  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::FIELD ), Table( fieldTab ) ) ;
616
617  TableDesc flagCmdDesc = MSFlagCmd::requiredTableDesc() ;
618  SetupNewTable flagCmdTab( mstable_->flagCmdTableName(), flagCmdDesc, Table::New ) ;
619  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::FLAG_CMD ), Table( flagCmdTab ) ) ;
620
621  TableDesc freqOffsetDesc = MSFreqOffset::requiredTableDesc() ;
622  SetupNewTable freqOffsetTab( mstable_->freqOffsetTableName(), freqOffsetDesc, Table::New ) ;
623  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::FREQ_OFFSET ), Table( freqOffsetTab ) ) ;
624
625  TableDesc historyDesc = MSHistory::requiredTableDesc() ;
626  SetupNewTable historyTab( mstable_->historyTableName(), historyDesc, Table::New ) ;
627  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::HISTORY ), Table( historyTab ) ) ;
628
629  TableDesc observationDesc = MSObservation::requiredTableDesc() ;
630  SetupNewTable observationTab( mstable_->observationTableName(), observationDesc, Table::New ) ;
631  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::OBSERVATION ), Table( observationTab ) ) ;
632
633  TableDesc pointingDesc = MSPointing::requiredTableDesc() ;
634  SetupNewTable pointingTab( mstable_->pointingTableName(), pointingDesc, Table::New ) ;
635  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::POINTING ), Table( pointingTab ) ) ;
636
637  TableDesc polarizationDesc = MSPolarization::requiredTableDesc() ;
638  SetupNewTable polarizationTab( mstable_->polarizationTableName(), polarizationDesc, Table::New ) ;
639  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::POLARIZATION ), Table( polarizationTab ) ) ;
640
641  TableDesc processorDesc = MSProcessor::requiredTableDesc() ;
642  SetupNewTable processorTab( mstable_->processorTableName(), processorDesc, Table::New ) ;
643  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::PROCESSOR ), Table( processorTab ) ) ;
644
645  TableDesc sourceDesc = MSSource::requiredTableDesc() ;
646  MSSource::addColumnToDesc( sourceDesc, MSSourceEnums::TRANSITION, 1 ) ;
647  MSSource::addColumnToDesc( sourceDesc, MSSourceEnums::REST_FREQUENCY, 1 ) ;
648  MSSource::addColumnToDesc( sourceDesc, MSSourceEnums::SYSVEL, 1 ) ;
649  SetupNewTable sourceTab( mstable_->sourceTableName(), sourceDesc, Table::New ) ;
650  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::SOURCE ), Table( sourceTab ) ) ;
651
652  TableDesc spwDesc = MSSpectralWindow::requiredTableDesc() ;
653  SetupNewTable spwTab( mstable_->spectralWindowTableName(), spwDesc, Table::New ) ;
654  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::SPECTRAL_WINDOW ), Table( spwTab ) ) ;
655
656  TableDesc stateDesc = MSState::requiredTableDesc() ;
657  SetupNewTable stateTab( mstable_->stateTableName(), stateDesc, Table::New ) ;
658  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::STATE ), Table( stateTab ) ) ;
659
660  // TODO: add TCAL_SPECTRUM and TSYS_SPECTRUM if necessary
661  TableDesc sysCalDesc = MSSysCal::requiredTableDesc() ;
662  MSSysCal::addColumnToDesc( sysCalDesc, MSSysCalEnums::TCAL, 2 ) ;
663  MSSysCal::addColumnToDesc( sysCalDesc, MSSysCalEnums::TSYS, 2 ) ;
664  if ( tcalSpec_ )
665    MSSysCal::addColumnToDesc( sysCalDesc, MSSysCalEnums::TCAL_SPECTRUM, 2 ) ;
666  if ( tsysSpec_ )
667    MSSysCal::addColumnToDesc( sysCalDesc, MSSysCalEnums::TSYS_SPECTRUM, 2 ) ;
668  SetupNewTable sysCalTab( mstable_->sysCalTableName(), sysCalDesc, Table::New ) ;
669  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::SYSCAL ), Table( sysCalTab ) ) ;
670
671  TableDesc weatherDesc = MSWeather::requiredTableDesc() ;
672  MSWeather::addColumnToDesc( weatherDesc, MSWeatherEnums::TEMPERATURE ) ;
673  MSWeather::addColumnToDesc( weatherDesc, MSWeatherEnums::PRESSURE ) ;
674  MSWeather::addColumnToDesc( weatherDesc, MSWeatherEnums::REL_HUMIDITY ) ;
675  MSWeather::addColumnToDesc( weatherDesc, MSWeatherEnums::WIND_SPEED ) ;
676  MSWeather::addColumnToDesc( weatherDesc, MSWeatherEnums::WIND_DIRECTION ) ;
677  SetupNewTable weatherTab( mstable_->weatherTableName(), weatherDesc, Table::New ) ;
678  mstable_->rwKeywordSet().defineTable( MeasurementSet::keywordName( MeasurementSet::WEATHER ), Table( weatherTab ) ) ;
679
680  mstable_->initRefs() ;
681
682//   double endSec = gettimeofday_sec() ;
683//   os_ << "end MSWriter::setupMS() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
684}
685
686void MSWriter::fillObservation()
687{
688//   double startSec = gettimeofday_sec() ;
689//   os_ << "start MSWriter::fillObservation() startSec=" << startSec << LogIO::POST ;
690
691  // only 1 row
692  mstable_->observation().addRow( 1, True ) ;
693  MSObservationColumns msObsCols( mstable_->observation() ) ;
694  msObsCols.observer().put( 0, header_.observer ) ;
695  // tentatively put antennaname (from ANTENNA subtable)
696  String hAntennaName = header_.antennaname ;
697  String::size_type pos = hAntennaName.find( "//" ) ;
698  String telescopeName ;
699  if ( pos != String::npos ) {
700    telescopeName = hAntennaName.substr( 0, pos ) ;
701  }
702  else {
703    pos = hAntennaName.find( "@" ) ;
704    telescopeName = hAntennaName.substr( 0, pos ) ;
705  }
706//   os_ << "telescopeName = " << telescopeName << LogIO::POST ;
707  msObsCols.telescopeName().put( 0, telescopeName ) ;
708  msObsCols.project().put( 0, header_.project ) ;
709  //ScalarMeasColumn<MEpoch> timeCol( table_->table().sort("TIME"), "TIME" ) ;
710  Table sortedtable = table_->table().sort("TIME") ;
711  ScalarMeasColumn<MEpoch> timeCol( sortedtable, "TIME" ) ;
712  Vector<MEpoch> trange( 2 ) ;
713  trange[0] = timeCol( 0 ) ;
714  trange[1] = timeCol( table_->nrow()-1 ) ;
715  msObsCols.timeRangeMeas().put( 0, trange ) ;
716
717//   double endSec = gettimeofday_sec() ;
718//   os_ << "end MSWriter::fillObservation() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
719}
720
721void MSWriter::fillAntenna()
722{
723//   double startSec = gettimeofday_sec() ;
724//   os_ << "start MSWriter::fillAntenna() startSec=" << startSec << LogIO::POST ;
725
726  // only 1 row
727  mstable_->antenna().addRow( 1, True ) ;
728  MSAntennaColumns msAntCols( mstable_->antenna() ) ;
729
730  String hAntennaName = header_.antennaname ;
731  String::size_type pos = hAntennaName.find( "//" ) ;
732  String antennaName ;
733  String stationName ;
734  if ( pos != String::npos ) {
735    hAntennaName = hAntennaName.substr( pos+2 ) ;
736  }
737  pos = hAntennaName.find( "@" ) ;
738  if ( pos != String::npos ) {
739    antennaName = hAntennaName.substr( 0, pos ) ;
740    stationName = hAntennaName.substr( pos+1 ) ;
741  }
742  else {
743    antennaName = hAntennaName ;
744    stationName = hAntennaName ;
745  }
746//   os_ << "antennaName = " << antennaName << LogIO::POST ;
747//   os_ << "stationName = " << stationName << LogIO::POST ;
748 
749  msAntCols.name().put( 0, antennaName ) ;
750  msAntCols.station().put( 0, stationName ) ;
751
752//   os_ << "antennaPosition = " << header_.antennaposition << LogIO::POST ;
753 
754  msAntCols.position().put( 0, header_.antennaposition ) ;
755
756  // MOUNT is set to "ALT-AZ"
757  msAntCols.mount().put( 0, "ALT-AZ" ) ;
758
759  Double diameter = getDishDiameter( antennaName ) ;
760  msAntCols.dishDiameterQuant().put( 0, Quantity( diameter, "m" ) ) ;
761
762//   double endSec = gettimeofday_sec() ;
763//   os_ << "end MSWriter::fillAntenna() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
764}
765
766void MSWriter::fillProcessor()
767{
768//   double startSec = gettimeofday_sec() ;
769//   os_ << "start MSWriter::fillProcessor() startSec=" << startSec << LogIO::POST ;
770 
771  // only add empty 1 row
772  MSProcessor msProc = mstable_->processor() ;
773  msProc.addRow( 1, True ) ;
774
775//   double endSec = gettimeofday_sec() ;
776//   os_ << "end MSWriter::fillProcessor() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
777}
778
779void MSWriter::fillSource()
780{
781//   double startSec = gettimeofday_sec() ;
782//   os_ << "start MSWriter::fillSource() startSec=" << startSec << LogIO::POST ;
783 
784  // access to MS SOURCE subtable
785  MSSource msSrc = mstable_->source() ;
786
787  // access to MOLECULE subtable
788  STMolecules stm = table_->molecules() ;
789
790  Int srcId = 0 ;
791  Vector<Double> restFreq ;
792  Vector<String> molName ;
793  Vector<String> fMolName ;
794
795  // row based
796  TableRow row( msSrc ) ;
797  TableRecord &rec = row.record() ;
798  RecordFieldPtr<Int> srcidRF( rec, "SOURCE_ID" ) ;
799  RecordFieldPtr<String> nameRF( rec, "NAME" ) ;
800  RecordFieldPtr< Array<Double> > srcpmRF( rec, "PROPER_MOTION" ) ;
801  RecordFieldPtr< Array<Double> > srcdirRF( rec, "DIRECTION" ) ;
802  RecordFieldPtr<Int> numlineRF( rec, "NUM_LINES" ) ;
803  RecordFieldPtr< Array<Double> > restfreqRF( rec, "REST_FREQUENCY" ) ;
804  RecordFieldPtr< Array<Double> > sysvelRF( rec, "SYSVEL" ) ;
805  RecordFieldPtr< Array<String> > transitionRF( rec, "TRANSITION" ) ;
806  RecordFieldPtr<Double> timeRF( rec, "TIME" ) ;
807  RecordFieldPtr<Double> intervalRF( rec, "INTERVAL" ) ;
808  RecordFieldPtr<Int> spwidRF( rec, "SPECTRAL_WINDOW_ID" ) ;
809
810  //
811  // ITERATION: SRCNAME
812  //
813  TableIterator iter0( table_->table(), "SRCNAME" ) ;
814  while( !iter0.pastEnd() ) {
815    //Table t0( iter0.table() ) ;
816    Table t0 =  iter0.table()  ;
817
818    // get necessary information
819    ROScalarColumn<String> srcNameCol( t0, "SRCNAME" ) ;
820    String srcName = srcNameCol( 0 ) ;
821    ROArrayColumn<Double> sharedDArrRCol( t0, "SRCPROPERMOTION" ) ;
822    Vector<Double> srcPM = sharedDArrRCol( 0 ) ;
823    sharedDArrRCol.attach( t0, "SRCDIRECTION" ) ;
824    Vector<Double> srcDir = sharedDArrRCol( 0 ) ;
825    ROScalarColumn<Double> srcVelCol( t0, "SRCVELOCITY" ) ;
826    Double srcVel = srcVelCol( 0 ) ;
827
828    // NAME
829    *nameRF = srcName ;
830
831    // SOURCE_ID
832    *srcidRF = srcId ;
833
834    // PROPER_MOTION
835    *srcpmRF = srcPM ;
836   
837    // DIRECTION
838    *srcdirRF = srcDir ;
839
840    //
841    // ITERATION: MOLECULE_ID
842    //
843    TableIterator iter1( t0, "MOLECULE_ID" ) ;
844    while( !iter1.pastEnd() ) {
845      //Table t1( iter1.table() ) ;
846      Table t1 = iter1.table() ;
847
848      // get necessary information
849      ROScalarColumn<uInt> molIdCol( t1, "MOLECULE_ID" ) ;
850      uInt molId = molIdCol( 0 ) ;
851      stm.getEntry( restFreq, molName, fMolName, molId ) ;
852
853      uInt numFreq = restFreq.size() ;
854     
855      // NUM_LINES
856      *numlineRF = numFreq ;
857
858      // REST_FREQUENCY
859      *restfreqRF = restFreq ;
860
861      // TRANSITION
862      //*transitionRF = fMolName ;
863      Vector<String> transition ;
864      if ( fMolName.size() != 0 ) {
865        transition = fMolName ;
866      }
867      else if ( molName.size() != 0 ) {
868        transition = molName ;
869      }
870      else {
871        transition.resize( numFreq ) ;
872        transition = "" ;
873      }
874      *transitionRF = transition ;
875
876      // SYSVEL
877      Vector<Double> sysvelArr( numFreq, srcVel ) ;
878      *sysvelRF = sysvelArr ;
879
880      //
881      // ITERATION: IFNO
882      //
883      TableIterator iter2( t1, "IFNO" ) ;
884      while( !iter2.pastEnd() ) {
885        //Table t2( iter2.table() ) ;
886        Table t2 = iter2.table() ;
887        uInt nrow = msSrc.nrow() ;
888
889        // get necessary information
890        ROScalarColumn<uInt> ifNoCol( t2, "IFNO" ) ;
891        uInt ifno = ifNoCol( 0 ) ; // IFNO = SPECTRAL_WINDOW_ID
892        Double midTime ;
893        Double interval ;
894        getValidTimeRange( midTime, interval, t2 ) ;
895
896        // fill SPECTRAL_WINDOW_ID
897        *spwidRF = ifno ;
898
899        // fill TIME, INTERVAL
900        *timeRF = midTime ;
901        *intervalRF = interval ;
902
903        // add row
904        msSrc.addRow( 1, True ) ;
905        row.put( nrow ) ;
906
907        iter2.next() ;
908      }
909
910      iter1.next() ;
911    }
912
913    // increment srcId if SRCNAME changed
914    srcId++ ;
915
916    iter0.next() ;
917  }
918
919//   double endSec = gettimeofday_sec() ;
920//   os_ << "end MSWriter::fillSource() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
921}
922
923void MSWriter::fillWeather()
924{
925//   double startSec = gettimeofday_sec() ;
926//   os_ << "start MSWriter::fillWeather() startSec=" << startSec << LogIO::POST ;
927
928  // access to MS WEATHER subtable
929  MSWeather msw = mstable_->weather() ;
930
931  // access to WEATHER subtable
932  Table stw = table_->weather().table() ;
933  uInt nrow = stw.nrow() ;
934
935  if ( nrow == 0 )
936    return ;
937
938  msw.addRow( nrow, True ) ;
939  MSWeatherColumns mswCols( msw ) ;
940
941  // ANTENNA_ID is always 0
942  Vector<Int> antIdArr( nrow, 0 ) ;
943  mswCols.antennaId().putColumn( antIdArr ) ;
944
945  // fill weather status
946  ROScalarColumn<Float> sharedFloatCol( stw, "TEMPERATURE" ) ;
947  mswCols.temperature().putColumn( sharedFloatCol ) ;
948  sharedFloatCol.attach( stw, "PRESSURE" ) ;
949  mswCols.pressure().putColumn( sharedFloatCol ) ;
950  sharedFloatCol.attach( stw, "HUMIDITY" ) ;
951  mswCols.relHumidity().putColumn( sharedFloatCol ) ;
952  sharedFloatCol.attach( stw, "WINDSPEED" ) ;
953  mswCols.windSpeed().putColumn( sharedFloatCol ) ;
954  sharedFloatCol.attach( stw, "WINDAZ" ) ;
955  mswCols.windDirection().putColumn( sharedFloatCol ) ;
956
957  // fill TIME and INTERVAL
958  Double midTime ;
959  Double interval ;
960  Vector<Double> intervalArr( nrow, 0.0 ) ;
961  TableIterator iter( table_->table(), "WEATHER_ID" ) ;
962  while( !iter.pastEnd() ) {
963    //Table tab( iter.table() ) ;
964    Table tab = iter.table() ;
965
966    ROScalarColumn<uInt> widCol( tab, "WEATHER_ID" ) ;
967    uInt wid = widCol( 0 ) ;
968
969    getValidTimeRange( midTime, interval, tab ) ;
970    mswCols.time().put( wid, midTime ) ;
971    intervalArr[wid] = interval ;
972
973    iter.next() ;
974  }
975  mswCols.interval().putColumn( intervalArr ) ;
976
977//   double endSec = gettimeofday_sec() ;
978//   os_ << "end MSWriter::fillWeather() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
979}
980
981void MSWriter::fillSysCal()
982{
983//   double startSec = gettimeofday_sec() ;
984//   os_ << "start MSWriter::fillSysCal() startSec=" << startSec << LogIO::POST ;
985
986  //tcalIdRec_.print( cout ) ;
987
988  // access to MS SYSCAL subtable
989  MSSysCal mssc = mstable_->sysCal() ;
990
991  // access to TCAL subtable
992  Table stt = table_->tcal().table() ;
993  uInt nrow = stt.nrow() ;
994
995  // access to MAIN table
996  Block<String> cols( 6 ) ;
997  cols[0] = "TIME" ;
998  cols[1] = "TCAL_ID" ;
999  cols[2] = "TSYS" ;
1000  cols[3] = "BEAMNO" ;
1001  cols[4] = "IFNO" ;
1002  cols[5] = "INTERVAL" ;
1003  Table tab = table_->table().project( cols ) ;
1004
1005  if ( nrow == 0 )
1006    return ;
1007
1008  nrow = tcalIdRec_.nfields() ;
1009
1010  Double midTime ;
1011  Double interval ;
1012  String timeStr ;
1013
1014  // row base
1015  TableRow row( mssc ) ;
1016  TableRecord &trec = row.record() ;
1017  RecordFieldPtr<Int> antennaRF( trec, "ANTENNA_ID" ) ;
1018  RecordFieldPtr<Int> feedRF( trec, "FEED_ID" ) ;
1019  RecordFieldPtr<Int> spwRF( trec, "SPECTRAL_WINDOW_ID" ) ;
1020  RecordFieldPtr<Double> timeRF( trec, "TIME" ) ;
1021  RecordFieldPtr<Double> intervalRF( trec, "INTERVAL" ) ;
1022  RecordFieldPtr< Array<Float> > tsysRF( trec, "TSYS" ) ;
1023  RecordFieldPtr< Array<Float> > tcalRF( trec, "TCAL" ) ;
1024  RecordFieldPtr< Array<Float> > tsysspRF ;
1025  RecordFieldPtr< Array<Float> > tcalspRF ;
1026  if ( tsysSpec_ )
1027    tsysspRF.attachToRecord( trec, "TSYS_SPECTRUM" ) ;
1028  if ( tcalSpec_ )
1029    tcalspRF.attachToRecord( trec, "TCAL_SPECTRUM" ) ;
1030
1031  // ANTENNA_ID is always 0
1032  *antennaRF = 0 ;
1033
1034  Table sortedstt = stt.sort( "ID" ) ;
1035  ROArrayColumn<Float> tcalCol( sortedstt, "TCAL" ) ;
1036  ROTableColumn idCol( sortedstt, "ID" ) ;
1037  ROArrayColumn<Float> tsysCol( tab, "TSYS" ) ;
1038  ROTableColumn tcalidCol( tab, "TCAL_ID" ) ;
1039  ROTableColumn timeCol( tab, "TIME" ) ;
1040  ROTableColumn intervalCol( tab, "INTERVAL" ) ;
1041  ROTableColumn beamnoCol( tab, "BEAMNO" ) ;
1042  ROTableColumn ifnoCol( tab, "IFNO" ) ;
1043  for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
1044//     double t1 = gettimeofday_sec() ;
1045    Vector<uInt> ids = tcalIdRec_.asArrayuInt( irow ) ;
1046//     os_ << "ids = " << ids << LogIO::POST ;
1047    uInt npol = ids.size() ;
1048    Vector<uInt> rows = tcalRowRec_.asArrayuInt( irow ) ;
1049//     os_ << "rows = " << rows << LogIO::POST ;
1050    Vector<Double> atime( rows.nelements() ) ;
1051    Vector<Double> ainterval( rows.nelements() ) ;
1052    Vector<uInt> atcalid( rows.nelements() ) ;
1053    for( uInt jrow = 0 ; jrow < rows.nelements() ; jrow++ ) {
1054      atime[jrow] = (Double)timeCol.asdouble( rows[jrow] ) ;
1055      ainterval[jrow] = (Double)intervalCol.asdouble( rows[jrow] ) ;
1056      atcalid[jrow] = tcalidCol.asuInt( rows[jrow] ) ;
1057    }
1058    Vector<Float> dummy = tsysCol( rows[0] ) ;
1059    Matrix<Float> tsys( npol,dummy.nelements() ) ;
1060    tsys.row( 0 ) = dummy ;
1061    for ( uInt jrow = 1 ; jrow < npol ; jrow++ )
1062      tsys.row( jrow ) = tsysCol( rows[jrow] ) ;
1063
1064    // FEED_ID
1065    *feedRF = beamnoCol.asuInt( rows[0] ) ;
1066
1067    // SPECTRAL_WINDOW_ID
1068    *spwRF = ifnoCol.asuInt( rows[0] ) ;
1069
1070    // TIME and INTERVAL
1071    getValidTimeRange( midTime, interval, atime, ainterval ) ;
1072    *timeRF = midTime ;
1073    *intervalRF = interval ;
1074
1075    // TCAL and TSYS
1076    Matrix<Float> tcal ;
1077    Table t ;
1078    if ( idCol.asuInt( ids[0] ) == ids[0] ) {
1079//       os_ << "sorted at irow=" << irow << " ids[0]=" << ids[0] << LogIO::POST ;
1080      Vector<Float> dummyC = tcalCol( ids[0] ) ;
1081      tcal.resize( npol, dummyC.size() ) ;
1082      tcal.row( 0 ) = dummyC ;
1083    }
1084    else {
1085//       os_ << "NOT sorted at irow=" << irow << " ids[0]=" << ids[0] << LogIO::POST ;
1086      t = stt( stt.col("ID") == ids[0] ) ;
1087      Vector<Float> dummyC = tcalCol( 0 ) ;
1088      tcal.resize( npol, dummyC.size() ) ;
1089      tcal.row( 0 ) = dummyC ;
1090    }
1091    if ( npol == 2 ) {
1092      if ( idCol.asuInt( ids[1] ) == ids[1] ) {
1093//         os_ << "sorted at irow=" << irow << " ids[1]=" << ids[1] << LogIO::POST ;
1094        tcal.row( 1 ) = tcalCol( ids[1] ) ;
1095      }
1096      else {
1097//         os_ << "NOT sorted at irow=" << irow << " ids[1]=" << ids[1] << LogIO::POST ;
1098        t = stt( stt.col("ID") == ids[1] ) ;
1099        tcalCol.attach( t, "TCAL" ) ;
1100        tcal.row( 1 ) = tcalCol( 1 ) ;
1101      }
1102    }
1103    else if ( npol == 3 ) {
1104      if ( idCol.asuInt( ids[2] ) == ids[2] )
1105        tcal.row( 1 ) = tcalCol( ids[2] ) ;
1106      else {
1107        t = stt( stt.col("ID") == ids[2] ) ;
1108        tcalCol.attach( t, "TCAL" ) ;
1109        tcal.row( 1 ) = tcalCol( 0 ) ;
1110      }
1111      if ( idCol.asuInt( ids[1] ) == ids[1] )
1112        tcal.row( 2 ) = tcalCol( ids[1] ) ;
1113      else {
1114        t = stt( stt.col("ID") == ids[1] ) ;
1115        tcalCol.attach( t, "TCAL" ) ;
1116        tcal.row( 2 ) = tcalCol( 0 ) ;
1117      }
1118    }
1119    else if ( npol == 4 ) {
1120      if ( idCol.asuInt( ids[2] ) == ids[2] )
1121        tcal.row( 1 ) = tcalCol( ids[2] ) ;
1122      else {
1123        t = stt( stt.col("ID") == ids[2] ) ;
1124        tcalCol.attach( t, "TCAL" ) ;
1125        tcal.row( 1 ) = tcalCol( 0 ) ;
1126      }
1127      if ( idCol.asuInt( ids[3] ) == ids[3] )
1128        tcal.row( 2 ) = tcalCol( ids[3] ) ;
1129      else {
1130        t = stt( stt.col("ID") == ids[3] ) ;
1131        tcalCol.attach( t, "TCAL" ) ;
1132        tcal.row( 2 ) = tcalCol( 0 ) ;
1133      }
1134      if ( idCol.asuInt( ids[1] ) == ids[1] )
1135        tcal.row( 2 ) = tcalCol( ids[1] ) ;
1136      else {
1137        t = stt( stt.col("ID") == ids[1] ) ;
1138        tcalCol.attach( t, "TCAL" ) ;
1139        tcal.row( 3 ) = tcalCol( 0 ) ;
1140      }
1141    }
1142    if ( tcalSpec_ ) {
1143      // put TCAL_SPECTRUM
1144      //*tcalspRF = tcal ;
1145      tcalspRF.define( tcal ) ;
1146      // set TCAL (mean of TCAL_SPECTRUM)
1147      Matrix<Float> tcalMean( npol, 1 ) ;
1148      for ( uInt iid = 0 ; iid < npol ; iid++ ) {
1149        tcalMean( iid, 0 ) = mean( tcal.row(iid) ) ;
1150      }
1151      // put TCAL
1152      *tcalRF = tcalMean ;
1153    }
1154    else {
1155      // put TCAL
1156      *tcalRF = tcal ;
1157    }
1158   
1159    if ( tsysSpec_ ) {
1160      // put TSYS_SPECTRUM
1161      //*tsysspRF = tsys ;
1162      tsysspRF.define( tsys ) ;
1163      // set TSYS (mean of TSYS_SPECTRUM)
1164      Matrix<Float> tsysMean( npol, 1 ) ;
1165      for ( uInt iid = 0 ; iid < npol ; iid++ ) {
1166        tsysMean( iid, 0 ) = mean( tsys.row(iid) ) ;
1167      }
1168      // put TSYS
1169      *tsysRF = tsysMean ;
1170    }
1171    else {
1172      // put TSYS
1173      *tsysRF = tsys ;
1174    }
1175
1176    // add row
1177    mssc.addRow( 1, True ) ;
1178    row.put( mssc.nrow()-1 ) ;
1179
1180//     double t2 = gettimeofday_sec() ;
1181//     os_ << irow << "th loop elapsed time = " << t2-t1 << "sec" << LogIO::POST ;
1182  }
1183 
1184//   double endSec = gettimeofday_sec() ;
1185//   os_ << "end MSWriter::fillSysCal() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1186}
1187
1188void MSWriter::addFeed( Int id )
1189{
1190//   double startSec = gettimeofday_sec() ;
1191//   os_ << "start MSWriter::addFeed() startSec=" << startSec << LogIO::POST ;
1192
1193  // add row
1194  MSFeed msFeed = mstable_->feed() ;
1195  msFeed.addRow( 1, True ) ;
1196  Int nrow = msFeed.nrow() ;
1197  Int numReceptors = 2 ;
1198  Vector<String> polType( numReceptors ) ;
1199  Matrix<Double> beamOffset( 2, numReceptors ) ;
1200  beamOffset = 0.0 ;
1201  Vector<Double> receptorAngle( numReceptors, 0.0 ) ;
1202  if ( polType_ == "linear" ) {
1203    polType[0] = "X" ;
1204    polType[1] = "Y" ;
1205  }
1206  else if ( polType_ == "circular" ) {
1207    polType[0] = "R" ;
1208    polType[1] = "L" ;
1209  }
1210  else {
1211    polType[0] = "X" ;
1212    polType[1] = "Y" ;
1213  }
1214  Matrix<Complex> polResponse( numReceptors, numReceptors, 0.0 ) ;
1215  for ( Int i = 0 ; i < numReceptors ; i++ )
1216    polResponse( i, i ) = 0.0 ;
1217
1218  MSFeedColumns msFeedCols( mstable_->feed() ) ;
1219
1220  msFeedCols.feedId().put( nrow-1, id ) ;
1221  msFeedCols.antennaId().put( nrow-1, 0 ) ;
1222  msFeedCols.numReceptors().put( nrow-1, numReceptors ) ;
1223  msFeedCols.polarizationType().put( nrow-1, polType ) ;
1224  msFeedCols.beamOffset().put( nrow-1, beamOffset ) ;
1225  msFeedCols.receptorAngle().put( nrow-1, receptorAngle ) ;
1226  msFeedCols.polResponse().put( nrow-1, polResponse ) ;
1227
1228//   double endSec = gettimeofday_sec() ;
1229//   os_ << "end MSWriter::addFeed() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1230}
1231
1232void MSWriter::addSpectralWindow( Int spwid, Int freqid )
1233{
1234//   double startSec = gettimeofday_sec() ;
1235//   os_ << "start MSWriter::addSpectralWindow() startSec=" << startSec << LogIO::POST ;
1236 
1237  // add row
1238  MSSpectralWindow msSpw = mstable_->spectralWindow() ;
1239  while( (Int)msSpw.nrow() <= spwid ) {
1240    msSpw.addRow( 1, True ) ;
1241  }
1242 
1243  MSSpWindowColumns msSpwCols( msSpw ) ;
1244
1245  STFrequencies stf = table_->frequencies() ;
1246
1247  // MEAS_FREQ_REF
1248  msSpwCols.measFreqRef().put( spwid, stf.getFrame( True ) ) ;
1249
1250  Double refpix ;
1251  Double refval ;
1252  Double inc ;
1253  stf.getEntry( refpix, refval, inc, (uInt)freqid ) ;
1254
1255  // NUM_CHAN
1256  Int nchan = (Int)(refpix * 2) + 1 ;
1257  if ( nchan == 0 )
1258    nchan = 1 ;
1259  msSpwCols.numChan().put( spwid, nchan ) ;
1260
1261  // TOTAL_BANDWIDTH
1262  Double bw = nchan * inc ;
1263  msSpwCols.totalBandwidth().put( spwid, bw ) ;
1264
1265  // REF_FREQUENCY
1266  Double refFreq = refval - refpix * inc ;
1267  msSpwCols.refFrequency().put( spwid, refFreq ) ;
1268
1269  // NET_SIDEBAND
1270  // tentative: USB->0, LSB->1
1271  Int netSideband = 0 ;
1272  if ( inc < 0 )
1273    netSideband = 1 ;
1274  msSpwCols.netSideband().put( spwid, netSideband ) ;
1275
1276  // RESOLUTION, CHAN_WIDTH, EFFECTIVE_BW
1277  Vector<Double> sharedDoubleArr( nchan, inc ) ;
1278  msSpwCols.resolution().put( spwid, sharedDoubleArr ) ;
1279  msSpwCols.chanWidth().put( spwid, sharedDoubleArr ) ;
1280  msSpwCols.effectiveBW().put( spwid, sharedDoubleArr ) ;
1281
1282  // CHAN_FREQ
1283  indgen( sharedDoubleArr, refFreq, inc ) ;
1284  msSpwCols.chanFreq().put( spwid, sharedDoubleArr ) ;
1285
1286//   double endSec = gettimeofday_sec() ;
1287//   os_ << "end MSWriter::addSpectralWindow() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1288}
1289
1290void MSWriter::addField( Int fid, String fieldname, String srcname, Double t, Vector<Double> rate )
1291{
1292//   double startSec = gettimeofday_sec() ;
1293//   os_ << "start MSWriter::addField() startSec=" << startSec << LogIO::POST ;
1294 
1295  MSField msField = mstable_->field() ;
1296  while( (Int)msField.nrow() <= fid ) {
1297    msField.addRow( 1, True ) ;
1298  }
1299  MSFieldColumns msFieldCols( msField ) ;
1300
1301  // Access to SOURCE table
1302  MSSource msSrc = mstable_->source() ;
1303
1304  // fill target row
1305  msFieldCols.name().put( fid, fieldname ) ;
1306  msFieldCols.time().put( fid, t ) ;
1307  Int numPoly = 0 ;
1308  if ( anyNE( rate, 0.0 ) )
1309    numPoly = 1 ;
1310  msFieldCols.numPoly().put( fid, numPoly ) ;
1311  MSSourceIndex msSrcIdx( msSrc ) ;
1312  Int srcId = -1 ;
1313  Vector<Int> srcIdArr = msSrcIdx.matchSourceName( srcname ) ;
1314  if ( srcIdArr.size() != 0 ) {
1315    srcId = srcIdArr[0] ;
1316    MSSource msSrcSel = msSrc( msSrc.col("SOURCE_ID") == srcId ) ;
1317    ROMSSourceColumns msSrcCols( msSrcSel ) ;
1318    Vector<Double> srcDir = msSrcCols.direction()( 0 ) ;
1319    Matrix<Double> srcDirA( IPosition( 2, 2, 1+numPoly ) ) ;
1320//     os_ << "srcDirA = " << srcDirA << LogIO::POST ;
1321//     os_ << "sliced srcDirA = " << srcDirA.column( 0 ) << LogIO::POST ;
1322    srcDirA.column( 0 ) = srcDir ;
1323//     os_ << "srcDirA = " << srcDirA << LogIO::POST ;
1324    if ( numPoly != 0 )
1325      srcDirA.column( 1 ) = rate ;
1326    msFieldCols.phaseDir().put( fid, srcDirA ) ;
1327    msFieldCols.referenceDir().put( fid, srcDirA ) ;
1328    msFieldCols.delayDir().put( fid, srcDirA ) ;
1329  }
1330  msFieldCols.sourceId().put( fid, srcId ) ;
1331
1332//   double endSec = gettimeofday_sec() ;
1333//   os_ << "end MSWriter::addField() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1334}
1335
1336void MSWriter::addPointing( String &name, Double &me, Double &interval, Matrix<Double> &dir )
1337{
1338//   double startSec = gettimeofday_sec() ;
1339//   os_ << "start MSWriter::addPointing() startSec=" << startSec << LogIO::POST ;
1340 
1341  // access to POINTING subtable
1342  MSPointing msp = mstable_->pointing() ;
1343  uInt nrow = msp.nrow() ;
1344
1345  // add row
1346  msp.addRow( 1, True ) ;
1347
1348  // fill row
1349  TableRow row( msp ) ;
1350  TableRecord &rec = row.record() ;
1351  RecordFieldPtr<Int> antennaRF( rec, "ANTENNA_ID" ) ;
1352  *antennaRF = 0 ;
1353  RecordFieldPtr<Int> numpolyRF( rec, "NUM_POLY" ) ;
1354  *numpolyRF = dir.ncolumn() ;
1355  RecordFieldPtr<Double> timeRF( rec, "TIME" ) ;
1356  *timeRF = me ;
1357  RecordFieldPtr<Double> toriginRF( rec, "TIME_ORIGIN" ) ;
1358  *toriginRF = me ;
1359  RecordFieldPtr<Double> intervalRF( rec, "INTERVAL" ) ;
1360  *intervalRF = interval ;
1361  RecordFieldPtr<String> nameRF( rec, "NAME" ) ;
1362  *nameRF = name ;
1363  RecordFieldPtr<Bool> trackRF( rec, "TRACKING" ) ;
1364  *trackRF = True ;
1365  RecordFieldPtr< Array<Double> > dirRF( rec, "DIRECTION" ) ;
1366  *dirRF = dir ;
1367  RecordFieldPtr< Array<Double> > targetRF( rec, "TARGET" ) ;
1368  *dirRF = dir ;
1369  row.put( nrow ) ;
1370
1371//   double endSec = gettimeofday_sec() ;
1372//   os_ << "end MSWriter::addPointing() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1373}
1374
1375Int MSWriter::addPolarization( Vector<Int> polnos )
1376{
1377//   double startSec = gettimeofday_sec() ;
1378//   os_ << "start MSWriter::addPolarization() startSec=" << startSec << LogIO::POST ;
1379
1380//   os_ << "polnos = " << polnos << LogIO::POST ;
1381  MSPolarization msPol = mstable_->polarization() ;
1382  uInt nrow = msPol.nrow() ;
1383
1384//   // only 1 POLARIZATION row for 1 scantable
1385//   if ( nrow > 0 )
1386//     return 0 ;
1387 
1388  Vector<Int> corrType = toCorrType( polnos ) ;
1389 
1390  ROArrayColumn<Int> corrtCol( msPol, "CORR_TYPE" ) ;
1391  //Matrix<Int> corrTypeArr = corrtCol.getColumn() ;
1392  Int polid = -1 ;
1393  for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
1394    Vector<Int> corrTypeArr = corrtCol( irow ) ;
1395    if ( corrType.nelements() == corrTypeArr.nelements()
1396         && allEQ( corrType, corrTypeArr ) ) {
1397      polid = irow ;
1398      break ;
1399    }
1400  }
1401
1402  if ( polid == -1 ) {
1403    MSPolarizationColumns msPolCols( msPol ) ;
1404
1405    // add row
1406    msPol.addRow( 1, True ) ;
1407    polid = (Int)nrow ;
1408
1409    // CORR_TYPE
1410    msPolCols.corrType().put( nrow, corrType ) ;
1411
1412    // NUM_CORR
1413    uInt npol = corrType.size() ;
1414    msPolCols.numCorr().put( nrow, npol ) ;
1415
1416    // CORR_PRODUCT
1417    Matrix<Int> corrProd( 2, npol, -1 ) ;
1418    if ( npol == 1 ) {
1419      corrProd = 0 ;
1420    }
1421    else if ( npol == 2 ) {
1422      corrProd.column( 0 ) = 0 ;
1423      corrProd.column( 1 ) = 1 ;
1424    }
1425    else {
1426      corrProd.column( 0 ) = 0 ;
1427      corrProd.column( 3 ) = 1 ;
1428      corrProd( 0,1 ) = 0 ;
1429      corrProd( 1,1 ) = 1 ;
1430      corrProd( 0,2 ) = 1 ;
1431      corrProd( 1,2 ) = 0 ;
1432    }
1433    msPolCols.corrProduct().put( nrow, corrProd ) ;   
1434  }
1435
1436//   double endSec = gettimeofday_sec() ;
1437//   os_ << "end MSWriter::addPolarization() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1438
1439  return polid ;
1440}
1441
1442Int MSWriter::addDataDescription( Int polid, Int spwid )
1443{
1444//   double startSec = gettimeofday_sec() ;
1445//   os_ << "start MSWriter::addDataDescription() startSec=" << startSec << LogIO::POST ;
1446
1447  MSDataDescription msDataDesc = mstable_->dataDescription() ;
1448  uInt nrow = msDataDesc.nrow() ;
1449
1450  // only 1 POLARIZATION_ID for 1 scantable
1451  Int ddid = -1 ;
1452  ROScalarColumn<Int> spwCol( msDataDesc, "SPECTRAL_WINDOW_ID" ) ;
1453  Vector<Int> spwIds = spwCol.getColumn() ;
1454  //ROScalarColumn<Int> polCol( msDataDesc, "POLARIZATION_ID" ) ;
1455  //Vector<Int> polIds = polCol.getColumn() ;
1456  for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
1457    //if ( spwid == spwIds[irow] && polid == polIds[irow] ) {
1458    if ( spwid == spwIds[irow] ) {
1459      ddid = irow ;
1460      break ;
1461    }
1462  }
1463//   os_ << "ddid = " << ddid << LogIO::POST ;
1464 
1465
1466  if ( ddid == -1 ) {
1467    msDataDesc.addRow( 1, True ) ;
1468    MSDataDescColumns msDataDescCols( msDataDesc ) ;
1469    msDataDescCols.polarizationId().put( nrow, polid ) ;
1470    msDataDescCols.spectralWindowId().put( nrow, spwid ) ;
1471    ddid = (Int)nrow ;
1472  }
1473
1474//   double endSec = gettimeofday_sec() ;
1475//   os_ << "end MSWriter::addDataDescription() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1476
1477  return ddid ;
1478}
1479
1480Int MSWriter::addState( Int st, Int &subscan )
1481{
1482//   double startSec = gettimeofday_sec() ;
1483//   os_ << "start MSWriter::addState() startSec=" << startSec << LogIO::POST ;
1484
1485  // access to STATE subtable
1486  MSState msState = mstable_->state() ;
1487  uInt nrow = msState.nrow() ;
1488
1489  String obsMode ;
1490  Bool isSignal ;
1491  Double tnoise ;
1492  Double tload ;
1493  queryType( st, obsMode, isSignal, tnoise, tload ) ;
1494//   os_ << "obsMode = " << obsMode << " isSignal = " << isSignal << LogIO::POST ;
1495
1496  Int idx = -1 ;
1497  ROScalarColumn<String> obsModeCol( msState, "OBS_MODE" ) ;
1498  ROScalarColumn<Int> subscanCol( msState, "SUB_SCAN" ) ;
1499  for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
1500    if ( obsModeCol(irow) == obsMode
1501         //&& sigCol(irow) == isSignal
1502         //&& refCol(irow) != isSignal
1503         && subscanCol(irow) == subscan ) {
1504      idx = irow ;
1505      break ;
1506    }
1507  }
1508  if ( idx == -1 ) {
1509    msState.addRow( 1, True ) ;
1510    TableRow row( msState ) ;
1511    TableRecord &rec = row.record() ;
1512    RecordFieldPtr<String> obsmodeRF( rec, "OBS_MODE" ) ;
1513    *obsmodeRF = obsMode ;
1514    RecordFieldPtr<Bool> sigRF( rec, "SIG" ) ;
1515    *sigRF = isSignal ;
1516    RecordFieldPtr<Bool> refRF( rec, "REF" ) ;
1517    *refRF = !isSignal ;
1518    RecordFieldPtr<Int> subscanRF( rec, "SUB_SCAN" ) ;
1519    *subscanRF = subscan ;
1520    RecordFieldPtr<Double> noiseRF( rec, "CAL" ) ;
1521    *noiseRF = tnoise ;
1522    RecordFieldPtr<Double> loadRF( rec, "LOAD" ) ;
1523    *loadRF = tload ;
1524    row.put( nrow ) ;
1525    idx = nrow ;
1526  }
1527  subscan++ ;
1528
1529//   double endSec = gettimeofday_sec() ;
1530//   os_ << "end MSWriter::addState() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1531
1532  return idx ;
1533}
1534
1535Vector<Int> MSWriter::toCorrType( Vector<Int> polnos )
1536{
1537//   double startSec = gettimeofday_sec() ;
1538//   os_ << "start MSWriter::toCorrType() startSec=" << startSec << LogIO::POST ;
1539
1540  uInt npol = polnos.size() ;
1541  Vector<Int> corrType( npol, Stokes::Undefined ) ;
1542 
1543  if ( npol == 4 ) {
1544    if ( polType_ == "linear" ) {
1545      for ( uInt ipol = 0 ; ipol < npol ; ipol++ ) {
1546        if ( polnos[ipol] == 0 )
1547          corrType[ipol] = Stokes::XX ;
1548        else if ( polnos[ipol] == 1 )
1549          corrType[ipol] = Stokes::XY ;
1550        else if ( polnos[ipol] == 2 )
1551          corrType[ipol] = Stokes::YX ;
1552        else if ( polnos[ipol] == 3 )
1553          corrType[ipol] = Stokes::YY ;
1554      }
1555    }
1556    else if ( polType_ == "circular" ) {
1557      for ( uInt ipol = 0 ; ipol < npol ; ipol++ ) {
1558        if ( polnos[ipol] == 0 )
1559          corrType[ipol] = Stokes::RR ;
1560        else if ( polnos[ipol] == 1 )
1561          corrType[ipol] = Stokes::RL ;
1562        else if ( polnos[ipol] == 2 )
1563          corrType[ipol] = Stokes::LR ;
1564        else if ( polnos[ipol] == 3 )
1565          corrType[ipol] = Stokes::LL ;
1566      }
1567    }
1568    else if ( polType_ == "stokes" ) {
1569      for ( uInt ipol = 0 ; ipol < npol ; ipol++ ) {
1570        if ( polnos[ipol] == 0 )
1571          corrType[ipol] = Stokes::I ;
1572        else if ( polnos[ipol] == 1 )
1573          corrType[ipol] = Stokes::Q ;
1574        else if ( polnos[ipol] == 2 )
1575          corrType[ipol] = Stokes::U ;
1576        else if ( polnos[ipol] == 3 )
1577          corrType[ipol] = Stokes::V ;
1578      }
1579    }
1580  }
1581  else if ( npol == 2 ) {
1582    if ( polType_ == "linear" ) {
1583      for ( uInt ipol = 0 ; ipol < npol ; ipol++ ) {
1584        if ( polnos[ipol] == 0 )
1585          corrType[ipol] = Stokes::XX ;
1586        else if ( polnos[ipol] == 1 )
1587          corrType[ipol] = Stokes::YY ;
1588      }
1589    }
1590    else if ( polType_ == "circular" ) {
1591      for ( uInt ipol = 0 ; ipol < npol ; ipol++ ) {
1592        if ( polnos[ipol] == 0 )
1593          corrType[ipol] = Stokes::RR ;
1594        else if ( polnos[ipol] == 1 )
1595          corrType[ipol] = Stokes::LL ;
1596      }
1597    }
1598    else if ( polType_ == "stokes" ) {
1599      for ( uInt ipol = 0 ; ipol < npol ; ipol++ ) {
1600        if ( polnos[ipol] == 0 )
1601          corrType[ipol] = Stokes::I ;
1602        else if ( polnos[ipol] == 1 )
1603          corrType[ipol] = Stokes::V ;
1604      }
1605    }
1606    else if ( polType_ == "linpol" ) {
1607      for ( uInt ipol = 0 ; ipol < npol ; ipol++ ) {
1608        if ( polnos[ipol] == 1 )
1609          corrType[ipol] = Stokes::Plinear ;
1610        else if ( polnos[ipol] == 2 )
1611          corrType[ipol] = Stokes::Pangle ;
1612      }
1613    }
1614  }     
1615  else if ( npol == 1 ) {
1616    if ( polType_ == "linear" )
1617      corrType[0] = Stokes::XX ;
1618    else if ( polType_ == "circular" )
1619      corrType[0] = Stokes::RR ;
1620    else if ( polType_ == "stokes" )
1621      corrType[0] = Stokes::I ;
1622  }
1623
1624//   double endSec = gettimeofday_sec() ;
1625//   os_ << "end MSWriter::toCorrType() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1626
1627  return corrType ;
1628}
1629
1630void MSWriter::getValidTimeRange( Double &me, Double &interval, Table &tab )
1631{
1632//   double startSec = gettimeofday_sec() ;
1633//   os_ << "start MSWriter::getVaridTimeRange() startSec=" << startSec << LogIO::POST ;
1634
1635  // sort table
1636  //Table stab = tab.sort( "TIME" ) ;
1637
1638  ROScalarColumn<Double> timeCol( tab, "TIME" ) ;
1639  Vector<Double> timeArr = timeCol.getColumn() ;
1640  Double minTime ;
1641  Double maxTime ;
1642  minMax( minTime, maxTime, timeArr ) ;
1643  Double midTime = 0.5 * ( minTime + maxTime ) * 86400.0 ;
1644  // unit for TIME
1645  // Scantable: "d"
1646  // MS: "s"
1647  me = midTime ;
1648  interval = ( maxTime - minTime ) * 86400.0 ;
1649
1650//   double endSec = gettimeofday_sec() ;
1651//   os_ << "end MSWriter::getValidTimeRange() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1652}
1653
1654void MSWriter::getValidTimeRange( Double &me, Double &interval, Vector<Double> &atime, Vector<Double> &ainterval )
1655{
1656//   double startSec = gettimeofday_sec() ;
1657//   os_ << "start MSWriter::getVaridTimeRange() startSec=" << startSec << LogIO::POST ;
1658
1659  // sort table
1660  //Table stab = tab.sort( "TIME" ) ;
1661
1662  Double minTime ;
1663  Double maxTime ;
1664  minMax( minTime, maxTime, atime ) ;
1665  Double midTime = 0.5 * ( minTime + maxTime ) * 86400.0 ;
1666  // unit for TIME
1667  // Scantable: "d"
1668  // MS: "s"
1669  me = midTime ;
1670  interval = ( maxTime - minTime ) * 86400.0 + mean( ainterval ) ;
1671
1672//   double endSec = gettimeofday_sec() ;
1673//   os_ << "end MSWriter::getValidTimeRange() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1674}
1675
1676//void MSWriter::queryType( Int type, String &stype, Bool &b )
1677void MSWriter::queryType( Int type, String &stype, Bool &b, Double &t, Double &l )
1678{
1679//   double startSec = gettimeofday_sec() ;
1680//   os_ << "start MSWriter::queryType() startSec=" << startSec << LogIO::POST ;
1681
1682  // 2011/03/14 TN
1683  // OBS_MODE string of MS created by importasdm task is slightly
1684  // (but critically) changed.
1685  switch ( type ) {
1686  case SrcType::PSON:
1687    stype = "OBSERVE_TARGET_ON_SOURCE,POSITION_SWITCH" ;
1688    b = True ;
1689    t = 0.0 ;
1690    l = 0.0 ;
1691    break ;
1692  case SrcType::PSOFF:
1693    stype = "OBSERVE_TARGET_OFF_SOURCE,POSITION_SWITCH" ;
1694    b = False ;
1695    t = 0.0 ;
1696    l = 0.0 ;
1697    break ;
1698  case SrcType::NOD:
1699    stype = "OBSERVE_TARGET_ON_SOURCE,NOD" ;
1700    b = True ;
1701    t = 0.0 ;
1702    l = 0.0 ;
1703    break ;
1704  case SrcType::FSON:
1705    stype = "OBSERVE_TARGET_ON_SOURCE,FREQUENCY_SWITCH_SIG" ;
1706    b = True ;
1707    t = 0.0 ;
1708    l = 0.0 ;
1709    break ;
1710  case SrcType::FSOFF:
1711    stype = "OBSERVE_TARGET_ON_SOURCE,FREQUENCY_SWITCH_REF" ;
1712    b = False ;
1713    t = 0.0 ;
1714    l = 0.0 ;
1715    break ;
1716  case SrcType::SKY:
1717    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,UNSPECIFIED" ;
1718    b = False ;
1719    t = 0.0 ;
1720    l = 1.0 ;
1721    break ;
1722  case SrcType::HOT:
1723    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,UNSPECIFIED" ;
1724    b = False ;
1725    t = 0.0 ;
1726    l = 1.0 ;
1727    break ;
1728  case SrcType::WARM:
1729    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,UNSPECIFIED" ;
1730    t = 0.0 ;
1731    b = False ;
1732    l = 1.0 ;
1733    break ;
1734  case SrcType::COLD:
1735    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,UNSPECIFIED" ;
1736    b = False ;
1737    t = 0.0 ;
1738    l = 1.0 ;
1739    break ;
1740  case SrcType::PONCAL:
1741    stype = "CALIBRATE_TEMPERATURE_ON_SOURCE,POSITION_SWITCH" ;
1742    b = True ;
1743    t = 1.0 ;
1744    l = 0.0 ;
1745    break ;
1746  case SrcType::POFFCAL:
1747    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,POSITION_SWITCH" ;
1748    b = False ;
1749    t = 1.0 ;
1750    l = 0.0 ;
1751    break ;
1752  case SrcType::NODCAL:
1753    stype = "CALIBRATE_TEMPERATURE_ON_SOURCE,NOD" ;
1754    b = True ;
1755    t = 1.0 ;
1756    l = 0.0 ;
1757    break ;
1758  case SrcType::FONCAL:
1759    stype = "CALIBRATE_TEMPERATURE_ON_SOURCE,FREQUENCY_SWITCH_SIG" ;
1760    b = True ;
1761    t = 1.0 ;
1762    l = 0.0 ;
1763    break ;
1764  case SrcType::FOFFCAL:
1765    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,FREQUENCY_SWITCH_REF" ;
1766    b = False ;
1767    t = 1.0 ;
1768    l = 0.0 ;
1769    break ;
1770  case SrcType::FSLO:
1771    stype = "OBSERVE_TARGET_ON_SOURCE,FREQUENCY_SWITCH_LOWER" ;
1772    b = True ;
1773    t = 0.0 ;
1774    l = 0.0 ;
1775    break ;
1776  case SrcType::FLOOFF:
1777    stype = "OBSERVE_TARGET_OFF_SOURCE,FREQUENCY_SWITCH_LOWER" ;
1778    b = False ;
1779    t = 0.0 ;
1780    l = 0.0 ;
1781    break ;
1782  case SrcType::FLOSKY:
1783    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,FREQUENCY_SWITCH_LOWER" ;
1784    b = False ;
1785    t = 0.0 ;
1786    l = 1.0 ;
1787    break ;
1788  case SrcType::FLOHOT:
1789    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,FREQUENCY_SWITCH_LOWER" ;
1790    b = False ;
1791    t = 0.0 ;
1792    l = 1.0 ;
1793    break ;
1794  case SrcType::FLOWARM:
1795    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,FREQUENCY_SWITCH_LOWER" ;
1796    b = False ;
1797    t = 0.0 ;
1798    l = 1.0 ;
1799    break ;
1800  case SrcType::FLOCOLD:
1801    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,FREQUENCY_SWITCH_LOWER" ;
1802    b = False ;
1803    t = 0.0 ;
1804    l = 1.0 ;
1805    break ;
1806  case SrcType::FSHI:
1807    stype = "OBSERVE_TARGET_ON_SOURCE,FREQUENCY_SWITCH_HIGHER" ;
1808    b = True ;
1809    t = 0.0 ;
1810    l = 0.0 ;
1811    break ;
1812  case SrcType::FHIOFF:
1813    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,FREQUENCY_SWITCH_HIGHER" ;
1814    b = False ;
1815    t = 0.0 ;
1816    l = 0.0 ;
1817    break ;
1818  case SrcType::FHISKY:
1819    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,FREQUENCY_SWITCH_HIGHER" ;
1820    b = False ;
1821    t = 0.0 ;
1822    l = 1.0 ;
1823    break ;
1824  case SrcType::FHIHOT:
1825    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,FREQUENCY_SWITCH_HIGHER" ;
1826    b = False ;
1827    t = 0.0 ;
1828    l = 1.0 ;
1829    break ;
1830  case SrcType::FHIWARM:
1831    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,FREQUENCY_SWITCH_HIGHER" ;
1832    b = False ;
1833    t = 0.0 ;
1834    l = 1.0 ;
1835    break ;
1836  case SrcType::FHICOLD:
1837    stype = "CALIBRATE_TEMPERATURE_OFF_SOURCE,FREQUENCY_SWITCH_HIGHER" ;
1838    b = False ;
1839    t = 0.0 ;
1840    l = 1.0 ;
1841    break ;
1842  case SrcType::SIG:
1843    stype = "OBSERVE_TARGET_ON_SOURCE,UNSPECIFIED" ;
1844    b = True ;
1845    t = 0.0 ;
1846    l = 0.0 ;
1847    break ;
1848  case SrcType::REF:
1849    stype = "OBSERVE_TARGET_ON_SOURCE,UNSPECIFIED" ;
1850    b = False ;
1851    t = 0.0 ;
1852    l = 0.0 ;
1853    break ;
1854  default:
1855    stype = "UNSPECIFIED" ;
1856    b = True ;
1857    t = 0.0 ;
1858    l = 0.0 ;
1859    break ;
1860  }
1861
1862//   double endSec = gettimeofday_sec() ;
1863//   os_ << "end MSWriter::queryType() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1864}
1865
1866Double MSWriter::getDishDiameter( String antname )
1867{
1868  Double diameter = 0.0 ;
1869 
1870  antname.upcase() ;
1871
1872  if ( antname.matches( Regex( "DV[0-9]+$" ) )
1873       || antname.matches( Regex( "DA[0-9]+$" ) )
1874       || antname.matches( Regex( "PM[0-9]+$" ) ) )
1875    diameter = 12.0 ;
1876  else if ( antname.matches( Regex( "CM[0-9]+$" ) ) )
1877    diameter = 7.0 ;
1878  else if ( antname.contains( "GBT" ) )
1879    diameter = 104.9 ;
1880  else if ( antname.contains( "MOPRA" ) )
1881    diameter = 22.0 ;
1882  else if ( antname.contains( "PKS" ) || antname.contains( "PARKS" ) )
1883    diameter = 64.0 ;
1884  else if ( antname.contains( "TIDBINBILLA" ) )
1885    diameter = 70.0 ;
1886  else if ( antname.contains( "CEDUNA" ) )
1887    diameter = 30.0 ;
1888  else if ( antname.contains( "HOBART" ) )
1889    diameter = 26.0 ;
1890  else if ( antname.contains( "APEX" ) )
1891    diameter = 12.0 ;
1892  else if ( antname.contains( "ASTE" ) )
1893    diameter = 10.0 ;
1894  else if ( antname.contains( "NRO" ) )
1895    diameter = 45.0 ;
1896  else
1897    diameter = 1.0 ;
1898
1899  return diameter ;
1900}
1901
1902void MSWriter::infillSpectralWindow()
1903{
1904  MSSpectralWindow msSpw = mstable_->spectralWindow() ;
1905  MSSpWindowColumns msSpwCols( msSpw ) ;
1906  uInt nrow = msSpw.nrow() ;
1907
1908  ScalarColumn<Int> measFreqRefCol = msSpwCols.measFreqRef() ;
1909  ArrayColumn<Double> chanFreqCol = msSpwCols.chanFreq() ;
1910  ArrayColumn<Double> chanWidthCol = msSpwCols.chanWidth() ;
1911  ArrayColumn<Double> effectiveBWCol = msSpwCols.effectiveBW() ;
1912  ArrayColumn<Double> resolutionCol = msSpwCols.resolution() ;
1913  Vector<Double> dummy( 1, 0.0 ) ;
1914  for ( uInt irow = 0 ; irow < nrow ; irow++ ) {
1915    if ( !(chanFreqCol.isDefined( irow )) ) {
1916      measFreqRefCol.put( irow, 1 ) ;
1917      chanFreqCol.put( irow, dummy ) ;
1918      chanWidthCol.put( irow, dummy ) ;
1919      effectiveBWCol.put( irow, dummy ) ;
1920      resolutionCol.put( irow, dummy ) ;
1921    }
1922  }
1923
1924}
1925
1926}
Note: See TracBrowser for help on using the repository browser.