source: trunk/src/MSWriter.cpp@ 3073

Last change on this file since 3073 was 3064, checked in by Takeshi Nakazato, 10 years ago

Fix for failure of sdsave unit test and FLS3a HI regression.

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