source: trunk/src/MSFiller.cpp@ 2002

Last change on this file since 2002 was 2002, checked in by Takeshi Nakazato, 14 years ago

New Development: No

JIRA Issue: Yes CAS-2718

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

  • Changed column-based data access to row-based data-access when writing the data.
  • Tuning on getSysCalTime() and other related parts


File size: 54.1 KB
Line 
1//
2// C++ Interface: MSFiller
3//
4// Description:
5//
6// This class is specific filler for MS format
7//
8// Takeshi Nakazato <takeshi.nakazato@nao.ac.jp>, (C) 2010
9//
10// Copyright: See COPYING file that comes with this distribution
11//
12//
13
14#include <iostream>
15#include <map>
16
17#include <tables/Tables/ExprNode.h>
18#include <tables/Tables/TableIter.h>
19#include <tables/Tables/TableColumn.h>
20#include <tables/Tables/ScalarColumn.h>
21#include <tables/Tables/ArrayColumn.h>
22#include <tables/Tables/RefRows.h>
23#include <tables/Tables/TableParse.h>
24#include <tables/Tables/RefRows.h>
25#include <tables/Tables/TableRow.h>
26
27#include <casa/Containers/RecordField.h>
28#include <casa/Logging/LogIO.h>
29#include <casa/Arrays/Slicer.h>
30#include <casa/Quanta/MVTime.h>
31#include <casa/OS/Path.h>
32
33#include <measures/Measures/Stokes.h>
34#include <measures/Measures/MEpoch.h>
35#include <measures/Measures/MCEpoch.h>
36#include <measures/Measures/MFrequency.h>
37#include <measures/Measures/MCFrequency.h>
38#include <measures/Measures/MPosition.h>
39#include <measures/Measures/MCPosition.h>
40#include <measures/Measures/MDirection.h>
41#include <measures/Measures/MCDirection.h>
42#include <measures/Measures/MeasConvert.h>
43#include <measures/TableMeasures/ScalarMeasColumn.h>
44#include <measures/TableMeasures/ArrayMeasColumn.h>
45#include <measures/TableMeasures/ScalarQuantColumn.h>
46#include <measures/TableMeasures/ArrayQuantColumn.h>
47
48#include <atnf/PKSIO/SrcType.h>
49
50#include "MSFiller.h"
51#include "STHeader.h"
52
53#include <ctime>
54#include <sys/time.h>
55
56double gettimeofday_sec()
57{
58 struct timeval tv ;
59 gettimeofday( &tv, NULL ) ;
60 return tv.tv_sec + (double)tv.tv_usec*1.0e-6 ;
61}
62
63using namespace casa ;
64using namespace std ;
65
66namespace asap {
67MSFiller::MSFiller( casa::CountedPtr<Scantable> stable )
68 : table_( stable ),
69 tablename_( "" ),
70 antenna_( -1 ),
71 getPt_( False ),
72 isFloatData_( False ),
73 isData_( False ),
74 isDoppler_( False ),
75 isFlagCmd_( False ),
76 isFreqOffset_( False ),
77 isHistory_( False ),
78 isProcessor_( False ),
79 isSysCal_( False ),
80 isWeather_( False ),
81 colTsys_( "TSYS_SPECTRUM" ),
82 colTcal_( "TCAL_SPECTRUM" )
83{
84 os_ = LogIO() ;
85 os_.origin( LogOrigin( "MSFiller", "MSFiller()", WHERE ) ) ;
86}
87
88MSFiller::~MSFiller()
89{
90 os_.origin( LogOrigin( "MSFiller", "~MSFiller()", WHERE ) ) ;
91}
92
93bool MSFiller::open( const std::string &filename, const casa::Record &rec )
94{
95 os_.origin( LogOrigin( "MSFiller", "open()", WHERE ) ) ;
96 double startSec = gettimeofday_sec() ;
97 os_ << "start MSFiller::open() startsec=" << startSec << LogIO::POST ;
98 //os_ << " filename = " << filename << endl ;
99
100 // parsing MS options
101 if ( rec.isDefined( "ms" ) ) {
102 Record msrec = rec.asRecord( "ms" ) ;
103 if ( msrec.isDefined( "getpt" ) ) {
104 getPt_ = msrec.asBool( "getpt" ) ;
105 }
106 if ( msrec.isDefined( "antenna" ) ) {
107 if ( msrec.type( msrec.fieldNumber( "antenna" ) ) == TpInt ) {
108 antenna_ = msrec.asInt( "antenna" ) ;
109 }
110 else {
111 antenna_ = atoi( msrec.asString( "antenna" ).c_str() ) ;
112 }
113 }
114 else {
115 antenna_ = 0 ;
116 }
117 }
118
119 os_ << "Parsing MS options" << endl ;
120 os_ << " getPt = " << getPt_ << endl ;
121 os_ << " antenna = " << antenna_ << LogIO::POST ;
122
123 MeasurementSet *tmpMS = new MeasurementSet( filename, Table::Old ) ;
124 //mstable_ = (*tmpMS)( tmpMS->col("ANTENNA1") == antenna_
125 // && tmpMS->col("ANTENNA1") == tmpMS->col("ANTENNA2") ) ;
126 tablename_ = tmpMS->tableName() ;
127 mstable_ = MeasurementSet( (*tmpMS)( tmpMS->col("ANTENNA1") == antenna_
128 && tmpMS->col("ANTENNA1") == tmpMS->col("ANTENNA2") ) ) ;
129// stringstream ss ;
130// ss << "SELECT FROM $1 WHERE ANTENNA1 == ANTENNA2 && ANTENNA1 == " << antenna_ ;
131// String taql( ss.str() ) ;
132// mstable_ = MeasurementSet( tableCommand( taql, *tmpMS ) ) ;
133 delete tmpMS ;
134
135 // check which data column exists
136 isFloatData_ = mstable_.tableDesc().isColumn( "FLOAT_DATA" ) ;
137 isData_ = mstable_.tableDesc().isColumn( "DATA" ) ;
138
139 double endSec = gettimeofday_sec() ;
140 os_ << "end MSFiller::open() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
141 return true ;
142}
143
144void MSFiller::fill()
145{
146 os_.origin( LogOrigin( "MSFiller", "fill()", WHERE ) ) ;
147 double startSec = gettimeofday_sec() ;
148 os_ << "start MSFiller::fill() startSec=" << startSec << LogIO::POST ;
149
150 double time0 = gettimeofday_sec() ;
151 os_ << "start init fill: " << time0 << LogIO::POST ;
152
153 // Initialize header
154 STHeader sdh ;
155 sdh.nchan = 0 ;
156 sdh.npol = 0 ;
157 sdh.nif = 0 ;
158 sdh.nbeam = 0 ;
159 sdh.observer = "" ;
160 sdh.project = "" ;
161 sdh.obstype = "" ;
162 sdh.antennaname = "" ;
163 sdh.antennaposition.resize( 0 ) ;
164 sdh.equinox = 0.0 ;
165 sdh.freqref = "" ;
166 sdh.reffreq = -1.0 ;
167 sdh.bandwidth = 0.0 ;
168 sdh.utc = 0.0 ;
169 sdh.fluxunit = "" ;
170 sdh.epoch = "" ;
171 sdh.poltype = "" ;
172
173 // check if optional table exists
174 //const TableRecord msrec = tablesel_.keywordSet() ;
175 const TableRecord msrec = mstable_.keywordSet() ;
176 isDoppler_ = msrec.isDefined( "DOPPLER" ) ;
177 isFlagCmd_ = msrec.isDefined( "FLAG_CMD" ) ;
178 isFreqOffset_ = msrec.isDefined( "FREQ_OFFSET" ) ;
179 isHistory_ = msrec.isDefined( "HISTORY" ) ;
180 isProcessor_ = msrec.isDefined( "PROCESSOR" ) ;
181 isSysCal_ = msrec.isDefined( "SYSCAL" ) ;
182 isWeather_ = msrec.isDefined( "WEATHER" ) ;
183
184 // Access to MS subtables
185 MSField fieldtab = mstable_.field() ;
186 MSPolarization poltab = mstable_.polarization() ;
187 MSDataDescription ddtab = mstable_.dataDescription() ;
188 MSObservation obstab = mstable_.observation() ;
189 MSSource srctab = mstable_.source() ;
190 MSSpectralWindow spwtab = mstable_.spectralWindow() ;
191 MSSysCal caltab = mstable_.sysCal() ;
192 if ( caltab.nrow() == 0 )
193 isSysCal_ = False ;
194 else {
195 if ( !caltab.tableDesc().isColumn( colTcal_ ) )
196 colTcal_ = "TCAL" ;
197 if ( !caltab.tableDesc().isColumn( colTsys_ ) )
198 colTsys_ = "TSYS" ;
199 }
200 //colTcal_ = "TCAL" ;
201 //colTsys_ = "TSYS" ;
202 MSPointing pointtab = mstable_.pointing() ;
203 if ( mstable_.weather().nrow() == 0 )
204 isWeather_ = False ;
205 MSState stattab = mstable_.state() ;
206 MSAntenna anttab = mstable_.antenna() ;
207
208 // TEST
209 // memory allocation by boost::object_pool
210 boost::object_pool<ROTableColumn> *tpoolr = new boost::object_pool<ROTableColumn> ;
211 //
212
213 // SUBTABLES: FREQUENCIES
214 table_->frequencies().setFrame( "LSRK" ) ;
215 table_->frequencies().setFrame( "LSRK", True ) ;
216
217 // SUBTABLES: WEATHER
218 if ( isWeather_ )
219 fillWeather() ;
220
221 // SUBTABLES: FOCUS
222 fillFocus() ;
223
224 // SUBTABLES: TCAL
225 if ( isSysCal_ )
226 fillTcal( tpoolr ) ;
227
228 // SUBTABLES: FIT
229 //fillFit() ;
230
231 // SUBTABLES: HISTORY
232 //fillHistory() ;
233
234 // shared pointers
235 ROTableColumn *tcolr ;
236
237 // MAIN
238 // Iterate over several ids
239 map<Int, uInt> ifmap ; // (IFNO, FREQ_ID) pair
240 ROArrayQuantColumn<Double> *sharedQDArrCol = new ROArrayQuantColumn<Double>( anttab, "POSITION" ) ;
241 Vector< Quantum<Double> > antpos = (*sharedQDArrCol)( antenna_ ) ;
242 delete sharedQDArrCol ;
243 MPosition mp( MVPosition( antpos ), MPosition::ITRF ) ;
244 if ( getPt_ ) {
245 //pointtab = pointtab( pointtab.col("ANTENNA_ID")==antenna_ ).sort("TIME") ;
246 pointtab = MSPointing( pointtab( pointtab.col("ANTENNA_ID")==antenna_ ).sort("TIME") ) ;
247 }
248 tcolr = tpoolr->construct( anttab, "STATION" ) ;
249 String stationName = tcolr->asString( antenna_ ) ;
250 tpoolr->destroy( tcolr ) ;
251 tcolr = tpoolr->construct( anttab, "NAME" ) ;
252 String antennaName = tcolr->asString( antenna_ ) ;
253 tpoolr->destroy( tcolr ) ;
254 sdh.antennaposition.resize( 3 ) ;
255 for ( int i = 0 ; i < 3 ; i++ )
256 sdh.antennaposition[i] = antpos[i].getValue( "m" ) ;
257 String telescopeName = "" ;
258
259 double time1 = gettimeofday_sec() ;
260 os_ << "end fill init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
261
262 // row based
263 Table &stab = table_->table() ;
264 TableRow row( stab ) ;
265 TableRecord &trec = row.record() ;
266 RecordFieldPtr< Array<Float> > spRF( trec, "SPECTRA" ) ;
267 RecordFieldPtr< Array<uChar> > ucarrRF( trec, "FLAGTRA" ) ;
268 RecordFieldPtr<Double> timeRF( trec, "TIME" ) ;
269 RecordFieldPtr< Array<Float> > tsysRF( trec, "TSYS" ) ;
270 RecordFieldPtr<Double> intervalRF( trec, "INTERVAL" ) ;
271 RecordFieldPtr< Array<Double> > dirRF( trec, "DIRECTION" ) ;
272 RecordFieldPtr<Float> azRF( trec, "AZIMUTH" ) ;
273 RecordFieldPtr<Float> elRF( trec, "ELEVATION" ) ;
274 RecordFieldPtr< Array<Double> > scrRF( trec, "SCANRATE" ) ;
275 RecordFieldPtr<uInt> cycleRF( trec, "CYCLENO" ) ;
276 RecordFieldPtr<uInt> flrRF( trec, "FLAGROW" ) ;
277 RecordFieldPtr<uInt> tcalidRF( trec, "TCAL_ID" ) ;
278 RecordFieldPtr<uInt> widRF( trec, "WEATHER_ID" ) ;
279 RecordFieldPtr<uInt> polnoRF( trec, "POLNO" ) ;
280
281
282 // REFBEAMNO
283 RecordFieldPtr<Int> intRF( trec, "REFBEAMNO" ) ;
284 *intRF = 0 ;
285
286 // FIT_ID
287 intRF.attachToRecord( trec, "FIT_ID" ) ;
288 *intRF = -1 ;
289
290 // OPACITY
291 RecordFieldPtr<Float> floatRF( trec, "OPACITY" ) ;
292 *floatRF = 0.0 ;
293
294 //
295 // ITERATION: OBSERVATION_ID
296 //
297 TableIterator iter0( mstable_, "OBSERVATION_ID" ) ;
298 while( !iter0.pastEnd() ) {
299 time0 = gettimeofday_sec() ;
300 os_ << "start 0th iteration: " << time0 << LogIO::POST ;
301 Table t0 = iter0.table() ;
302 tcolr = tpoolr->construct( t0, "OBSERVATION_ID" ) ;
303 Int obsId = tcolr->asInt( 0 ) ;
304 tpoolr->destroy( tcolr ) ;
305 if ( sdh.observer == "" ) {
306 tcolr = tpoolr->construct( obstab, "OBSERVER" ) ;
307 sdh.observer = tcolr->asString( obsId ) ;
308 tpoolr->destroy( tcolr ) ;
309 }
310 if ( sdh.project == "" ) {
311 tcolr = tpoolr->construct( obstab, "PROJECT" ) ;
312 sdh.observer = tcolr->asString( obsId ) ;
313 tpoolr->destroy( tcolr ) ;
314 }
315 ROArrayMeasColumn<MEpoch> *tmpMeasCol = new ROArrayMeasColumn<MEpoch>( obstab, "TIME_RANGE" ) ;
316 MEpoch me = (*tmpMeasCol)( obsId )( IPosition(1,0) ) ;
317 delete tmpMeasCol ;
318 if ( sdh.utc == 0.0 ) {
319 sdh.utc = me.get( "s" ).getValue() ;
320 }
321 if ( telescopeName == "" ) {
322 tcolr = tpoolr->construct( obstab, "TELESCOPE_NAME" ) ;
323 sdh.observer = tcolr->asString( obsId ) ;
324 tpoolr->destroy( tcolr ) ;
325 }
326 Int nbeam = 0 ;
327 time1 = gettimeofday_sec() ;
328 os_ << "end 0th iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
329 //
330 // ITERATION: FEED1
331 //
332 TableIterator iter1( t0, "FEED1" ) ;
333 while( !iter1.pastEnd() ) {
334 time0 = gettimeofday_sec() ;
335 os_ << "start 1st iteration: " << time0 << LogIO::POST ;
336 Table t1 = iter1.table() ;
337 // assume FEED1 == FEED2
338 tcolr = tpoolr->construct( t1, "FEED1" ) ;
339 Int feedId = tcolr->asInt( 0 ) ;
340 tpoolr->destroy( tcolr ) ;
341 nbeam++ ;
342
343 // BEAMNO
344 RecordFieldPtr<uInt> uintRF( trec, "BEAMNO" ) ;
345 *uintRF = feedId ;
346
347 // FOCUS_ID
348 uintRF.attachToRecord( trec, "FOCUS_ID" ) ;
349 *uintRF = 0 ;
350
351 time1 = gettimeofday_sec() ;
352 os_ << "end 1st iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
353 //
354 // ITERATION: FIELD_ID
355 //
356 TableIterator iter2( t1, "FIELD_ID" ) ;
357 while( !iter2.pastEnd() ) {
358 time0 = gettimeofday_sec() ;
359 os_ << "start 2nd iteration: " << time0 << LogIO::POST ;
360 Table t2 = iter2.table() ;
361 tcolr = tpoolr->construct( t2, "FIELD_ID" ) ;
362 Int fieldId = tcolr->asInt( 0 ) ;
363 tpoolr->destroy( tcolr ) ;
364 tcolr = tpoolr->construct( fieldtab, "SOURCE_ID" ) ;
365 Int srcId = tcolr->asInt( fieldId ) ;
366 tpoolr->destroy( tcolr ) ;
367 tcolr = tpoolr->construct( fieldtab, "NAME" ) ;
368 String fieldName = tcolr->asString( fieldId ) + "__" + String::toString(fieldId) ;
369 tpoolr->destroy( tcolr ) ;
370
371 // FIELDNAME
372 RecordFieldPtr<String> strRF( trec, "FIELDNAME" ) ;
373 *strRF = fieldName ;
374
375
376 time1 = gettimeofday_sec() ;
377 os_ << "end 2nd iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
378 //
379 // ITERATION: DATA_DESC_ID
380 //
381 TableIterator iter3( t2, "DATA_DESC_ID" ) ;
382 while( !iter3.pastEnd() ) {
383 time0 = gettimeofday_sec() ;
384 os_ << "start 3rd iteration: " << time0 << LogIO::POST ;
385 Table t3 = iter3.table() ;
386 tcolr = tpoolr->construct( t3, "DATA_DESC_ID" ) ;
387 Int ddId = tcolr->asInt( 0 ) ;
388 tpoolr->destroy( tcolr ) ;
389 tcolr = tpoolr->construct( ddtab, "POLARIZATION_ID" ) ;
390 Int polId = tcolr->asInt( ddId ) ;
391 tpoolr->destroy( tcolr ) ;
392 tcolr = tpoolr->construct( ddtab, "SPECTRAL_WINDOW_ID" ) ;
393 Int spwId = tcolr->asInt( ddId ) ;
394 tpoolr->destroy( tcolr ) ;
395
396 // IFNO
397 uintRF.attachToRecord( trec, "IFNO" ) ;
398 *uintRF = (uInt)spwId ;
399
400 // polarization information
401 tcolr = tpoolr->construct( poltab, "NUM_CORR" ) ;
402 Int npol = tcolr->asInt( polId ) ;
403 tpoolr->destroy( tcolr ) ;
404 ROArrayColumn<Int> *roArrICol = new ROArrayColumn<Int>( poltab, "CORR_TYPE" ) ;
405 Vector<Int> corrtype = (*roArrICol)( polId ) ;
406 delete roArrICol ;
407 //os_ << "npol = " << npol << LogIO::POST ;
408 //os_ << "corrtype = " << corrtype << LogIO::POST ;
409 sdh.npol = max( sdh.npol, npol ) ;
410 if ( sdh.poltype == "" ) sdh.poltype = getPolType( corrtype[0] ) ;
411 // source information
412 MSSource srctabSel( srctab( srctab.col("SOURCE_ID") == srcId && srctab.col("SPECTRAL_WINDOW_ID") == spwId ) ) ;
413 os_ << "srcId = " << srcId << " spwId = " << spwId << " nrow = " << srctabSel.nrow() << LogIO::POST ;
414 tcolr = tpoolr->construct( srctabSel, "NAME" ) ;
415 String srcName = tcolr->asString( 0 ) ;
416 tpoolr->destroy( tcolr ) ;
417
418 // SRCNAME
419 strRF.attachToRecord( trec, "SRCNAME" ) ;
420 *strRF = srcName ;
421
422 //os_ << "srcName = " << srcName << LogIO::POST ;
423 ROArrayColumn<Double> *roArrDCol = new ROArrayColumn<Double>( srctabSel, "PROPER_MOTION" ) ;
424 Array<Double> srcPM = (*roArrDCol)( 0 ) ;
425 delete roArrDCol ;
426
427 // SRCPROPERMOTION
428 RecordFieldPtr< Array<Double> > darrRF( trec, "SRCPROPERMOTION" ) ;
429 *darrRF = srcPM ;
430
431 //os_ << "srcPM = " << srcPM << LogIO::POST ;
432 roArrDCol = new ROArrayColumn<Double>( srctabSel, "DIRECTION" ) ;
433 Array<Double> srcDir = (*roArrDCol)( 0 ) ;
434 delete roArrDCol ;
435
436 // SRCDIRECTION
437 darrRF.attachToRecord( trec, "SRCDIRECTION" ) ;
438 *darrRF = srcDir ;
439
440 //os_ << "srcDir = " << srcDir << LogIO::POST ;
441 Array<Double> sysVels ;
442 Double sysVel = 0.0 ;
443 if ( srctabSel.tableDesc().isColumn( "SYSVEL" ) ) {
444 roArrDCol = new ROArrayColumn<Double>( srctabSel, "SYSVEL" ) ;
445 sysVels = (*roArrDCol)( 0 ) ;
446 delete roArrDCol ;
447 }
448 if ( !sysVels.empty() ) {
449 //os_ << "sysVels.shape() = " << sysVels.shape() << LogIO::POST ;
450 // NB: assume all SYSVEL values are the same
451 sysVel = sysVels( IPosition(1,0) ) ;
452 }
453
454 // SRCVELOCITY
455 RecordFieldPtr<Double> doubleRF( trec, "SRCVELOCITY" ) ;
456 *doubleRF = sysVel ;
457
458 //delete tmpArrCol ;
459 //os_ << "sysVel = " << sysVel << LogIO::POST ;
460 ROScalarMeasColumn<MDirection> *tmpMeasCol = new ROScalarMeasColumn<MDirection>( srctabSel, "DIRECTION" ) ;
461 MDirection md = (*tmpMeasCol)( 0 ) ;
462 delete tmpMeasCol ;
463 // for MOLECULES subtable
464 tcolr = tpoolr->construct( srctabSel, "NUM_LINES" ) ;
465 Int numLines = tcolr->asInt( 0 ) ;
466 tpoolr->destroy( tcolr ) ;
467 //os_ << "numLines = " << numLines << LogIO::POST ;
468 Vector<Double> restFreqs( numLines, 0.0 ) ;
469 Vector<String> transitionName( numLines, "" ) ;
470 if ( numLines != 0 ) {
471 if ( srctabSel.tableDesc().isColumn( "REST_FREQUENCY" ) ) {
472 sharedQDArrCol = new ROArrayQuantColumn<Double>( srctabSel, "REST_FREQUENCY" ) ;
473 Array< Quantum<Double> > qRestFreqs = (*sharedQDArrCol)( 0 ) ;
474 delete sharedQDArrCol ;
475 for ( int i = 0 ; i < numLines ; i++ ) {
476 restFreqs[i] = qRestFreqs( IPosition( 1, i ) ).getValue( "Hz" ) ;
477 }
478 }
479 //os_ << "restFreqs = " << restFreqs << LogIO::POST ;
480 if ( srctabSel.tableDesc().isColumn( "TRANSITION" ) ) {
481 tcolr = tpoolr->construct( srctabSel, "TRANSITION" ) ;
482 transitionName = tcolr->asString( 0 ) ;
483 tpoolr->destroy( tcolr ) ;
484 //os_ << "transitionNameCol.nrow() = " << transitionNameCol.nrow() << LogIO::POST ;
485 }
486 }
487 uInt molId = table_->molecules().addEntry( restFreqs, transitionName, transitionName ) ;
488
489 // MOLECULE_ID
490 uintRF.attachToRecord( trec, "MOLECULE_ID" ) ;
491 *uintRF = molId ;
492
493 // spectral setup
494 MeasFrame mf( me, mp, md ) ;
495 tcolr = tpoolr->construct( spwtab, "MEAS_FREQ_REF" ) ;
496 MFrequency::Types freqRef = MFrequency::castType((uInt)(tcolr->asInt(spwId))) ;
497 tpoolr->destroy( tcolr ) ;
498 tcolr = tpoolr->construct( spwtab, "NUM_CHAN" ) ;
499 Int nchan = tcolr->asInt( spwId ) ;
500 tpoolr->destroy( tcolr ) ;
501 Bool even = False ;
502 if ( (nchan/2)*2 == nchan ) even = True ;
503 sdh.nchan = max( sdh.nchan, nchan ) ;
504 ROScalarQuantColumn<Double> *tmpQuantCol = new ROScalarQuantColumn<Double>( spwtab, "TOTAL_BANDWIDTH" ) ;
505 Double totbw = (*tmpQuantCol)( spwId ).getValue( "Hz" ) ;
506 delete tmpQuantCol ;
507 sdh.bandwidth = max( sdh.bandwidth, totbw ) ;
508 if ( sdh.freqref == "" )
509 //sdh.freqref = MFrequency::showType( freqRef ) ;
510 sdh.freqref = "LSRK" ;
511 if ( sdh.reffreq == -1.0 ) {
512 tmpQuantCol = new ROScalarQuantColumn<Double>( spwtab, "REF_FREQUENCY" ) ;
513 Quantum<Double> qreffreq = (*tmpQuantCol)( spwId ) ;
514 delete tmpQuantCol ;
515 if ( freqRef == MFrequency::LSRK ) {
516 sdh.reffreq = qreffreq.getValue("Hz") ;
517 }
518 else {
519 MFrequency::Convert tolsr( freqRef, MFrequency::Ref( MFrequency::LSRK, mf ) ) ;
520 sdh.reffreq = tolsr( qreffreq ).get("Hz").getValue() ;
521 }
522 }
523 Int refchan = nchan / 2 ;
524 IPosition refip( 1, refchan ) ;
525 Double refpix = 0.5*(nchan-1) ;
526 Double refval = 0.0 ;
527 sharedQDArrCol = new ROArrayQuantColumn<Double>( spwtab, "CHAN_WIDTH" ) ;
528 Double increment = (*sharedQDArrCol)( spwId )( refip ).getValue( "Hz" ) ;
529 delete sharedQDArrCol ;
530 //os_ << "nchan = " << nchan << " refchan = " << refchan << "(even=" << even << ") refpix = " << refpix << LogIO::POST ;
531 sharedQDArrCol = new ROArrayQuantColumn<Double>( spwtab, "CHAN_FREQ" ) ;
532 Vector< Quantum<Double> > chanFreqs = (*sharedQDArrCol)( spwId ) ;
533 delete sharedQDArrCol ;
534 if ( freqRef == MFrequency::LSRK ) {
535 if ( even ) {
536 IPosition refip0( 1, refchan-1 ) ;
537 Double refval0 = chanFreqs(refip0).getValue("Hz") ;
538 Double refval1 = chanFreqs(refip).getValue("Hz") ;
539 refval = 0.5 * ( refval0 + refval1 ) ;
540 }
541 else {
542 refval = chanFreqs(refip).getValue("Hz") ;
543 }
544 }
545 else {
546 MFrequency::Convert tolsr( freqRef, MFrequency::Ref( MFrequency::LSRK, mf ) ) ;
547 if ( even ) {
548 IPosition refip0( 1, refchan-1 ) ;
549 Double refval0 = chanFreqs(refip0).getValue("Hz") ;
550 Double refval1 = chanFreqs(refip).getValue("Hz") ;
551 refval = 0.5 * ( refval0 + refval1 ) ;
552 refval = tolsr( refval ).get("Hz").getValue() ;
553 }
554 else {
555 refval = tolsr( chanFreqs(refip) ).get("Hz").getValue() ;
556 }
557 }
558 uInt freqId = table_->frequencies().addEntry( refpix, refval, increment ) ;
559 if ( ifmap.find( spwId ) == ifmap.end() ) {
560 ifmap.insert( pair<Int, uInt>(spwId,freqId) ) ;
561 //os_ << "added to ifmap: (" << spwId << "," << freqId << ")" << LogIO::POST ;
562 }
563
564 // FREQ_ID
565 uintRF.attachToRecord( trec, "FREQ_ID" ) ;
566 *uintRF = freqId ;
567
568 // for TSYS and TCAL
569 MSSysCal caltabsel( caltab( caltab.col("ANTENNA_ID") == antenna_ && caltab.col("FEED_ID") == feedId && caltab.col("SPECTRAL_WINDOW_ID") == spwId ).sort("TIME") ) ;
570 ROScalarMeasColumn<MEpoch> scTimeCol( caltabsel, "TIME" ) ;
571 Block<MEpoch> scTime( caltabsel.nrow() ) ;
572 for ( uInt irow = 0 ; irow < caltabsel.nrow() ; irow++ )
573 scTime[irow] = scTimeCol( irow ) ;
574 ROScalarColumn<Double> *scIntervalCol = new ROScalarColumn<Double>( caltabsel, "INTERVAL" ) ;
575 Vector<Double> scInterval = scIntervalCol->getColumn() ;
576 delete scIntervalCol ;
577 ROArrayColumn<Float> scTsysCol( caltabsel, "TSYS" ) ;
578 time1 = gettimeofday_sec() ;
579 os_ << "end 3rd iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
580 //
581 // ITERATION: SCAN_NUMBER
582 //
583 TableIterator iter4( t3, "SCAN_NUMBER" ) ;
584 while( !iter4.pastEnd() ) {
585 time0 = gettimeofday_sec() ;
586 os_ << "start 4th iteration: " << time0 << LogIO::POST ;
587 Table t4 = iter4.table() ;
588 tcolr = tpoolr->construct( t4, "SCAN_NUMBER" ) ;
589 Int scanNum = tcolr->asInt( 0 ) ;
590 tpoolr->destroy( tcolr ) ;
591
592 // SCANNO
593 uintRF.attachToRecord( trec, "SCANNO" ) ;
594 *uintRF = scanNum - 1 ;
595
596 uInt cycle = 0 ;
597 time1 = gettimeofday_sec() ;
598 os_ << "end 4th iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
599 //
600 // ITERATION: STATE_ID
601 //
602 TableIterator iter5( t4, "STATE_ID" ) ;
603 while( !iter5.pastEnd() ) {
604 time0 = gettimeofday_sec() ;
605 os_ << "start 5th iteration: " << time0 << LogIO::POST ;
606 Table t5 = iter5.table() ;
607 tcolr = tpoolr->construct( t5, "STATE_ID" ) ;
608 Int stateId = tcolr->asInt( 0 ) ;
609 tpoolr->destroy( tcolr ) ;
610 tcolr = tpoolr->construct( stattab, "OBS_MODE" ) ;
611 String obstype = tcolr->asString( stateId ) ;
612 tpoolr->destroy( tcolr ) ;
613 if ( sdh.obstype == "" ) sdh.obstype = obstype ;
614
615 Int nrow = t5.nrow() ;
616 time1 = gettimeofday_sec() ;
617 os_ << "end 5th iteration init: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
618
619 Cube<Float> spArr ;
620 Cube<Bool> flArr ;
621 if ( isFloatData_ ) {
622 ROArrayColumn<Bool> mFlagCol( t5, "FLAG" ) ;
623 ROArrayColumn<Float> mFloatDataCol( t5, "FLOAT_DATA" ) ;
624 spArr = mFloatDataCol.getColumn() ;
625 flArr = mFlagCol.getColumn() ;
626 if ( sdh.fluxunit == "" ) {
627 const TableRecord &dataColKeys = mFloatDataCol.keywordSet() ;
628 if ( dataColKeys.isDefined( "UNIT" ) )
629 sdh.fluxunit = dataColKeys.asString( "UNIT" ) ;
630 }
631 }
632 else if ( isData_ ) {
633 spArr.resize( npol, nchan, nrow ) ;
634 ROArrayColumn<Bool> mFlagCol( t5, "FLAG" ) ;
635 ROArrayColumn<Complex> mDataCol( t5, "DATA" ) ;
636 for ( Int irow = 0 ; irow < nrow ; irow++ ) {
637 Bool crossOK = False ;
638 Matrix<Complex> sp = mDataCol( irow ) ;
639 Matrix<Bool> fl = mFlagCol( irow ) ;
640 for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
641 if ( corrtype[ipol] == Stokes::XY || corrtype[ipol] == Stokes::YX
642 || corrtype[ipol] == Stokes::RL || corrtype[ipol] == Stokes::LR ) {
643 if ( !crossOK ) {
644 spArr( Slicer(Slice(ipol,1),Slice(0,nchan),Slice(irow,1)) ) = real( sp.row( ipol ) ) ;
645 flArr( Slicer(Slice(ipol,1),Slice(0,nchan),Slice(irow,1)) ) = fl.row( ipol ) ;
646 if ( corrtype[ipol] == Stokes::XY || corrtype[ipol] == Stokes::RL ) {
647 spArr( Slicer(Slice(ipol+1,1),Slice(0,nchan),Slice(irow,1)) ) = imag( sp.row( ipol ) ) ;
648 flArr( Slicer(Slice(ipol+1,1),Slice(0,nchan),Slice(irow,1)) ) = fl.row( ipol ) ;
649 }
650 else {
651 spArr( Slicer(Slice(ipol+1,1),Slice(0,nchan),Slice(irow,1)) ) = imag( conj( sp.row( ipol ) ) ) ;
652 flArr( Slicer(Slice(ipol+1,1),Slice(0,nchan),Slice(irow,1)) ) = fl.row( ipol ) ;
653 }
654 }
655 }
656 else {
657 spArr( Slicer(Slice(ipol,1),Slice(0,nchan),Slice(irow,1)) ) = real( sp.row( ipol ) ) ;
658 flArr( Slicer(Slice(ipol,1),Slice(0,nchan),Slice(irow,1)) ) = fl.row( ipol ) ;
659 }
660 }
661 }
662 if ( sdh.fluxunit == "" ) {
663 const TableRecord &dataColKeys = mDataCol.keywordSet() ;
664 if ( dataColKeys.isDefined( "UNIT" ) )
665 sdh.fluxunit = dataColKeys.asString( "UNIT" ) ;
666 }
667 }
668 ROScalarMeasColumn<MEpoch> *mTimeCol = new ROScalarMeasColumn<MEpoch>( t5, "TIME" ) ;
669 Block<MEpoch> mTimeB( nrow ) ;
670 for ( Int irow = 0 ; irow < nrow ; irow++ )
671 mTimeB[irow] = (*mTimeCol)( irow ) ;
672 ROTableColumn *mIntervalCol = tpoolr->construct( t5, "INTERVAL" ) ;
673 ROTableColumn *mFlagRowCol = tpoolr->construct( t5, "FLAG_ROW" ) ;
674 //Vector<Double> sysCalTime( nrow, -1.0 ) ;
675 Block<Double> sysCalTime( nrow, -1.0 ) ;
676 Block<Int> sysCalIdx( nrow, -1 ) ;
677 if ( isSysCal_ ) {
678 //getSysCalTime( caltabsel, mTimeB, sysCalTime, sysCalIdx ) ;
679 getSysCalTime( scTime, scInterval, mTimeB, sysCalTime, sysCalIdx ) ;
680 }
681 delete mTimeCol ;
682 Matrix<Float> defaulttsys( npol, 1, 1.0 ) ;
683 //uInt calidx = 0 ;
684 Int srcType = getSrcType( stateId, tpoolr ) ;
685 Vector<Double> defaultScanrate( 2, 0.0 ) ;
686 uInt diridx = 0 ;
687 MDirection::Types dirType ;
688 uInt wid = 0 ;
689 Int pidx = 0 ;
690 Bool crossOK = False ;
691 Block<uInt> polnos( npol, 99 ) ;
692 for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
693 Block<uInt> p = getPolNo( corrtype[ipol] ) ;
694 if ( p.size() > 1 ) {
695 if ( crossOK ) continue ;
696 else {
697 polnos[pidx] = p[0] ;
698 pidx++ ;
699 polnos[pidx] = p[1] ;
700 pidx++ ;
701 crossOK = True ;
702 }
703 }
704 else {
705 polnos[pidx] = p[0] ;
706 pidx++ ;
707 }
708 }
709
710 // SRCTYPE
711 intRF.attachToRecord( trec, "SRCTYPE" ) ;
712 *intRF = srcType ;
713
714 for ( Int irow = 0 ; irow < nrow ; irow++ ) {
715 // CYCLENO
716 *cycleRF = cycle ;
717
718 // FLAGROW
719 *flrRF = (uInt)mFlagRowCol->asBool( irow ) ;
720
721 // SPECTRA, FLAG
722 //Matrix<Float> sp = mFloatDataCol( irow ) ;
723 //Matrix<Bool> flb = mFlagCol( irow ) ;
724 Matrix<Float> sp = spArr.xyPlane( irow ) ;
725 Matrix<Bool> flb = flArr.xyPlane( irow ) ;
726 Matrix<uChar> fl( flb.shape() ) ;
727 convertArray( fl, flb ) ;
728
729 // TIME
730 *timeRF = mTimeB[irow].get("s").getValue() ;
731
732 // INTERVAL
733 *intervalRF = (Double)(mIntervalCol->asdouble( irow )) ;
734
735 // TSYS
736 Matrix<Float> tsys ;
737 //calidx = getTsys( calidx, tsys, caltabsel, sysCalTime[irow] ) ;
738// calidx = getTsys( calidx, tsys, scTsysCol, scTime, sysCalTime[irow] ) ;
739// if ( tsys.nelements() == 0 )
740// tsys = defaulttsys ;
741 if ( sysCalIdx[irow] != -1 )
742 tsys = scTsysCol( irow ) ;
743 else
744 tsys = defaulttsys ;
745
746 // TCAL_ID
747 Block<uInt> tcalids = getTcalId( feedId, spwId, sysCalTime[irow] ) ;
748 if ( tcalids.size() == 0 ) {
749 tcalids.resize( npol ) ;
750 tcalids = 0 ;
751 }
752
753 // WEATHER_ID
754 if ( isWeather_ )
755 wid = getWeatherId( wid, mTimeB[irow].get("s").getValue() ) ;
756 *widRF = wid ;
757
758
759 // DIRECTION, AZEL, SCANRATE
760 if ( getPt_ ) {
761 Vector<Double> dir ;
762 Vector<Double> scanrate ;
763 String refString ;
764 diridx = getDirection( diridx, dir, scanrate, refString, pointtab, mTimeB[irow].get("s").getValue() ) ;
765 MDirection::getType( dirType, refString ) ;
766 mf.resetEpoch( mTimeB[irow] ) ;
767 mf.resetDirection( MDirection( MVDirection(dir), dirType ) ) ;
768 if ( refString == "J2000" ) {
769 *dirRF = dir ;
770 MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZEL, mf ) ) ;
771 Vector<Double> azel = toazel( dir ).getAngle("rad").getValue() ;
772 *azRF = (Float)azel(0) ;
773 *elRF = (Float)azel(1) ;
774 }
775 else if ( refString(0,4) == "AZEL" ) {
776 *azRF = (Float)dir(0) ;
777 *elRF = (Float)dir(1) ;
778 MDirection::Convert toj2000( dirType, MDirection::Ref( MDirection::J2000, mf ) ) ;
779 Vector<Double> newdir = toj2000( dir ).getAngle("rad").getValue() ;
780 *dirRF = newdir ;
781 }
782 else {
783 MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZEL, mf ) ) ;
784 Vector<Double> azel = toazel( dir ).getAngle("rad").getValue() ;
785 MDirection::Convert toj2000( dirType, MDirection::Ref( MDirection::J2000, mf ) ) ;
786 Vector<Double> newdir = toj2000( dir ).getAngle("rad").getValue() ;
787 *dirRF = newdir ;
788 *azRF = (Float)azel(0) ;
789 *elRF = (Float)azel(1) ;
790 }
791 if ( scanrate.size() != 0 ) {
792 *scrRF = scanrate ;
793 }
794 else {
795 *scrRF = defaultScanrate ;
796 }
797 }
798 else {
799 String ref = md.getRefString() ;
800 Vector<Double> defaultDir = srcDir ;
801 MDirection::getType( dirType, "J2000" ) ;
802 if ( ref != "J2000" ) {
803 ROScalarMeasColumn<MEpoch> tmCol( pointtab, "TIME" ) ;
804 mf.resetEpoch( tmCol( 0 ) ) ;
805 MDirection::Convert toj2000( dirType, MDirection::Ref( MDirection::J2000, mf ) ) ;
806 defaultDir = toj2000( defaultDir ).getAngle("rad").getValue() ;
807 }
808 mf.resetEpoch( mTimeB[irow] ) ;
809 MDirection::Convert toazel( dirType, MDirection::Ref( MDirection::AZEL, mf ) ) ;
810 Vector<Double> azel = toazel( defaultDir ).getAngle("rad").getValue() ;
811 *azRF = (Float)azel(0) ;
812 *elRF = (Float)azel(1) ;
813 *dirRF = defaultDir ;
814 *scrRF = defaultScanrate ;
815 }
816
817 // Polarization dependent things
818 for ( Int ipol = 0 ; ipol < npol ; ipol++ ) {
819 // POLNO
820 *polnoRF = polnos[ipol] ;
821
822 *spRF = sp.row( ipol ) ;
823 *ucarrRF = fl.row( ipol ) ;
824 *tsysRF = tsys.row( ipol ) ;
825 *tcalidRF = tcalids[ipol] ;
826
827 // Commit row
828 stab.addRow() ;
829 row.put( stab.nrow()-1 ) ;
830 }
831 }
832 //delete mTimeCol ;
833 tpoolr->destroy( mIntervalCol ) ;
834 tpoolr->destroy( mFlagRowCol ) ;
835
836 time1 = gettimeofday_sec() ;
837 os_ << "end 5th iteration: " << time1 << " (" << time1-time0 << "sec)" << LogIO::POST ;
838
839 iter5.next() ;
840 }
841
842
843 iter4.next() ;
844 }
845
846
847 iter3.next() ;
848 }
849
850
851 iter2.next() ;
852 }
853
854
855 iter1.next() ;
856 }
857 if ( sdh.nbeam < nbeam ) sdh.nbeam = nbeam ;
858
859 iter0.next() ;
860 }
861
862
863 delete tpoolr ;
864
865
866 // Table Keywords
867 sdh.nif = ifmap.size() ;
868 if ( ( telescopeName == "" ) || ( antennaName == telescopeName ) ) {
869 sdh.antennaname = antennaName ;
870 }
871 else {
872 sdh.antennaname = telescopeName + "//" + antennaName ;
873 }
874 if ( stationName != "" ) {
875 sdh.antennaname += "@" + stationName ;
876 }
877 ROArrayColumn<Double> pdirCol( pointtab, "DIRECTION" ) ;
878 String dirref = pdirCol.keywordSet().asRecord("MEASINFO").asString("Ref") ;
879 if ( dirref == "AZELGEO" || dirref == "AZEL" ) {
880 dirref = "J2000" ;
881 }
882 sscanf( dirref.chars()+1, "%f", &sdh.equinox ) ;
883 sdh.epoch = "UTC" ;
884 if (sdh.freqref == "TOPO") {
885 sdh.freqref = "TOPOCENT";
886 } else if (sdh.freqref == "GEO") {
887 sdh.freqref = "GEOCENTR";
888 } else if (sdh.freqref == "BARY") {
889 sdh.freqref = "BARYCENT";
890 } else if (sdh.freqref == "GALACTO") {
891 sdh.freqref = "GALACTOC";
892 } else if (sdh.freqref == "LGROUP") {
893 sdh.freqref = "LOCALGRP";
894 } else if (sdh.freqref == "CMB") {
895 sdh.freqref = "CMBDIPOL";
896 } else if (sdh.freqref == "REST") {
897 sdh.freqref = "SOURCE";
898 }
899 table_->setHeader( sdh ) ;
900
901 // save path to POINTING table
902 //Path datapath(mstable_.tableName()) ;
903 Path datapath( tablename_ ) ;
904 String pTabName = datapath.absoluteName() + "/POINTING" ;
905 stab.rwKeywordSet().define( "POINTING", pTabName ) ;
906
907 // for GBT
908 if ( antennaName == "GBT" ) {
909 String goTabName = datapath.absoluteName() + "/GBT_GO" ;
910 stab.rwKeywordSet().define( "GBT_GO", goTabName ) ;
911 }
912 double endSec = gettimeofday_sec() ;
913 os_ << "end MSFiller::fill() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
914}
915
916void MSFiller::close()
917{
918 //tablesel_.closeSubTables() ;
919 mstable_.closeSubTables() ;
920 //tablesel_.unlock() ;
921 mstable_.unlock() ;
922}
923
924Int MSFiller::getSrcType( Int stateId, boost::object_pool<ROTableColumn> *tpool )
925{
926 double startSec = gettimeofday_sec() ;
927 os_ << "start MSFiller::getSrcType() startSec=" << startSec << LogIO::POST ;
928
929 MSState statetab = mstable_.state() ;
930 ROTableColumn *sharedCol ;
931 sharedCol = tpool->construct( statetab, "OBS_MODE" ) ;
932 String obsMode = sharedCol->asString( stateId ) ;
933 tpool->destroy( sharedCol ) ;
934 sharedCol = tpool->construct( statetab, "SIG" ) ;
935 Bool sig = sharedCol->asBool( stateId ) ;
936 tpool->destroy( sharedCol ) ;
937 sharedCol = tpool->construct( statetab, "REF" ) ;
938 Bool ref = sharedCol->asBool( stateId ) ;
939 tpool->destroy( sharedCol ) ;
940 sharedCol = tpool->construct( statetab, "CAL" ) ;
941 Double cal = (Double)(sharedCol->asdouble( stateId )) ;
942 tpool->destroy( sharedCol ) ;
943 //os_ << "OBS_MODE = " << obsMode << LogIO::POST ;
944
945 // determine separator
946 String sep = "" ;
947 if ( obsMode.find( ":" ) != String::npos ) {
948 sep = ":" ;
949 }
950 else if ( obsMode.find( "." ) != String::npos ) {
951 sep = "." ;
952 }
953
954 // determine SRCTYPE
955 Int srcType = SrcType::NOTYPE ;
956 if ( sep == ":" ) {
957 // sep == ":"
958 //
959 // GBT case
960 //
961 // obsMode1=Nod
962 // NOD
963 // obsMode1=OffOn
964 // obsMode2=PSWITCHON: PSON
965 // obsMode2=PSWITCHOFF: PSOFF
966 // obsMode1=??
967 // obsMode2=FSWITCH:
968 // SIG=1: FSON
969 // REF=1: FSOFF
970 // Calibration scan if CAL != 0
971 Int epos = obsMode.find_first_of( sep ) ;
972 Int nextpos = obsMode.find_first_of( sep, epos+1 ) ;
973 String obsMode1 = obsMode.substr( 0, epos ) ;
974 String obsMode2 = obsMode.substr( epos+1, nextpos-epos-1 ) ;
975 if ( obsMode1 == "Nod" ) {
976 srcType = SrcType::NOD ;
977 }
978 else if ( obsMode1 == "OffOn" ) {
979 if ( obsMode2 == "PSWITCHON" ) srcType = SrcType::PSON ;
980 if ( obsMode2 == "PSWITCHOFF" ) srcType = SrcType::PSOFF ;
981 }
982 else {
983 if ( obsMode2 == "FSWITCH" ) {
984 if ( sig ) srcType = SrcType::FSON ;
985 if ( ref ) srcType = SrcType::FSOFF ;
986 }
987 }
988 if ( cal > 0.0 ) {
989 if ( srcType == SrcType::NOD )
990 srcType = SrcType::NODCAL ;
991 else if ( srcType == SrcType::PSON )
992 srcType = SrcType::PONCAL ;
993 else if ( srcType == SrcType::PSOFF )
994 srcType = SrcType::POFFCAL ;
995 else if ( srcType == SrcType::FSON )
996 srcType = SrcType::FONCAL ;
997 else if ( srcType == SrcType::FSOFF )
998 srcType = SrcType::FOFFCAL ;
999 else
1000 srcType = SrcType::CAL ;
1001 }
1002 }
1003 else if ( sep == "." ) {
1004 // sep == "."
1005 //
1006 // ALMA & EVLA case (MS via ASDM)
1007 //
1008 // obsMode1=CALIBRATE_*
1009 // obsMode2=ON_SOURCE: PONCAL
1010 // obsMode2=OFF_SOURCE: POFFCAL
1011 // obsMode1=OBSERVE_TARGET
1012 // obsMode2=ON_SOURCE: PON
1013 // obsMode2=OFF_SOURCE: POFF
1014 Int epos = obsMode.find_first_of( sep ) ;
1015 Int nextpos = obsMode.find_first_of( sep, epos+1 ) ;
1016 String obsMode1 = obsMode.substr( 0, epos ) ;
1017 String obsMode2 = obsMode.substr( epos+1, nextpos-epos-1 ) ;
1018 if ( obsMode1.find( "CALIBRATE_" ) == 0 ) {
1019 if ( obsMode2 == "ON_SOURCE" ) srcType = SrcType::PONCAL ;
1020 if ( obsMode2 == "OFF_SOURCE" ) srcType = SrcType::POFFCAL ;
1021 }
1022 else if ( obsMode1 == "OBSERVE_TARGET" ) {
1023 if ( obsMode2 == "ON_SOURCE" ) srcType = SrcType::PSON ;
1024 if ( obsMode2 == "OFF_SOURCE" ) srcType = SrcType::PSOFF ;
1025 }
1026 }
1027 else {
1028 if ( sig ) srcType = SrcType::SIG ;
1029 if ( ref ) srcType = SrcType::REF ;
1030 }
1031
1032 //os_ << "srcType = " << srcType << LogIO::POST ;
1033 double endSec = gettimeofday_sec() ;
1034 os_ << "end MSFiller::getSrcType() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1035 return srcType ;
1036}
1037
1038//Vector<uInt> MSFiller::getPolNo( Int corrType )
1039Block<uInt> MSFiller::getPolNo( Int corrType )
1040{
1041 double startSec = gettimeofday_sec() ;
1042 os_ << "start MSFiller::getPolNo() startSec=" << startSec << LogIO::POST ;
1043 Block<uInt> polno( 1 ) ;
1044
1045 if ( corrType == Stokes::I || corrType == Stokes::RR || corrType == Stokes::XX ) {
1046 polno = 0 ;
1047 }
1048 else if ( corrType == Stokes::Q || corrType == Stokes::LL || corrType == Stokes::YY ) {
1049 polno = 1 ;
1050 }
1051 else if ( corrType == Stokes::U ) {
1052 polno = 2 ;
1053 }
1054 else if ( corrType == Stokes::V ) {
1055 polno = 3 ;
1056 }
1057 else if ( corrType == Stokes::RL || corrType == Stokes::XY || corrType == Stokes::LR || corrType == Stokes::RL ) {
1058 polno.resize( 2 ) ;
1059 polno[0] = 2 ;
1060 polno[1] = 3 ;
1061 }
1062 else if ( corrType == Stokes::Plinear ) {
1063 polno[0] = 1 ;
1064 }
1065 else if ( corrType == Stokes::Pangle ) {
1066 polno[0] = 2 ;
1067 }
1068 else {
1069 polno = 99 ;
1070 }
1071 //os_ << "polno = " << polno << LogIO::POST ;
1072 double endSec = gettimeofday_sec() ;
1073 os_ << "end MSFiller::getPolNo() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1074
1075 return polno ;
1076}
1077
1078String MSFiller::getPolType( Int corrType )
1079{
1080 double startSec = gettimeofday_sec() ;
1081 os_ << "start MSFiller::getPolType() startSec=" << startSec << LogIO::POST ;
1082 String poltype = "" ;
1083
1084 if ( corrType == Stokes::I || corrType == Stokes::Q || corrType == Stokes::U || corrType == Stokes::V )
1085 poltype = "stokes" ;
1086 else if ( corrType == Stokes::XX || corrType == Stokes::YY || corrType == Stokes::XY || corrType == Stokes::YX )
1087 poltype = "linear" ;
1088 else if ( corrType == Stokes::RR || corrType == Stokes::LL || corrType == Stokes::RL || corrType == Stokes::LR )
1089 poltype = "circular" ;
1090 else if ( corrType == Stokes::Plinear || corrType == Stokes::Pangle )
1091 poltype = "linpol" ;
1092
1093 double endSec = gettimeofday_sec() ;
1094 os_ << "end MSFiller::getPolType() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1095 return poltype ;
1096}
1097
1098void MSFiller::fillWeather()
1099{
1100 double startSec = gettimeofday_sec() ;
1101 os_ << "start MSFiller::fillWeather() startSec=" << startSec << LogIO::POST ;
1102 Table mWeather = mstable_.weather() ;
1103 //Table mWeatherSel = mWeather( mWeather.col("ANTENNA_ID") == antenna_ ).sort("TIME") ;
1104 Table mWeatherSel( mWeather( mWeather.col("ANTENNA_ID") == antenna_ ).sort("TIME") ) ;
1105 //os_ << "mWeatherSel.nrow() = " << mWeatherSel.nrow() << LogIO::POST ;
1106 if ( mWeatherSel.nrow() == 0 ) {
1107 os_ << "No rows with ANTENNA_ID = " << antenna_ << ", Try -1..." << LogIO::POST ;
1108 mWeatherSel = Table( MSWeather( mWeather( mWeather.col("ANTENNA_ID") == -1 ) ) ) ;
1109 if ( mWeatherSel.nrow() == 0 ) {
1110 os_ << "No rows in WEATHER table" << LogIO::POST ;
1111 }
1112 }
1113 uInt wnrow = mWeatherSel.nrow() ;
1114 //os_ << "wnrow = " << wnrow << LogIO::POST ;
1115
1116 if ( wnrow == 0 )
1117 return ;
1118
1119 Table wtab = table_->weather().table() ;
1120 wtab.addRow( wnrow ) ;
1121
1122 ScalarColumn<Float> *fCol ;
1123 ROScalarColumn<Float> *sharedFloatCol ;
1124 if ( mWeatherSel.tableDesc().isColumn( "TEMPERATURE" ) ) {
1125 fCol = new ScalarColumn<Float>( wtab, "TEMPERATURE" ) ;
1126 sharedFloatCol = new ROScalarColumn<Float>( mWeatherSel, "TEMPERATURE" ) ;
1127 fCol->putColumn( *sharedFloatCol ) ;
1128 delete sharedFloatCol ;
1129 delete fCol ;
1130 }
1131 if ( mWeatherSel.tableDesc().isColumn( "PRESSURE" ) ) {
1132 fCol = new ScalarColumn<Float>( wtab, "PRESSURE" ) ;
1133 sharedFloatCol = new ROScalarColumn<Float>( mWeatherSel, "PRESSURE" ) ;
1134 fCol->putColumn( *sharedFloatCol ) ;
1135 delete sharedFloatCol ;
1136 delete fCol ;
1137 }
1138 if ( mWeatherSel.tableDesc().isColumn( "REL_HUMIDITY" ) ) {
1139 fCol = new ScalarColumn<Float>( wtab, "HUMIDITY" ) ;
1140 sharedFloatCol = new ROScalarColumn<Float>( mWeatherSel, "REL_HUMIDITY" ) ;
1141 fCol->putColumn( *sharedFloatCol ) ;
1142 delete sharedFloatCol ;
1143 delete fCol ;
1144 }
1145 if ( mWeatherSel.tableDesc().isColumn( "WIND_SPEED" ) ) {
1146 fCol = new ScalarColumn<Float>( wtab, "WINDSPEED" ) ;
1147 sharedFloatCol = new ROScalarColumn<Float>( mWeatherSel, "WIND_SPEED" ) ;
1148 fCol->putColumn( *sharedFloatCol ) ;
1149 delete sharedFloatCol ;
1150 delete fCol ;
1151 }
1152 if ( mWeatherSel.tableDesc().isColumn( "WIND_DIRECTION" ) ) {
1153 fCol = new ScalarColumn<Float>( wtab, "WINDAZ" ) ;
1154 sharedFloatCol = new ROScalarColumn<Float>( mWeatherSel, "WIND_DIRECTION" ) ;
1155 fCol->putColumn( *sharedFloatCol ) ;
1156 delete sharedFloatCol ;
1157 delete fCol ;
1158 }
1159 ScalarColumn<uInt> idCol( wtab, "ID" ) ;
1160 for ( uInt irow = 0 ; irow < wnrow ; irow++ )
1161 idCol.put( irow, irow ) ;
1162
1163 ROScalarQuantColumn<Double> tqCol( mWeatherSel, "TIME" ) ;
1164 ROScalarColumn<Double> tCol( mWeatherSel, "TIME" ) ;
1165 String tUnit = tqCol.getUnits() ;
1166 mwTime_ = tCol.getColumn() ;
1167 if ( tUnit == "d" )
1168 mwTime_ *= 86400.0 ;
1169 tqCol.attach( mWeatherSel, "INTERVAL" ) ;
1170 tCol.attach( mWeatherSel, "INTERVAL" ) ;
1171 String iUnit = tqCol.getUnits() ;
1172 mwInterval_ = tCol.getColumn() ;
1173 if ( iUnit == "d" )
1174 mwInterval_ *= 86400.0 ;
1175 //os_ << "mwTime[0] = " << mwTime_[0] << " mwInterval[0] = " << mwInterval_[0] << LogIO::POST ;
1176 double endSec = gettimeofday_sec() ;
1177 os_ << "end MSFiller::fillWeather() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1178}
1179
1180void MSFiller::fillFocus()
1181{
1182 double startSec = gettimeofday_sec() ;
1183 os_ << "start MSFiller::fillFocus() startSec=" << startSec << LogIO::POST ;
1184 // tentative
1185 Table tab = table_->focus().table() ;
1186 tab.addRow( 1 ) ;
1187 ScalarColumn<uInt> idCol( tab, "ID" ) ;
1188 idCol.put( 0, 0 ) ;
1189 double endSec = gettimeofday_sec() ;
1190 os_ << "end MSFiller::fillFocus() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1191}
1192
1193void MSFiller::fillTcal( boost::object_pool<ROTableColumn> *tpoolr )
1194{
1195 double startSec = gettimeofday_sec() ;
1196 os_ << "start MSFiller::fillTcal() startSec=" << startSec << LogIO::POST ;
1197
1198 Table sctab = mstable_.sysCal() ;
1199 if ( sctab.nrow() == 0 ) {
1200 os_ << "No SysCal rows" << LogIO::POST ;
1201 return ;
1202 }
1203 Table sctabsel( sctab( sctab.col("ANTENNA_ID") == antenna_ ) ) ;
1204 if ( sctabsel.nrow() == 0 ) {
1205 os_ << "No SysCal rows" << LogIO::POST ;
1206 return ;
1207 }
1208 ROArrayColumn<Float> *tmpTcalCol = new ROArrayColumn<Float>( sctabsel, "TCAL" ) ;
1209 uInt npol = tmpTcalCol->shape( 0 )(0) ;
1210 delete tmpTcalCol ;
1211 //os_ << "fillTcal(): npol = " << npol << LogIO::POST ;
1212 Table tab = table_->tcal().table() ;
1213 ArrayColumn<Float> tcalCol( tab, "TCAL" ) ;
1214 ROTableColumn *sharedCol ;
1215 uInt oldnr = 0 ;
1216 uInt newnr = 0 ;
1217 TableRow row( tab ) ;
1218 TableRecord &trec = row.record() ;
1219 RecordFieldPtr<uInt> idRF( trec, "ID" ) ;
1220 RecordFieldPtr<String> timeRF( trec, "TIME" ) ;
1221 RecordFieldPtr< Array<Float> > tcalRF( trec, "TCAL" ) ;
1222 TableIterator iter0( sctabsel, "FEED_ID" ) ;
1223 while( !iter0.pastEnd() ) {
1224 Table t0 = iter0.table() ;
1225 sharedCol = tpoolr->construct( t0, "FEED_ID" ) ;
1226 Int feedId = sharedCol->asInt( 0 ) ;
1227 tpoolr->destroy( sharedCol ) ;
1228 TableIterator iter1( t0, "SPECTRAL_WINDOW_ID" ) ;
1229 while( !iter1.pastEnd() ) {
1230 Table t1 = iter1.table() ;
1231 sharedCol = tpoolr->construct( t1, "SPECTRAL_WINDOW_ID" ) ;
1232 Int spwId = sharedCol->asInt( 0 ) ;
1233 tpoolr->destroy( sharedCol ) ;
1234 tmpTcalCol = new ROArrayColumn<Float>( t1, colTcal_ ) ;
1235 ROScalarQuantColumn<Double> scTimeCol( t1, "TIME" ) ;
1236 Vector<uInt> idminmax( 2, oldnr ) ;
1237 for ( uInt irow = 0 ; irow < t1.nrow() ; irow++ ) {
1238 String sTime = MVTime( scTimeCol(irow) ).string( MVTime::YMD ) ;
1239 *timeRF = sTime ;
1240 uInt idx = oldnr ;
1241 Matrix<Float> subtcal = (*tmpTcalCol)( irow ) ;
1242 for ( uInt ipol = 0 ; ipol < npol ; ipol++ ) {
1243 *idRF = idx++ ;
1244 *tcalRF = subtcal.row( ipol ) ;
1245
1246 // commit row
1247 tab.addRow() ;
1248 row.put( tab.nrow()-1 ) ;
1249
1250 newnr++ ;
1251 }
1252 idminmax[0] = oldnr ;
1253 idminmax[1] = newnr - 1 ;
1254 oldnr = newnr ;
1255
1256 String key = keyTcal( feedId, spwId, sTime ) ;
1257 tcalrec_.define( key, idminmax ) ;
1258 }
1259 delete tmpTcalCol ;
1260 iter1++ ;
1261 }
1262 iter0++ ;
1263 }
1264
1265 //tcalrec_.print( std::cout ) ;
1266 double endSec = gettimeofday_sec() ;
1267 os_ << "end MSFiller::fillTcal() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1268}
1269
1270uInt MSFiller::getWeatherId( uInt idx, Double wtime )
1271{
1272 double startSec = gettimeofday_sec() ;
1273 os_ << "start MSFiller::getWeatherId() startSec=" << startSec << LogIO::POST ;
1274 uInt nrow = mwTime_.size() ;
1275 if ( nrow == 0 )
1276 return 0 ;
1277 uInt wid = nrow ;
1278 for ( uInt i = idx ; i < nrow-1 ; i++ ) {
1279 Double tStart = mwTime_[i]-0.5*mwInterval_[i] ;
1280 // use of INTERVAL column is problematic
1281 // since there are "blank" time of weather monitoring
1282 //Double tEnd = tStart + mwInterval_[i] ;
1283 Double tEnd = mwTime_[i+1]-0.5*mwInterval_[i+1] ;
1284 //os_ << "tStart = " << tStart << " dtEnd = " << tEnd-tStart << " dwtime = " << wtime-tStart << LogIO::POST ;
1285 if ( wtime >= tStart && wtime <= tEnd ) {
1286 wid = i ;
1287 break ;
1288 }
1289 }
1290 if ( wid == nrow ) {
1291 uInt i = nrow - 1 ;
1292 Double tStart = mwTime_[i-1]+0.5*mwInterval_[i-1] ;
1293 Double tEnd = mwTime_[i]+0.5*mwInterval_[i] ;
1294 //os_ << "tStart = " << tStart << " dtEnd = " << tEnd-tStart << " dwtime = " << wtime-tStart << LogIO::POST ;
1295 if ( wtime >= tStart && wtime <= tEnd )
1296 wid = i ;
1297 }
1298
1299 //if ( wid == nrow )
1300 //os_ << LogIO::WARN << "Couldn't find correct WEATHER_ID for time " << wtime << LogIO::POST ;
1301
1302 double endSec = gettimeofday_sec() ;
1303 os_ << "end MSFiller::getWeatherId() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1304 return wid ;
1305}
1306
1307void MSFiller::getSysCalTime( Block<MEpoch> &scTime, Vector<Double> &scInterval, Block<MEpoch> &tcol, Block<Double> &tstr, Block<Int> &tidx )
1308{
1309 double startSec = gettimeofday_sec() ;
1310 os_ << "start MSFiller::getSysCalTime() startSec=" << startSec << LogIO::POST ;
1311 uInt nrow = tstr.nelements() ;
1312 if ( scTime.nelements() == 0 )
1313 return ;
1314 uInt scnrow = scTime.nelements() ;
1315 uInt idx = 0 ;
1316 const Double half = 0.5e0 ;
1317 for ( uInt i = 0 ; i < nrow ; i++ ) {
1318 Double t = tcol[i].get( "s" ).getValue() ;
1319 os_ << "getSysCalTime() irow = " << i << " idx = " << idx << LogIO::POST ;
1320 for ( uInt j = idx ; j < scnrow-1 ; j++ ) {
1321 Double tsc1 = scTime[j].get( "s" ).getValue() ;
1322 Double dt1 = scInterval[j] ;
1323 Double tsc2 = scTime[j+1].get( "s" ).getValue() ;
1324 Double dt2 = scInterval[j+1] ;
1325 if ( t > tsc1-half*dt1 && t <= tsc2-half*dt2 ) {
1326 tstr[i] = tsc1 ;
1327 tidx[i] = j ;
1328 idx = j ;
1329 break ;
1330 }
1331 }
1332 if ( tstr[i] == -1.0 ) {
1333 Double tsc = scTime[scnrow-1].get( "s" ).getValue() ;
1334 Double dt = scInterval[scnrow-1] ;
1335 if ( t <= tsc+0.5*dt ) {
1336 tstr[i] = tsc ;
1337 tidx[i] = scnrow-1 ;
1338 }
1339 }
1340 }
1341 double endSec = gettimeofday_sec() ;
1342 os_ << "end MSFiller::getSysCalTime() endSec=" << endSec << " (" << endSec-startSec << "sec) scnrow = " << scnrow << "tcol.nelements() = " << tcol.nelements() << LogIO::POST ;
1343 return ;
1344}
1345
1346// uInt MSFiller::getTsys( uInt idx, Matrix<Float> &tsys, ROArrayColumn<Float> &mTsysCol, Block<MEpoch> &scTimeCol, Double t )
1347// {
1348// double startSec = gettimeofday_sec() ;
1349// os_ << "start MSFiller::getTsys() startSec=" << startSec << LogIO::POST ;
1350// uInt nrow = mTsysCol.nrow() ;
1351// if ( nrow == 0 ) {
1352// os_ << "No SysCal rows" << LogIO::POST ;
1353// tsys.resize( IPosition(0) ) ;
1354// return 0 ;
1355// }
1356// for ( uInt i = idx ; i < nrow ; i++ ) {
1357// Double tref = scTimeCol[i].get("s").getValue() ;
1358// if ( t == tref ) {
1359// tsys.reference( mTsysCol( i ) ) ;
1360// idx = i ;
1361// break ;
1362// }
1363// }
1364// //os_ << "MSFiller::getTsys() idx = " << idx << " tsys = " << tsys << LogIO::POST ;
1365// double endSec = gettimeofday_sec() ;
1366// os_ << "end MSFiller::getTsys() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1367// return idx ;
1368// }
1369
1370Block<uInt> MSFiller::getTcalId( Int fid, Int spwid, Double t )
1371{
1372 double startSec = gettimeofday_sec() ;
1373 os_ << "start MSFiller::getTcalId() startSec=" << startSec << LogIO::POST ;
1374 if ( table_->tcal().table().nrow() == 0 ) {
1375 os_ << "No TCAL rows" << LogIO::POST ;
1376 Block<uInt> tcalids( 0 ) ;
1377 return tcalids ;
1378 }
1379 String sctime = MVTime( Quantum<Double>(t,"s") ).string(MVTime::YMD) ;
1380 String key = keyTcal( fid, spwid, sctime ) ;
1381 if ( !tcalrec_.isDefined( key ) ) {
1382 os_ << "No TCAL rows" << LogIO::POST ;
1383 Block<uInt> tcalids( 0 ) ;
1384 return tcalids ;
1385 }
1386 Vector<uInt> ids = tcalrec_.asArrayuInt( key ) ;
1387 uInt npol = ids[1] - ids[0] + 1 ;
1388 Block<uInt> tcalids( npol ) ;
1389 tcalids[0] = ids[0] ;
1390 tcalids[1] = ids[1] ;
1391 for ( uInt ipol = 2 ; ipol < npol ; ipol++ )
1392 tcalids[ipol] = ids[0] + ipol - 1 ;
1393
1394 double endSec = gettimeofday_sec() ;
1395 os_ << "end MSFiller::getTcalId() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1396 return tcalids ;
1397}
1398
1399uInt MSFiller::getDirection( uInt idx, Vector<Double> &dir, Vector<Double> &srate, String &ref, MSPointing &tab, Double t )
1400{
1401 double startSec = gettimeofday_sec() ;
1402 os_ << "start MSFiller::getDirection() startSec=" << startSec << LogIO::POST ;
1403 // assume that cols is sorted by TIME
1404 Bool doInterp = False ;
1405 //uInt nrow = cols.nrow() ;
1406 uInt nrow = tab.nrow() ;
1407 if ( nrow == 0 )
1408 return 0 ;
1409 ROScalarMeasColumn<MEpoch> tcol( tab, "TIME" ) ;
1410 ROArrayMeasColumn<MDirection> dmcol( tab, "DIRECTION" ) ;
1411 ROArrayColumn<Double> dcol( tab, "DIRECTION" ) ;
1412 // ensure that tcol(idx) < t
1413 //os_ << "tcol(idx) = " << tcol(idx).get("s").getValue() << " t = " << t << " diff = " << tcol(idx).get("s").getValue()-t << endl ;
1414 while ( tcol(idx).get("s").getValue() > t && idx > 0 )
1415 idx-- ;
1416 //os_ << "idx = " << idx << LogIO::POST ;
1417
1418 // index search
1419 for ( uInt i = idx ; i < nrow ; i++ ) {
1420 Double tref = tcol( i ).get( "s" ).getValue() ;
1421 if ( tref == t ) {
1422 idx = i ;
1423 break ;
1424 }
1425 else if ( tref > t ) {
1426 if ( i == 0 ) {
1427 idx = i ;
1428 }
1429 else {
1430 idx = i-1 ;
1431 doInterp = True ;
1432 }
1433 break ;
1434 }
1435 else {
1436 idx = nrow - 1 ;
1437 }
1438 }
1439 //os_ << "searched idx = " << idx << LogIO::POST ;
1440
1441 //os_ << "dmcol(idx).shape() = " << dmcol(idx).shape() << LogIO::POST ;
1442 IPosition ip( dmcol(idx).shape().nelements(), 0 ) ;
1443 //os_ << "ip = " << ip << LogIO::POST ;
1444 ref = dmcol(idx)(ip).getRefString() ;
1445 //os_ << "ref = " << ref << LogIO::POST ;
1446 if ( doInterp ) {
1447 //os_ << "do interpolation" << LogIO::POST ;
1448 //os_ << "dcol(idx).shape() = " << dcol(idx).shape() << LogIO::POST ;
1449 Double tref0 = tcol(idx).get("s").getValue() ;
1450 Double tref1 = tcol(idx+1).get("s").getValue() ;
1451 Matrix<Double> mdir0 = dcol( idx ) ;
1452 Matrix<Double> mdir1 = dcol( idx+1 ) ;
1453 Vector<Double> dir0 = mdir0.column( 0 ) ;
1454 //os_ << "dir0 = " << dir0 << LogIO::POST ;
1455 Vector<Double> dir1 = mdir1.column( 0 ) ;
1456 //os_ << "dir1 = " << dir1 << LogIO::POST ;
1457 Double dt0 = t - tref0 ;
1458 Double dt1 = tref1 - t ;
1459 dir.reference( (dt0*dir1+dt1*dir0)/(dt0+dt1) ) ;
1460 if ( mdir0.ncolumn() > 1 ) {
1461 if ( dt0 >= dt1 )
1462 srate.reference( mdir0.column( 1 ) ) ;
1463 else
1464 srate.reference( mdir1.column( 1 ) ) ;
1465 }
1466 //os_ << "dir = " << dir << LogIO::POST ;
1467 }
1468 else {
1469 //os_ << "no interpolation" << LogIO::POST ;
1470 Matrix<Double> mdir0 = dcol( idx ) ;
1471 dir.reference( mdir0.column( 0 ) ) ;
1472 if ( mdir0.ncolumn() > 1 )
1473 srate.reference( mdir0.column( 1 ) ) ;
1474 }
1475
1476 double endSec = gettimeofday_sec() ;
1477 os_ << "end MSFiller::getDirection() endSec=" << endSec << " (" << endSec-startSec << "sec)" << LogIO::POST ;
1478 return idx ;
1479}
1480
1481String MSFiller::keyTcal( Int feedid, Int spwid, String stime )
1482{
1483 String sfeed = "FEED" + String::toString( feedid ) ;
1484 String sspw = "SPW" + String::toString( spwid ) ;
1485 return sfeed+":"+sspw+":"+stime ;
1486}
1487
1488} ;
1489
Note: See TracBrowser for help on using the repository browser.