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

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

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: test_sdsave, regressions/fls3a_hi_regression

Put in Release Notes: No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Merge bug fix on trunk (r2309).


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