source: trunk/src/STMath.cpp@ 2917

Last change on this file since 2917 was 2917, checked in by Takeshi Nakazato, 12 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: Yes/No

What Interface Changed: Please list interface changes

Test Programs: test_sdcal, test_sdcal2

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Refactoring calibration code in STMath.


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 155.9 KB
Line 
1//
2// C++ Implementation: STMath
3//
4// Description:
5//
6//
7// Author: Malte Marquarding <asap@atnf.csiro.au>, (C) 2006
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
12
13#include <sstream>
14
15#include <casa/iomanip.h>
16#include <casa/Arrays/MaskArrLogi.h>
17#include <casa/Arrays/MaskArrMath.h>
18#include <casa/Arrays/ArrayLogical.h>
19#include <casa/Arrays/ArrayMath.h>
20#include <casa/Arrays/Slice.h>
21#include <casa/Arrays/Slicer.h>
22#include <casa/BasicSL/String.h>
23#include <casa/Containers/Block.h>
24#include <casa/Containers/RecordField.h>
25#include <casa/Exceptions/Error.h>
26#include <casa/Logging/LogIO.h>
27#include <casa/Quanta/Quantum.h>
28
29#include <coordinates/Coordinates/CoordinateSystem.h>
30#include <coordinates/Coordinates/CoordinateUtil.h>
31#include <coordinates/Coordinates/FrequencyAligner.h>
32#include <coordinates/Coordinates/SpectralCoordinate.h>
33
34#include <lattices/Lattices/LatticeUtilities.h>
35
36#include <scimath/Functionals/Polynomial.h>
37#include <scimath/Mathematics/Convolver.h>
38#include <scimath/Mathematics/VectorKernel.h>
39
40#include <tables/Tables/ExprNode.h>
41#include <tables/Tables/ReadAsciiTable.h>
42#include <tables/Tables/TableCopy.h>
43#include <tables/Tables/TableIter.h>
44#include <tables/Tables/TableParse.h>
45#include <tables/Tables/TableRecord.h>
46#include <tables/Tables/TableRow.h>
47#include <tables/Tables/TableVector.h>
48#include <tables/Tables/TabVecMath.h>
49
50#include <atnf/PKSIO/SrcType.h>
51
52#include "RowAccumulator.h"
53#include "STAttr.h"
54#include "STMath.h"
55#include "STSelector.h"
56#include "Accelerator.h"
57#include "STIdxIter.h"
58
59#include "CalibrationHelper.h"
60
61using namespace casa;
62using namespace asap;
63
64// namespace {
65// class CalibrationIterator
66// {
67// public:
68// CalibrationIterator()
69// : table_(table)
70// {}
71// ~CalibrationIterator() {}
72// void Iterate() {
73// STSelector sel;
74// vector<string> cols( 3 ) ;
75// cols[0] = "BEAMNO" ;
76// cols[1] = "POLNO" ;
77// cols[2] = "IFNO" ;
78// STIdxIter2 iter(out, cols);
79// while ( !iter.pastEnd() ) {
80// Record ids = iter.currentValue();
81// stringstream ss ;
82// ss << "SELECT FROM $1 WHERE "
83// << "BEAMNO==" << ids.asuInt("BEAMNO") << "&&"
84// << "POLNO==" << ids.asuInt("POLNO") << "&&"
85// << "IFNO==" << ids.asuInt("IFNO") ;
86// //cout << "TaQL string: " << ss.str() << endl ;
87// sel.setTaQL( ss.str() ) ;
88// ////
89// // begin individual processing
90// aoff->setSelection( sel ) ;
91// ahot->setSelection( sel ) ;
92// asky->setSelection( sel ) ;
93// Vector<uInt> rows = iter.getRows( SHARE ) ;
94// // out should be an exact copy of s except that SPECTRA column is empty
95// calibrateCW( out, s, aoff, asky, ahot, acold, rows, antname ) ;
96// aoff->unsetSelection() ;
97// ahot->unsetSelection() ;
98// asky->unsetSelection() ;
99// // end individual processing
100// ////
101// sel.reset() ;
102// iter.next() ;
103// }
104// };
105// protected:
106// CountedPtr<Scantable> table_;
107// };
108
109
110// } // anonymous namespace
111
112// 2012/02/17 TN
113// Since STGrid is implemented, average doesn't consider direction
114// when accumulating
115// tolerance for direction comparison (rad)
116// #define TOL_OTF 1.0e-15
117// #define TOL_POINT 2.9088821e-4 // 1 arcmin
118
119STMath::STMath(bool insitu) :
120 insitu_(insitu)
121{
122}
123
124
125STMath::~STMath()
126{
127}
128
129CountedPtr<Scantable>
130STMath::average( const std::vector<CountedPtr<Scantable> >& in,
131 const std::vector<bool>& mask,
132 const std::string& weight,
133 const std::string& avmode)
134{
135// double t0, t1 ;
136// t0 = mathutil::gettimeofday_sec() ;
137
138 LogIO os( LogOrigin( "STMath", "average()", WHERE ) ) ;
139 if ( avmode == "SCAN" && in.size() != 1 )
140 throw(AipsError("Can't perform 'SCAN' averaging on multiple tables.\n"
141 "Use merge first."));
142 WeightType wtype = stringToWeight(weight);
143
144 // 2012/02/17 TN
145 // Since STGrid is implemented, average doesn't consider direction
146 // when accumulating
147 // check if OTF observation
148// String obstype = in[0]->getHeader().obstype ;
149// Double tol = 0.0 ;
150// if ( (obstype.find( "OTF" ) != String::npos) || (obstype.find( "OBSERVE_TARGET" ) != String::npos) ) {
151// tol = TOL_OTF ;
152// }
153// else {
154// tol = TOL_POINT ;
155// }
156
157 // output
158 // clone as this is non insitu
159 bool insitu = insitu_;
160 setInsitu(false);
161 CountedPtr< Scantable > out = getScantable(in[0], true);
162 setInsitu(insitu);
163 std::vector<CountedPtr<Scantable> >::const_iterator stit = in.begin();
164 ++stit;
165 while ( stit != in.end() ) {
166 out->appendToHistoryTable((*stit)->history());
167 ++stit;
168 }
169
170 Table& tout = out->table();
171
172 /// @todo check if all scantables are conformant
173
174 ArrayColumn<Float> specColOut(tout,"SPECTRA");
175 ArrayColumn<uChar> flagColOut(tout,"FLAGTRA");
176 ArrayColumn<Float> tsysColOut(tout,"TSYS");
177 ScalarColumn<Double> mjdColOut(tout,"TIME");
178 ScalarColumn<Double> intColOut(tout,"INTERVAL");
179 ScalarColumn<uInt> cycColOut(tout,"CYCLENO");
180 ScalarColumn<uInt> scanColOut(tout,"SCANNO");
181 ScalarColumn<uInt> flagRowColOut(tout,"FLAGROW");
182
183 // set up the output table rows. These are based on the structure of the
184 // FIRST scantable in the vector
185 const Table& baset = in[0]->table();
186
187 RowAccumulator acc(wtype);
188 Vector<Bool> cmask(mask);
189 acc.setUserMask(cmask);
190// ROTableRow row(tout);
191 ROArrayColumn<Float> specCol, tsysCol;
192 ROArrayColumn<uChar> flagCol;
193 ROScalarColumn<Double> mjdCol, intCol;
194 ROScalarColumn<Int> scanIDCol;
195 ROScalarColumn<uInt> flagRowCol;
196
197 //Vector<uInt> rowstodelete;
198 Block<uInt> rowstodelB( in[0]->nrow() ) ;
199 uInt nrowdel = 0 ;
200
201// Block<String> cols(3);
202 vector<string> cols(3) ;
203 cols[0] = String("BEAMNO");
204 cols[1] = String("IFNO");
205 cols[2] = String("POLNO");
206 if ( avmode == "SOURCE" ) {
207 cols.resize(4);
208 cols[3] = String("SRCNAME");
209 }
210 if ( avmode == "SCAN" && in.size() == 1) {
211 //cols.resize(4);
212 //cols[3] = String("SCANNO");
213 cols.resize(5);
214 cols[3] = String("SRCNAME");
215 cols[4] = String("SCANNO");
216 }
217 uInt outrowCount = 0;
218 // use STIdxIterExAcc instead of TableIterator
219 STIdxIterExAcc iter( in[0], cols ) ;
220// double t2 = 0 ;
221// double t3 = 0 ;
222// double t4 = 0 ;
223// double t5 = 0 ;
224// TableIterator iter(baset, cols);
225// int count = 0 ;
226 while (!iter.pastEnd()) {
227 Vector<uInt> rows = iter.getRows( SHARE ) ;
228 if ( rows.nelements() == 0 ) {
229 iter.next() ;
230 continue ;
231 }
232 Vector<uInt> current = iter.current() ;
233 String srcname = iter.getSrcName() ;
234 //Table subt = iter.table();
235 // copy the first row of this selection into the new table
236 tout.addRow();
237// t4 = mathutil::gettimeofday_sec() ;
238 // skip to copy SPECTRA, FLAGTRA, and TSYS since those heavy columns are
239 // overwritten in the following process
240 copyRows( tout, baset, outrowCount, rows[0], 1, False, False, False ) ;
241// t5 += mathutil::gettimeofday_sec() - t4 ;
242 // re-index to 0
243 if ( avmode != "SCAN" && avmode != "SOURCE" ) {
244 scanColOut.put(outrowCount, uInt(0));
245 }
246
247 // 2012/02/17 TN
248 // Since STGrid is implemented, average doesn't consider direction
249 // when accumulating
250// MDirection::ScalarColumn dircol ;
251// dircol.attach( subt, "DIRECTION" ) ;
252// Int length = subt.nrow() ;
253// vector< Vector<Double> > dirs ;
254// vector<int> indexes ;
255// for ( Int i = 0 ; i < length ; i++ ) {
256// Vector<Double> t = dircol(i).getAngle(Unit(String("rad"))).getValue() ;
257// //os << << count++ << ": " ;
258// //os << "[" << t[0] << "," << t[1] << "]" << LogIO::POST ;
259// bool adddir = true ;
260// for ( uInt j = 0 ; j < dirs.size() ; j++ ) {
261// //if ( allTrue( t == dirs[j] ) ) {
262// Double dx = t[0] - dirs[j][0] ;
263// Double dy = t[1] - dirs[j][1] ;
264// Double dd = sqrt( dx * dx + dy * dy ) ;
265// //if ( allNearAbs( t, dirs[j], tol ) ) {
266// if ( dd <= tol ) {
267// adddir = false ;
268// break ;
269// }
270// }
271// if ( adddir ) {
272// dirs.push_back( t ) ;
273// indexes.push_back( i ) ;
274// }
275// }
276// uInt rowNum = dirs.size() ;
277// tout.addRow( rowNum ) ;
278// for ( uInt i = 0 ; i < rowNum ; i++ ) {
279// TableCopy::copyRows( tout, subt, outrowCount+i, indexes[i], 1 ) ;
280// // re-index to 0
281// if ( avmode != "SCAN" && avmode != "SOURCE" ) {
282// scanColOut.put(outrowCount+i, uInt(0));
283// }
284// }
285// outrowCount += rowNum ;
286
287 // merge loop
288 uInt i = outrowCount ;
289 // in[0] is already selected by iterator
290 specCol.attach(baset,"SPECTRA");
291 flagCol.attach(baset,"FLAGTRA");
292 tsysCol.attach(baset,"TSYS");
293 intCol.attach(baset,"INTERVAL");
294 mjdCol.attach(baset,"TIME");
295 flagRowCol.attach(baset,"FLAGROW");
296 Vector<Float> spec,tsys;
297 Vector<uChar> flag;
298 Double inter,time;
299 uInt flagRow;
300
301 for (uInt l = 0; l < rows.nelements(); ++l ) {
302 uInt k = rows[l] ;
303 flagCol.get(k, flag);
304 Vector<Bool> bflag(flag.shape());
305 flagRowCol.get(k, flagRow);
306 if (flagRow > 0)
307 bflag = true;
308 else
309 convertArray(bflag, flag);
310 /*
311 if ( allEQ(bflag, True) ) {
312 continue;//don't accumulate
313 }
314 */
315 specCol.get(k, spec);
316 tsysCol.get(k, tsys);
317 intCol.get(k, inter);
318 mjdCol.get(k, time);
319 // spectrum has to be added last to enable weighting by the other values
320// t2 = mathutil::gettimeofday_sec() ;
321 acc.add(spec, !bflag, tsys, inter, time);
322// t3 += mathutil::gettimeofday_sec() - t2 ;
323
324 }
325
326
327 // in[0] is already selected by TableIterator so that index is
328 // started from 1
329 for ( int j=1; j < int(in.size()); ++j ) {
330 const Table& tin = in[j]->table();
331 //const TableRecord& rec = row.get(i);
332 ROScalarColumn<Double> tmp(tin, "TIME");
333 Double td;tmp.get(0,td);
334
335#if 1
336 static char const*const colNames1[] = { "IFNO", "BEAMNO", "POLNO" };
337 //uInt const values1[] = { rec.asuInt("IFNO"), rec.asuInt("BEAMNO"), rec.asuInt("POLNO") };
338 uInt const values1[] = { current[1], current[0], current[2] };
339 SingleTypeEqPredicate<uInt, 3> myPred(tin, colNames1, values1);
340 CustomTableExprNodeRep myNodeRep(tin, myPred);
341 myNodeRep.link(); // to avoid automatic delete when myExpr is destructed.
342 CustomTableExprNode myExpr(myNodeRep);
343 Table basesubt = tin(myExpr);
344#else
345// Table basesubt = tin( tin.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
346// && tin.col("IFNO") == Int(rec.asuInt("IFNO"))
347// && tin.col("POLNO") == Int(rec.asuInt("POLNO")) );
348 Table basesubt = tin( tin.col("BEAMNO") == current[0]
349 && tin.col("IFNO") == current[1]
350 && tin.col("POLNO") == current[2] );
351#endif
352 Table subt;
353 if ( avmode == "SOURCE") {
354// subt = basesubt( basesubt.col("SRCNAME") == rec.asString("SRCNAME"));
355 subt = basesubt( basesubt.col("SRCNAME") == srcname );
356
357 } else if (avmode == "SCAN") {
358// subt = basesubt( basesubt.col("SRCNAME") == rec.asString("SRCNAME")
359// && basesubt.col("SCANNO") == Int(rec.asuInt("SCANNO")) );
360 subt = basesubt( basesubt.col("SRCNAME") == srcname
361 && basesubt.col("SCANNO") == current[4] );
362 } else {
363 subt = basesubt;
364 }
365
366 // 2012/02/17 TN
367 // Since STGrid is implemented, average doesn't consider direction
368 // when accumulating
369// vector<uInt> removeRows ;
370// uInt nrsubt = subt.nrow() ;
371// for ( uInt irow = 0 ; irow < nrsubt ; irow++ ) {
372// //if ( !allTrue((subt.col("DIRECTION").getArrayDouble(TableExprId(irow)))==rec.asArrayDouble("DIRECTION")) ) {
373// Vector<Double> x0 = (subt.col("DIRECTION").getArrayDouble(TableExprId(irow))) ;
374// Vector<Double> x1 = rec.asArrayDouble("DIRECTION") ;
375// double dx = x0[0] - x1[0];
376// double dy = x0[1] - x1[1];
377// Double dd = sqrt( dx * dx + dy * dy ) ;
378// //if ( !allNearAbs((subt.col("DIRECTION").getArrayDouble(TableExprId(irow))), rec.asArrayDouble("DIRECTION"), tol ) ) {
379// if ( dd > tol ) {
380// removeRows.push_back( irow ) ;
381// }
382// }
383// if ( removeRows.size() != 0 ) {
384// subt.removeRow( removeRows ) ;
385// }
386
387// if ( nrsubt == removeRows.size() )
388// throw(AipsError("Averaging data is empty.")) ;
389
390 specCol.attach(subt,"SPECTRA");
391 flagCol.attach(subt,"FLAGTRA");
392 tsysCol.attach(subt,"TSYS");
393 intCol.attach(subt,"INTERVAL");
394 mjdCol.attach(subt,"TIME");
395 flagRowCol.attach(subt,"FLAGROW");
396 for (uInt k = 0; k < subt.nrow(); ++k ) {
397 flagCol.get(k, flag);
398 Vector<Bool> bflag(flag.shape());
399 flagRowCol.get(k, flagRow);
400 if (flagRow > 0)
401 bflag = true;
402 else
403 convertArray(bflag, flag);
404 /*
405 if ( allEQ(bflag, True) ) {
406 continue;//don't accumulate
407 }
408 */
409 specCol.get(k, spec);
410 //tsysCol.get(k, tsys);
411 tsys.assign( tsysCol(k) );
412 intCol.get(k, inter);
413 mjdCol.get(k, time);
414 // spectrum has to be added last to enable weighting by the other values
415// t2 = mathutil::gettimeofday_sec() ;
416 acc.add(spec, !bflag, tsys, inter, time);
417// t3 += mathutil::gettimeofday_sec() - t2 ;
418 }
419
420 }
421 const Vector<Bool>& msk = acc.getMask();
422 if ( allEQ(msk, False) ) {
423 rowstodelB[nrowdel] = i ;
424 nrowdel++ ;
425 continue;
426 }
427 //write out
428 if (acc.state()) {
429 // If there exists a channel at which all the input spectra are masked,
430 // spec has 'nan' values for that channel and it may affect the following
431 // processes. To avoid this, replacing 'nan' values in spec with
432 // weighted-mean of all spectra in the following line.
433 // (done for CAS-2776, 2011/04/07 by Wataru Kawasaki)
434 acc.replaceNaN();
435
436 Vector<uChar> flg(msk.shape());
437 convertArray(flg, !msk);
438 for (uInt k = 0; k < flg.nelements(); ++k) {
439 uChar userFlag = 1 << 7;
440 if (msk[k]==True) userFlag = 0 << 7;
441 flg(k) = userFlag;
442 }
443
444 flagColOut.put(i, flg);
445 specColOut.put(i, acc.getSpectrum());
446 tsysColOut.put(i, acc.getTsys());
447 intColOut.put(i, acc.getInterval());
448 mjdColOut.put(i, acc.getTime());
449 // we should only have one cycle now -> reset it to be 0
450 // frequency switched data has different CYCLENO for different IFNO
451 // which requires resetting this value
452 cycColOut.put(i, uInt(0));
453 // completely flagged rows are removed anyway
454 flagRowColOut.put(i, uInt(0));
455 } else {
456 os << "For output row="<<i<<", all input rows of data are flagged. no averaging" << LogIO::POST;
457 }
458 acc.reset();
459
460 // merge with while loop for preparing out table
461 ++outrowCount;
462// ++iter ;
463 iter.next() ;
464 }
465
466 if ( nrowdel > 0 ) {
467 Vector<uInt> rowstodelete( IPosition(1,nrowdel), rowstodelB.storage(), SHARE ) ;
468 os << rowstodelete << LogIO::POST ;
469 tout.removeRow(rowstodelete);
470 if (tout.nrow() == 0) {
471 throw(AipsError("Can't average fully flagged data."));
472 }
473 }
474
475// t1 = mathutil::gettimeofday_sec() ;
476// cout << "elapsed time for average(): " << t1-t0 << " sec" << endl ;
477// cout << " elapsed time for acc.add(): " << t3 << " sec" << endl ;
478// cout << " elapsed time for copyRows(): " << t5 << " sec" << endl ;
479
480 return out;
481}
482
483CountedPtr< Scantable >
484STMath::averageChannel( const CountedPtr < Scantable > & in,
485 const std::string & mode,
486 const std::string& avmode )
487{
488 (void) mode; // currently unused
489 // 2012/02/17 TN
490 // Since STGrid is implemented, average doesn't consider direction
491 // when accumulating
492 // check if OTF observation
493// String obstype = in->getHeader().obstype ;
494// Double tol = 0.0 ;
495// if ( obstype.find( "OTF" ) != String::npos ) {
496// tol = TOL_OTF ;
497// }
498// else {
499// tol = TOL_POINT ;
500// }
501
502 // clone as this is non insitu
503 bool insitu = insitu_;
504 setInsitu(false);
505 CountedPtr< Scantable > out = getScantable(in, true);
506 setInsitu(insitu);
507 Table& tout = out->table();
508 ArrayColumn<Float> specColOut(tout,"SPECTRA");
509 ArrayColumn<uChar> flagColOut(tout,"FLAGTRA");
510 ArrayColumn<Float> tsysColOut(tout,"TSYS");
511 ScalarColumn<uInt> scanColOut(tout,"SCANNO");
512 ScalarColumn<Double> intColOut(tout, "INTERVAL");
513 Table tmp = in->table().sort("BEAMNO");
514 Block<String> cols(3);
515 cols[0] = String("BEAMNO");
516 cols[1] = String("IFNO");
517 cols[2] = String("POLNO");
518 if ( avmode == "SCAN") {
519 cols.resize(4);
520 cols[3] = String("SCANNO");
521 }
522 uInt outrowCount = 0;
523 uChar userflag = 1 << 7;
524 TableIterator iter(tmp, cols);
525 while (!iter.pastEnd()) {
526 Table subt = iter.table();
527 ROArrayColumn<Float> specCol, tsysCol;
528 ROArrayColumn<uChar> flagCol;
529 ROScalarColumn<Double> intCol(subt, "INTERVAL");
530 specCol.attach(subt,"SPECTRA");
531 flagCol.attach(subt,"FLAGTRA");
532 tsysCol.attach(subt,"TSYS");
533
534 tout.addRow();
535 TableCopy::copyRows(tout, subt, outrowCount, 0, 1);
536 if ( avmode != "SCAN") {
537 scanColOut.put(outrowCount, uInt(0));
538 }
539 Vector<Float> tmp;
540 specCol.get(0, tmp);
541 uInt nchan = tmp.nelements();
542 // have to do channel by channel here as MaskedArrMath
543 // doesn't have partialMedians
544 Vector<uChar> flags = flagCol.getColumn(Slicer(Slice(0)));
545 Vector<Float> outspec(nchan);
546 Vector<uChar> outflag(nchan,0);
547 Vector<Float> outtsys(1);/// @fixme when tsys is channel based
548 for (uInt i=0; i<nchan; ++i) {
549 Vector<Float> specs = specCol.getColumn(Slicer(Slice(i)));
550 MaskedArray<Float> ma = maskedArray(specs,flags);
551 outspec[i] = median(ma);
552 if ( allEQ(ma.getMask(), False) )
553 outflag[i] = userflag;// flag data
554 }
555 outtsys[0] = median(tsysCol.getColumn());
556 specColOut.put(outrowCount, outspec);
557 flagColOut.put(outrowCount, outflag);
558 tsysColOut.put(outrowCount, outtsys);
559 Double intsum = sum(intCol.getColumn());
560 intColOut.put(outrowCount, intsum);
561 ++outrowCount;
562 ++iter;
563
564 // 2012/02/17 TN
565 // Since STGrid is implemented, average doesn't consider direction
566 // when accumulating
567// MDirection::ScalarColumn dircol ;
568// dircol.attach( subt, "DIRECTION" ) ;
569// Int length = subt.nrow() ;
570// vector< Vector<Double> > dirs ;
571// vector<int> indexes ;
572// // Handle MX mode averaging
573// if (in->nbeam() > 1 ) {
574// length = 1;
575// }
576// for ( Int i = 0 ; i < length ; i++ ) {
577// Vector<Double> t = dircol(i).getAngle(Unit(String("rad"))).getValue() ;
578// bool adddir = true ;
579// for ( uInt j = 0 ; j < dirs.size() ; j++ ) {
580// //if ( allTrue( t == dirs[j] ) ) {
581// Double dx = t[0] - dirs[j][0] ;
582// Double dy = t[1] - dirs[j][1] ;
583// Double dd = sqrt( dx * dx + dy * dy ) ;
584// //if ( allNearAbs( t, dirs[j], tol ) ) {
585// if ( dd <= tol ) {
586// adddir = false ;
587// break ;
588// }
589// }
590// if ( adddir ) {
591// dirs.push_back( t ) ;
592// indexes.push_back( i ) ;
593// }
594// }
595// uInt rowNum = dirs.size() ;
596// tout.addRow( rowNum );
597// for ( uInt i = 0 ; i < rowNum ; i++ ) {
598// TableCopy::copyRows(tout, subt, outrowCount+i, indexes[i], 1) ;
599// // Handle MX mode averaging
600// if ( avmode != "SCAN") {
601// scanColOut.put(outrowCount+i, uInt(0));
602// }
603// }
604// MDirection::ScalarColumn dircolOut ;
605// dircolOut.attach( tout, "DIRECTION" ) ;
606// for ( uInt irow = 0 ; irow < rowNum ; irow++ ) {
607// Vector<Double> t = \
608// dircolOut(outrowCount+irow).getAngle(Unit(String("rad"))).getValue() ;
609// Vector<Float> tmp;
610// specCol.get(0, tmp);
611// uInt nchan = tmp.nelements();
612// // have to do channel by channel here as MaskedArrMath
613// // doesn't have partialMedians
614// Vector<uChar> flags = flagCol.getColumn(Slicer(Slice(0)));
615// // mask spectra for different DIRECTION
616// for ( uInt jrow = 0 ; jrow < subt.nrow() ; jrow++ ) {
617// Vector<Double> direction = \
618// dircol(jrow).getAngle(Unit(String("rad"))).getValue() ;
619// //if ( t[0] != direction[0] || t[1] != direction[1] ) {
620// Double dx = t[0] - direction[0];
621// Double dy = t[1] - direction[1];
622// Double dd = sqrt(dx*dx + dy*dy);
623// //if ( !allNearAbs( t, direction, tol ) ) {
624// if ( dd > tol && in->nbeam() < 2 ) {
625// flags[jrow] = userflag ;
626// }
627// }
628// Vector<Float> outspec(nchan);
629// Vector<uChar> outflag(nchan,0);
630// Vector<Float> outtsys(1);/// @fixme when tsys is channel based
631// for (uInt i=0; i<nchan; ++i) {
632// Vector<Float> specs = specCol.getColumn(Slicer(Slice(i)));
633// MaskedArray<Float> ma = maskedArray(specs,flags);
634// outspec[i] = median(ma);
635// if ( allEQ(ma.getMask(), False) )
636// outflag[i] = userflag;// flag data
637// }
638// outtsys[0] = median(tsysCol.getColumn());
639// specColOut.put(outrowCount+irow, outspec);
640// flagColOut.put(outrowCount+irow, outflag);
641// tsysColOut.put(outrowCount+irow, outtsys);
642// Vector<Double> integ = intCol.getColumn() ;
643// MaskedArray<Double> mi = maskedArray( integ, flags ) ;
644// Double intsum = sum(mi);
645// intColOut.put(outrowCount+irow, intsum);
646// }
647// outrowCount += rowNum ;
648// ++iter;
649 }
650 return out;
651}
652
653CountedPtr< Scantable > STMath::getScantable(const CountedPtr< Scantable >& in,
654 bool droprows)
655{
656 if (insitu_) {
657 return in;
658 }
659 else {
660 // clone
661 return CountedPtr<Scantable>(new Scantable(*in, Bool(droprows)));
662 }
663}
664
665CountedPtr< Scantable > STMath::unaryOperate( const CountedPtr< Scantable >& in,
666 float val,
667 const std::string& mode,
668 bool tsys )
669{
670 CountedPtr< Scantable > out = getScantable(in, false);
671 Table& tab = out->table();
672 ArrayColumn<Float> specCol(tab,"SPECTRA");
673 ArrayColumn<Float> tsysCol(tab,"TSYS");
674 if (mode=="DIV") val = 1.0/val ;
675 else if (mode=="SUB") val *= -1.0 ;
676 for (uInt i=0; i<tab.nrow(); ++i) {
677 Vector<Float> spec;
678 Vector<Float> ts;
679 specCol.get(i, spec);
680 tsysCol.get(i, ts);
681 if (mode == "MUL" || mode == "DIV") {
682 //if (mode == "DIV") val = 1.0/val;
683 spec *= val;
684 specCol.put(i, spec);
685 if ( tsys ) {
686 ts *= val;
687 tsysCol.put(i, ts);
688 }
689 } else if ( mode == "ADD" || mode == "SUB") {
690 //if (mode == "SUB") val *= -1.0;
691 spec += val;
692 specCol.put(i, spec);
693 if ( tsys ) {
694 ts += val;
695 tsysCol.put(i, ts);
696 }
697 }
698 }
699 return out;
700}
701
702CountedPtr< Scantable > STMath::arrayOperate( const CountedPtr< Scantable >& in,
703 const std::vector<float> val,
704 const std::string& mode,
705 const std::string& opmode,
706 bool tsys )
707{
708 CountedPtr< Scantable > out ;
709 if ( opmode == "channel" ) {
710 out = arrayOperateChannel( in, val, mode, tsys ) ;
711 }
712 else if ( opmode == "row" ) {
713 out = arrayOperateRow( in, val, mode, tsys ) ;
714 }
715 else {
716 throw( AipsError( "Unknown array operation mode." ) ) ;
717 }
718 return out ;
719}
720
721CountedPtr< Scantable > STMath::arrayOperateChannel( const CountedPtr< Scantable >& in,
722 const std::vector<float> val,
723 const std::string& mode,
724 bool tsys )
725{
726 if ( val.size() == 1 ){
727 return unaryOperate( in, val[0], mode, tsys ) ;
728 }
729
730 // conformity of SPECTRA and TSYS
731 if ( tsys ) {
732 TableIterator titer(in->table(), "IFNO");
733 while ( !titer.pastEnd() ) {
734 ArrayColumn<Float> specCol( in->table(), "SPECTRA" ) ;
735 ArrayColumn<Float> tsysCol( in->table(), "TSYS" ) ;
736 Array<Float> spec = specCol.getColumn() ;
737 Array<Float> ts = tsysCol.getColumn() ;
738 if ( !spec.conform( ts ) ) {
739 throw( AipsError( "SPECTRA and TSYS must conform in shape if you want to apply operation on Tsys." ) ) ;
740 }
741 titer.next() ;
742 }
743 }
744
745 // check if all spectra in the scantable have the same number of channel
746 vector<uInt> nchans;
747 vector<uInt> ifnos = in->getIFNos() ;
748 for ( uInt i = 0 ; i < ifnos.size() ; i++ ) {
749 nchans.push_back( in->nchan( ifnos[i] ) ) ;
750 }
751 Vector<uInt> mchans( nchans ) ;
752 if ( anyNE( mchans, mchans[0] ) ) {
753 throw( AipsError("All spectra in the input scantable must have the same number of channel for vector operation." ) ) ;
754 }
755
756 // check if vector size is equal to nchan
757 Vector<Float> fact( val ) ;
758 if ( fact.nelements() != mchans[0] ) {
759 throw( AipsError("Vector size must be 1 or be same as number of channel.") ) ;
760 }
761
762 // check divided by zero
763 if ( ( mode == "DIV" ) && anyEQ( fact, (float)0.0 ) ) {
764 throw( AipsError("Divided by zero is not recommended." ) ) ;
765 }
766
767 CountedPtr< Scantable > out = getScantable(in, false);
768 Table& tab = out->table();
769 ArrayColumn<Float> specCol(tab,"SPECTRA");
770 ArrayColumn<Float> tsysCol(tab,"TSYS");
771 if (mode == "DIV") fact = (float)1.0 / fact;
772 else if (mode == "SUB") fact *= (float)-1.0 ;
773 for (uInt i=0; i<tab.nrow(); ++i) {
774 Vector<Float> spec;
775 Vector<Float> ts;
776 specCol.get(i, spec);
777 tsysCol.get(i, ts);
778 if (mode == "MUL" || mode == "DIV") {
779 //if (mode == "DIV") fact = (float)1.0 / fact;
780 spec *= fact;
781 specCol.put(i, spec);
782 if ( tsys ) {
783 ts *= fact;
784 tsysCol.put(i, ts);
785 }
786 } else if ( mode == "ADD" || mode == "SUB") {
787 //if (mode == "SUB") fact *= (float)-1.0 ;
788 spec += fact;
789 specCol.put(i, spec);
790 if ( tsys ) {
791 ts += fact;
792 tsysCol.put(i, ts);
793 }
794 }
795 }
796 return out;
797}
798
799CountedPtr< Scantable > STMath::arrayOperateRow( const CountedPtr< Scantable >& in,
800 const std::vector<float> val,
801 const std::string& mode,
802 bool tsys )
803{
804 if ( val.size() == 1 ) {
805 return unaryOperate( in, val[0], mode, tsys ) ;
806 }
807
808 // conformity of SPECTRA and TSYS
809 if ( tsys ) {
810 TableIterator titer(in->table(), "IFNO");
811 while ( !titer.pastEnd() ) {
812 ArrayColumn<Float> specCol( in->table(), "SPECTRA" ) ;
813 ArrayColumn<Float> tsysCol( in->table(), "TSYS" ) ;
814 Array<Float> spec = specCol.getColumn() ;
815 Array<Float> ts = tsysCol.getColumn() ;
816 if ( !spec.conform( ts ) ) {
817 throw( AipsError( "SPECTRA and TSYS must conform in shape if you want to apply operation on Tsys." ) ) ;
818 }
819 titer.next() ;
820 }
821 }
822
823 // check if vector size is equal to nrow
824 Vector<Float> fact( val ) ;
825 if (fact.nelements() != uInt(in->nrow())) {
826 throw( AipsError("Vector size must be 1 or be same as number of row.") ) ;
827 }
828
829 // check divided by zero
830 if ( ( mode == "DIV" ) && anyEQ( fact, (float)0.0 ) ) {
831 throw( AipsError("Divided by zero is not recommended." ) ) ;
832 }
833
834 CountedPtr< Scantable > out = getScantable(in, false);
835 Table& tab = out->table();
836 ArrayColumn<Float> specCol(tab,"SPECTRA");
837 ArrayColumn<Float> tsysCol(tab,"TSYS");
838 if (mode == "DIV") fact = (float)1.0 / fact;
839 if (mode == "SUB") fact *= (float)-1.0 ;
840 for (uInt i=0; i<tab.nrow(); ++i) {
841 Vector<Float> spec;
842 Vector<Float> ts;
843 specCol.get(i, spec);
844 tsysCol.get(i, ts);
845 if (mode == "MUL" || mode == "DIV") {
846 spec *= fact[i];
847 specCol.put(i, spec);
848 if ( tsys ) {
849 ts *= fact[i];
850 tsysCol.put(i, ts);
851 }
852 } else if ( mode == "ADD" || mode == "SUB") {
853 spec += fact[i];
854 specCol.put(i, spec);
855 if ( tsys ) {
856 ts += fact[i];
857 tsysCol.put(i, ts);
858 }
859 }
860 }
861 return out;
862}
863
864CountedPtr< Scantable > STMath::array2dOperate( const CountedPtr< Scantable >& in,
865 const std::vector< std::vector<float> > val,
866 const std::string& mode,
867 bool tsys )
868{
869 // conformity of SPECTRA and TSYS
870 if ( tsys ) {
871 TableIterator titer(in->table(), "IFNO");
872 while ( !titer.pastEnd() ) {
873 ArrayColumn<Float> specCol( in->table(), "SPECTRA" ) ;
874 ArrayColumn<Float> tsysCol( in->table(), "TSYS" ) ;
875 Array<Float> spec = specCol.getColumn() ;
876 Array<Float> ts = tsysCol.getColumn() ;
877 if ( !spec.conform( ts ) ) {
878 throw( AipsError( "SPECTRA and TSYS must conform in shape if you want to apply operation on Tsys." ) ) ;
879 }
880 titer.next() ;
881 }
882 }
883
884 // some checks
885 vector<uInt> nchans;
886 for (Int i = 0 ; i < in->nrow() ; i++) {
887 nchans.push_back((in->getSpectrum(i)).size());
888 }
889 //Vector<uInt> mchans( nchans ) ;
890 vector< Vector<Float> > facts ;
891 for ( uInt i = 0 ; i < nchans.size() ; i++ ) {
892 Vector<Float> tmp( val[i] ) ;
893 // check divided by zero
894 if ( ( mode == "DIV" ) && anyEQ( tmp, (float)0.0 ) ) {
895 throw( AipsError("Divided by zero is not recommended." ) ) ;
896 }
897 // conformity check
898 if ( tmp.nelements() != nchans[i] ) {
899 stringstream ss ;
900 ss << "Row " << i << ": Vector size must be same as number of channel." ;
901 throw( AipsError( ss.str() ) ) ;
902 }
903 facts.push_back( tmp ) ;
904 }
905
906
907 CountedPtr< Scantable > out = getScantable(in, false);
908 Table& tab = out->table();
909 ArrayColumn<Float> specCol(tab,"SPECTRA");
910 ArrayColumn<Float> tsysCol(tab,"TSYS");
911 for (uInt i=0; i<tab.nrow(); ++i) {
912 Vector<Float> fact = facts[i] ;
913 Vector<Float> spec;
914 Vector<Float> ts;
915 specCol.get(i, spec);
916 tsysCol.get(i, ts);
917 if (mode == "MUL" || mode == "DIV") {
918 if (mode == "DIV") fact = (float)1.0 / fact;
919 spec *= fact;
920 specCol.put(i, spec);
921 if ( tsys ) {
922 ts *= fact;
923 tsysCol.put(i, ts);
924 }
925 } else if ( mode == "ADD" || mode == "SUB") {
926 if (mode == "SUB") fact *= (float)-1.0 ;
927 spec += fact;
928 specCol.put(i, spec);
929 if ( tsys ) {
930 ts += fact;
931 tsysCol.put(i, ts);
932 }
933 }
934 }
935 return out;
936}
937
938CountedPtr<Scantable> STMath::binaryOperate(const CountedPtr<Scantable>& left,
939 const CountedPtr<Scantable>& right,
940 const std::string& mode)
941{
942 bool insitu = insitu_;
943 if ( ! left->conformant(*right) ) {
944 throw(AipsError("'left' and 'right' scantables are not conformant."));
945 }
946 setInsitu(false);
947 CountedPtr< Scantable > out = getScantable(left, false);
948 setInsitu(insitu);
949 Table& tout = out->table();
950 Block<String> coln(5);
951 coln[0] = "SCANNO"; coln[1] = "CYCLENO"; coln[2] = "BEAMNO";
952 coln[3] = "IFNO"; coln[4] = "POLNO";
953 Table tmpl = tout.sort(coln);
954 Table tmpr = right->table().sort(coln);
955 ArrayColumn<Float> lspecCol(tmpl,"SPECTRA");
956 ROArrayColumn<Float> rspecCol(tmpr,"SPECTRA");
957 ArrayColumn<uChar> lflagCol(tmpl,"FLAGTRA");
958 ROArrayColumn<uChar> rflagCol(tmpr,"FLAGTRA");
959
960 for (uInt i=0; i<tout.nrow(); ++i) {
961 Vector<Float> lspecvec, rspecvec;
962 Vector<uChar> lflagvec, rflagvec;
963 lspecvec = lspecCol(i); rspecvec = rspecCol(i);
964 lflagvec = lflagCol(i); rflagvec = rflagCol(i);
965 MaskedArray<Float> mleft = maskedArray(lspecvec, lflagvec);
966 MaskedArray<Float> mright = maskedArray(rspecvec, rflagvec);
967 if (mode == "ADD") {
968 mleft += mright;
969 } else if ( mode == "SUB") {
970 mleft -= mright;
971 } else if ( mode == "MUL") {
972 mleft *= mright;
973 } else if ( mode == "DIV") {
974 mleft /= mright;
975 } else {
976 throw(AipsError("Illegal binary operator"));
977 }
978 lspecCol.put(i, mleft.getArray());
979 }
980 return out;
981}
982
983
984
985MaskedArray<Float> STMath::maskedArray( const Vector<Float>& s,
986 const Vector<uChar>& f)
987{
988 Vector<Bool> mask;
989 mask.resize(f.shape());
990 convertArray(mask, f);
991 return MaskedArray<Float>(s,!mask);
992}
993
994MaskedArray<Double> STMath::maskedArray( const Vector<Double>& s,
995 const Vector<uChar>& f)
996{
997 Vector<Bool> mask;
998 mask.resize(f.shape());
999 convertArray(mask, f);
1000 return MaskedArray<Double>(s,!mask);
1001}
1002
1003Vector<uChar> STMath::flagsFromMA(const MaskedArray<Float>& ma)
1004{
1005 const Vector<Bool>& m = ma.getMask();
1006 Vector<uChar> flags(m.shape());
1007 convertArray(flags, !m);
1008 return flags;
1009}
1010
1011CountedPtr< Scantable > STMath::autoQuotient( const CountedPtr< Scantable >& in,
1012 const std::string & mode,
1013 bool preserve )
1014{
1015 /// @todo make other modes available
1016 /// modes should be "nearest", "pair"
1017 // make this operation non insitu
1018 (void) mode; //currently unused
1019 const Table& tin = in->table();
1020 Table ons = tin(tin.col("SRCTYPE") == Int(SrcType::PSON));
1021 Table offs = tin(tin.col("SRCTYPE") == Int(SrcType::PSOFF));
1022 if ( offs.nrow() == 0 )
1023 throw(AipsError("No 'off' scans present."));
1024 // put all "on" scans into output table
1025
1026 bool insitu = insitu_;
1027 setInsitu(false);
1028 CountedPtr< Scantable > out = getScantable(in, true);
1029 setInsitu(insitu);
1030 Table& tout = out->table();
1031
1032 TableCopy::copyRows(tout, ons);
1033 TableRow row(tout);
1034 ROScalarColumn<Double> offtimeCol(offs, "TIME");
1035 ArrayColumn<Float> outspecCol(tout, "SPECTRA");
1036 ROArrayColumn<Float> outtsysCol(tout, "TSYS");
1037 ArrayColumn<uChar> outflagCol(tout, "FLAGTRA");
1038 for (uInt i=0; i < tout.nrow(); ++i) {
1039 const TableRecord& rec = row.get(i);
1040 Double ontime = rec.asDouble("TIME");
1041 Table presel = offs(offs.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
1042 && offs.col("IFNO") == Int(rec.asuInt("IFNO"))
1043 && offs.col("POLNO") == Int(rec.asuInt("POLNO")) );
1044 ROScalarColumn<Double> offtimeCol(presel, "TIME");
1045
1046 Double mindeltat = min(abs(offtimeCol.getColumn() - ontime));
1047 // Timestamp may vary within a cycle ???!!!
1048 // increase this by 0.01 sec in case of rounding errors...
1049 // There might be a better way to do this.
1050 // fix to this fix. TIME is MJD, so 1.0d not 1.0s
1051 mindeltat += 0.01/24./60./60.;
1052 Table sel = presel( abs(presel.col("TIME")-ontime) <= mindeltat);
1053
1054 if ( sel.nrow() < 1 ) {
1055 throw(AipsError("No closest in time found... This could be a rounding "
1056 "issue. Try quotient instead."));
1057 }
1058 TableRow offrow(sel);
1059 const TableRecord& offrec = offrow.get(0);//should only be one row
1060 RORecordFieldPtr< Array<Float> > specoff(offrec, "SPECTRA");
1061 RORecordFieldPtr< Array<Float> > tsysoff(offrec, "TSYS");
1062 RORecordFieldPtr< Array<uChar> > flagoff(offrec, "FLAGTRA");
1063 /// @fixme this assumes tsys is a scalar not vector
1064 Float tsysoffscalar = (*tsysoff)(IPosition(1,0));
1065 Vector<Float> specon, tsyson;
1066 outtsysCol.get(i, tsyson);
1067 outspecCol.get(i, specon);
1068 Vector<uChar> flagon;
1069 outflagCol.get(i, flagon);
1070 MaskedArray<Float> mon = maskedArray(specon, flagon);
1071 MaskedArray<Float> moff = maskedArray(*specoff, *flagoff);
1072 MaskedArray<Float> quot = (tsysoffscalar * mon / moff);
1073 if (preserve) {
1074 quot -= tsysoffscalar;
1075 } else {
1076 quot -= tsyson[0];
1077 }
1078 outspecCol.put(i, quot.getArray());
1079 outflagCol.put(i, flagsFromMA(quot));
1080 }
1081 // renumber scanno
1082 TableIterator it(tout, "SCANNO");
1083 uInt i = 0;
1084 while ( !it.pastEnd() ) {
1085 Table t = it.table();
1086 TableVector<uInt> vec(t, "SCANNO");
1087 vec = i;
1088 ++i;
1089 ++it;
1090 }
1091 return out;
1092}
1093
1094
1095CountedPtr< Scantable > STMath::quotient( const CountedPtr< Scantable > & on,
1096 const CountedPtr< Scantable > & off,
1097 bool preserve )
1098{
1099 bool insitu = insitu_;
1100 if ( ! on->conformant(*off) ) {
1101 throw(AipsError("'on' and 'off' scantables are not conformant."));
1102 }
1103 setInsitu(false);
1104 CountedPtr< Scantable > out = getScantable(on, false);
1105 setInsitu(insitu);
1106 Table& tout = out->table();
1107 const Table& toff = off->table();
1108 TableIterator sit(tout, "SCANNO");
1109 TableIterator s2it(toff, "SCANNO");
1110 while ( !sit.pastEnd() ) {
1111 Table ton = sit.table();
1112 TableRow row(ton);
1113 Table t = s2it.table();
1114 ArrayColumn<Float> outspecCol(ton, "SPECTRA");
1115 ROArrayColumn<Float> outtsysCol(ton, "TSYS");
1116 ArrayColumn<uChar> outflagCol(ton, "FLAGTRA");
1117 for (uInt i=0; i < ton.nrow(); ++i) {
1118 const TableRecord& rec = row.get(i);
1119 Table offsel = t( t.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
1120 && t.col("IFNO") == Int(rec.asuInt("IFNO"))
1121 && t.col("POLNO") == Int(rec.asuInt("POLNO")) );
1122 if ( offsel.nrow() == 0 )
1123 throw AipsError("STMath::quotient: no matching off");
1124 TableRow offrow(offsel);
1125 const TableRecord& offrec = offrow.get(0);//should be ncycles - take first
1126 RORecordFieldPtr< Array<Float> > specoff(offrec, "SPECTRA");
1127 RORecordFieldPtr< Array<Float> > tsysoff(offrec, "TSYS");
1128 RORecordFieldPtr< Array<uChar> > flagoff(offrec, "FLAGTRA");
1129 Float tsysoffscalar = (*tsysoff)(IPosition(1,0));
1130 Vector<Float> specon, tsyson;
1131 outtsysCol.get(i, tsyson);
1132 outspecCol.get(i, specon);
1133 Vector<uChar> flagon;
1134 outflagCol.get(i, flagon);
1135 MaskedArray<Float> mon = maskedArray(specon, flagon);
1136 MaskedArray<Float> moff = maskedArray(*specoff, *flagoff);
1137 MaskedArray<Float> quot = (tsysoffscalar * mon / moff);
1138 if (preserve) {
1139 quot -= tsysoffscalar;
1140 } else {
1141 quot -= tsyson[0];
1142 }
1143 outspecCol.put(i, quot.getArray());
1144 outflagCol.put(i, flagsFromMA(quot));
1145 }
1146 ++sit;
1147 ++s2it;
1148 // take the first off for each on scan which doesn't have a
1149 // matching off scan
1150 // non <= noff: matching pairs, non > noff matching pairs then first off
1151 if ( s2it.pastEnd() ) s2it.reset();
1152 }
1153 return out;
1154}
1155
1156// dototalpower (migration of GBTIDL procedure dototalpower.pro)
1157// calibrate the CAL on-off pair. It calculate Tsys and average CAL on-off subintegrations
1158// do it for each cycles in a specific scan.
1159CountedPtr< Scantable > STMath::dototalpower( const CountedPtr< Scantable >& calon,
1160 const CountedPtr< Scantable >& caloff, Float tcal )
1161{
1162 if ( ! calon->conformant(*caloff) ) {
1163 throw(AipsError("'CAL on' and 'CAL off' scantables are not conformant."));
1164 }
1165 setInsitu(false);
1166 CountedPtr< Scantable > out = getScantable(caloff, false);
1167 Table& tout = out->table();
1168 const Table& tcon = calon->table();
1169 Vector<Float> tcalout;
1170
1171 std::map<uInt,uInt> tcalIdToRecNoMap;
1172 const Table& calOffTcalTable = caloff->tcal().table();
1173 {
1174 ROScalarColumn<uInt> calOffTcalTable_IDcol(calOffTcalTable, "ID");
1175 const Vector<uInt> tcalIds(calOffTcalTable_IDcol.getColumn());
1176 size_t tcalIdsEnd = tcalIds.nelements();
1177 for (uInt i = 0; i < tcalIdsEnd; i++) {
1178 tcalIdToRecNoMap[tcalIds[i]] = i;
1179 }
1180 }
1181 ROArrayColumn<Float> calOffTcalTable_TCALcol(calOffTcalTable, "TCAL");
1182
1183 if ( tout.nrow() != tcon.nrow() ) {
1184 throw(AipsError("Mismatch in number of rows to form cal on - off pair."));
1185 }
1186 // iteration by scanno or cycle no.
1187 TableIterator sit(tout, "SCANNO");
1188 TableIterator s2it(tcon, "SCANNO");
1189 while ( !sit.pastEnd() ) {
1190 Table toff = sit.table();
1191 TableRow row(toff);
1192 Table t = s2it.table();
1193 ScalarColumn<Double> outintCol(toff, "INTERVAL");
1194 ArrayColumn<Float> outspecCol(toff, "SPECTRA");
1195 ArrayColumn<Float> outtsysCol(toff, "TSYS");
1196 ArrayColumn<uChar> outflagCol(toff, "FLAGTRA");
1197 ROScalarColumn<uInt> outtcalIdCol(toff, "TCAL_ID");
1198 ROScalarColumn<uInt> outpolCol(toff, "POLNO");
1199 ROScalarColumn<Double> onintCol(t, "INTERVAL");
1200 ROArrayColumn<Float> onspecCol(t, "SPECTRA");
1201 ROArrayColumn<Float> ontsysCol(t, "TSYS");
1202 ROArrayColumn<uChar> onflagCol(t, "FLAGTRA");
1203 //ROScalarColumn<uInt> ontcalIdCol(t, "TCAL_ID");
1204
1205 for (uInt i=0; i < toff.nrow(); ++i) {
1206 //skip these checks -> assumes the data order are the same between the cal on off pairs
1207 //
1208 Vector<Float> specCalon, specCaloff;
1209 // to store scalar (mean) tsys
1210 Vector<Float> tsysout(1);
1211 uInt tcalId, polno;
1212 Double offint, onint;
1213 outpolCol.get(i, polno);
1214 outspecCol.get(i, specCaloff);
1215 onspecCol.get(i, specCalon);
1216 Vector<uChar> flagCaloff, flagCalon;
1217 outflagCol.get(i, flagCaloff);
1218 onflagCol.get(i, flagCalon);
1219 outtcalIdCol.get(i, tcalId);
1220 outintCol.get(i, offint);
1221 onintCol.get(i, onint);
1222 // caluculate mean Tsys
1223 uInt nchan = specCaloff.nelements();
1224 // percentage of edge cut off
1225 uInt pc = 10;
1226 uInt bchan = nchan/pc;
1227 uInt echan = nchan-bchan;
1228
1229 Slicer chansl(IPosition(1,bchan-1), IPosition(1,echan-1), IPosition(1,1),Slicer::endIsLast);
1230 Vector<Float> testsubsp = specCaloff(chansl);
1231 MaskedArray<Float> spoff = maskedArray( specCaloff(chansl),flagCaloff(chansl) );
1232 MaskedArray<Float> spon = maskedArray( specCalon(chansl),flagCalon(chansl) );
1233 MaskedArray<Float> spdiff = spon-spoff;
1234 uInt noff = spoff.nelementsValid();
1235 //uInt non = spon.nelementsValid();
1236 uInt ndiff = spdiff.nelementsValid();
1237 Float meantsys;
1238
1239/**
1240 Double subspec, subdiff;
1241 uInt usednchan;
1242 subspec = 0;
1243 subdiff = 0;
1244 usednchan = 0;
1245 for(uInt k=(bchan-1); k<echan; k++) {
1246 subspec += specCaloff[k];
1247 subdiff += static_cast<Double>(specCalon[k]-specCaloff[k]);
1248 ++usednchan;
1249 }
1250**/
1251 // get tcal if input tcal <= 0
1252 Float tcalUsed;
1253 tcalUsed = tcal;
1254 if ( tcal <= 0.0 ) {
1255 uInt tcalRecNo = tcalIdToRecNoMap[tcalId];
1256 calOffTcalTable_TCALcol.get(tcalRecNo, tcalout);
1257// if (polno<=3) {
1258// tcalUsed = tcalout[polno];
1259// }
1260// else {
1261// tcalUsed = tcalout[0];
1262// }
1263 if ( tcalout.size() == 1 )
1264 tcalUsed = tcalout[0] ;
1265 else if ( tcalout.size() == nchan )
1266 tcalUsed = mean(tcalout) ;
1267 else {
1268 uInt ipol = polno ;
1269 if ( ipol > 3 ) ipol = 0 ;
1270 tcalUsed = tcalout[ipol] ;
1271 }
1272 }
1273
1274 Float meanoff;
1275 Float meandiff;
1276 if (noff && ndiff) {
1277 //Debug
1278 //if(noff!=ndiff) cerr<<"noff and ndiff is not equal"<<endl;
1279 //LogIO os( LogOrigin( "STMath", "dototalpower()", WHERE ) ) ;
1280 //if(noff!=ndiff) os<<"noff and ndiff is not equal"<<LogIO::POST;
1281 meanoff = sum(spoff)/noff;
1282 meandiff = sum(spdiff)/ndiff;
1283 meantsys= (meanoff/meandiff )*tcalUsed + tcalUsed/2;
1284 }
1285 else {
1286 meantsys=1;
1287 }
1288
1289 tsysout[0] = Float(meantsys);
1290 MaskedArray<Float> mcaloff = maskedArray(specCaloff, flagCaloff);
1291 MaskedArray<Float> mcalon = maskedArray(specCalon, flagCalon);
1292 MaskedArray<Float> sig = Float(0.5) * (mcaloff + mcalon);
1293 //uInt ncaloff = mcaloff.nelementsValid();
1294 //uInt ncalon = mcalon.nelementsValid();
1295
1296 outintCol.put(i, offint+onint);
1297 outspecCol.put(i, sig.getArray());
1298 outflagCol.put(i, flagsFromMA(sig));
1299 outtsysCol.put(i, tsysout);
1300 }
1301 ++sit;
1302 ++s2it;
1303 }
1304 return out;
1305}
1306
1307//dosigref - migrated from GBT IDL's dosigref.pro, do calibration of position switch
1308// observatiions.
1309// input: sig and ref scantables, and an optional boxcar smoothing width(default width=0,
1310// no smoothing).
1311// output: resultant scantable [= (sig-ref/ref)*tsys]
1312CountedPtr< Scantable > STMath::dosigref( const CountedPtr < Scantable >& sig,
1313 const CountedPtr < Scantable >& ref,
1314 int smoothref,
1315 casa::Float tsysv,
1316 casa::Float tau )
1317{
1318 LogIO os( casa::LogOrigin( "STMath", "dosigref()"));
1319if ( ! ref->conformant(*sig) ) {
1320 throw(AipsError("'sig' and 'ref' scantables are not conformant."));
1321 }
1322 setInsitu(false);
1323 CountedPtr< Scantable > out = getScantable(sig, false);
1324 CountedPtr< Scantable > smref;
1325 if ( smoothref > 1 ) {
1326 float fsmoothref = static_cast<float>(smoothref);
1327 std::string inkernel = "boxcar";
1328 smref = smooth(ref, inkernel, fsmoothref );
1329 ostringstream oss;
1330 os <<"Applied smoothing of "<<fsmoothref<<" on the reference."
1331 << LogIO::POST;
1332 }
1333 else {
1334 smref = ref;
1335 }
1336 Table& tout = out->table();
1337 const Table& tref = smref->table();
1338 if ( tout.nrow() != tref.nrow() ) {
1339 throw(AipsError("Mismatch in number of rows to form on-source and reference pair."));
1340 }
1341 // iteration by scanno? or cycle no.
1342 TableIterator sit(tout, "SCANNO");
1343 TableIterator s2it(tref, "SCANNO");
1344 while ( !sit.pastEnd() ) {
1345 Table ton = sit.table();
1346 Table t = s2it.table();
1347 ScalarColumn<Double> outintCol(ton, "INTERVAL");
1348 ArrayColumn<Float> outspecCol(ton, "SPECTRA");
1349 ArrayColumn<Float> outtsysCol(ton, "TSYS");
1350 ArrayColumn<uChar> outflagCol(ton, "FLAGTRA");
1351 ArrayColumn<Float> refspecCol(t, "SPECTRA");
1352 ROScalarColumn<Double> refintCol(t, "INTERVAL");
1353 ROArrayColumn<Float> reftsysCol(t, "TSYS");
1354 ArrayColumn<uChar> refflagCol(t, "FLAGTRA");
1355 ROScalarColumn<Float> refelevCol(t, "ELEVATION");
1356 for (uInt i=0; i < ton.nrow(); ++i) {
1357
1358 Double onint, refint;
1359 Vector<Float> specon, specref;
1360 // to store scalar (mean) tsys
1361 Vector<Float> tsysref;
1362 outintCol.get(i, onint);
1363 refintCol.get(i, refint);
1364 outspecCol.get(i, specon);
1365 refspecCol.get(i, specref);
1366 Vector<uChar> flagref, flagon;
1367 outflagCol.get(i, flagon);
1368 refflagCol.get(i, flagref);
1369 reftsysCol.get(i, tsysref);
1370
1371 Float tsysrefscalar;
1372 if ( tsysv > 0.0 ) {
1373 ostringstream oss;
1374 Float elev;
1375 refelevCol.get(i, elev);
1376 os << "user specified Tsys = " << tsysv;
1377 // do recalc elevation if EL = 0
1378 if ( elev == 0 ) {
1379 throw(AipsError("EL=0, elevation data is missing."));
1380 } else {
1381 if ( tau <= 0.0 ) {
1382 throw(AipsError("Valid tau is not supplied."));
1383 } else {
1384 tsysrefscalar = tsysv * exp(tau/elev);
1385 }
1386 }
1387 os << ", corrected (for El) tsys= "<<tsysrefscalar;
1388 }
1389 else {
1390 tsysrefscalar = tsysref[0];
1391 }
1392 //get quotient spectrum
1393 MaskedArray<Float> mref = maskedArray(specref, flagref);
1394 MaskedArray<Float> mon = maskedArray(specon, flagon);
1395 MaskedArray<Float> specres = tsysrefscalar*((mon - mref)/mref);
1396 Double resint = onint*refint*smoothref/(onint+refint*smoothref);
1397
1398 //Debug
1399 //cerr<<"Tsys used="<<tsysrefscalar<<endl;
1400 //LogIO os( LogOrigin( "STMath", "dosigref", WHERE ) ) ;
1401 //os<<"Tsys used="<<tsysrefscalar<<LogIO::POST;
1402 // fill the result, replay signal tsys by reference tsys
1403 outintCol.put(i, resint);
1404 outspecCol.put(i, specres.getArray());
1405 outflagCol.put(i, flagsFromMA(specres));
1406 outtsysCol.put(i, tsysref);
1407 }
1408 ++sit;
1409 ++s2it;
1410 }
1411
1412 out->setFluxUnit("K");
1413
1414 return out;
1415}
1416
1417CountedPtr< Scantable > STMath::donod(const casa::CountedPtr<Scantable>& s,
1418 const std::vector<int>& scans,
1419 int smoothref,
1420 casa::Float tsysv,
1421 casa::Float tau,
1422 casa::Float tcal )
1423
1424{
1425 setInsitu(false);
1426 LogIO os( casa::LogOrigin( "STMath", "donod()"));
1427 STSelector sel;
1428 std::vector<int> scan1, scan2, beams, types;
1429 std::vector< vector<int> > scanpair;
1430 //std::vector<string> calstate;
1431 std::vector<int> calstate;
1432 String msg;
1433
1434 CountedPtr< Scantable > s1b1on, s1b1off, s1b2on, s1b2off;
1435 CountedPtr< Scantable > s2b1on, s2b1off, s2b2on, s2b2off;
1436
1437 std::vector< CountedPtr< Scantable > > sctables;
1438 sctables.push_back(s1b1on);
1439 sctables.push_back(s1b1off);
1440 sctables.push_back(s1b2on);
1441 sctables.push_back(s1b2off);
1442 sctables.push_back(s2b1on);
1443 sctables.push_back(s2b1off);
1444 sctables.push_back(s2b2on);
1445 sctables.push_back(s2b2off);
1446
1447 //check scanlist
1448 int n=s->checkScanInfo(scans);
1449 if (n==1) {
1450 throw(AipsError("Incorrect scan pairs. "));
1451 }
1452
1453 // Assume scans contain only a pair of consecutive scan numbers.
1454 // It is assumed that first beam, b1, is on target.
1455 // There is no check if the first beam is on or not.
1456 if ( scans.size()==1 ) {
1457 scan1.push_back(scans[0]);
1458 scan2.push_back(scans[0]+1);
1459 } else if ( scans.size()==2 ) {
1460 scan1.push_back(scans[0]);
1461 scan2.push_back(scans[1]);
1462 } else {
1463 if ( scans.size()%2 == 0 ) {
1464 for (uInt i=0; i<scans.size(); i++) {
1465 if (i%2 == 0) {
1466 scan1.push_back(scans[i]);
1467 }
1468 else {
1469 scan2.push_back(scans[i]);
1470 }
1471 }
1472 } else {
1473 throw(AipsError("Odd numbers of scans, cannot form pairs."));
1474 }
1475 }
1476 scanpair.push_back(scan1);
1477 scanpair.push_back(scan2);
1478 //calstate.push_back("*calon");
1479 //calstate.push_back("*[^calon]");
1480 calstate.push_back(SrcType::NODCAL);
1481 calstate.push_back(SrcType::NOD);
1482 CountedPtr< Scantable > ws = getScantable(s, false);
1483 uInt l=0;
1484 while ( l < sctables.size() ) {
1485 for (uInt i=0; i < 2; i++) {
1486 for (uInt j=0; j < 2; j++) {
1487 for (uInt k=0; k < 2; k++) {
1488 sel.reset();
1489 sel.setScans(scanpair[i]);
1490 //sel.setName(calstate[k]);
1491 types.clear();
1492 types.push_back(calstate[k]);
1493 sel.setTypes(types);
1494 beams.clear();
1495 beams.push_back(j);
1496 sel.setBeams(beams);
1497 ws->setSelection(sel);
1498 sctables[l]= getScantable(ws, false);
1499 l++;
1500 }
1501 }
1502 }
1503 }
1504
1505 // replace here by splitData or getData functionality
1506 CountedPtr< Scantable > sig1;
1507 CountedPtr< Scantable > ref1;
1508 CountedPtr< Scantable > sig2;
1509 CountedPtr< Scantable > ref2;
1510 CountedPtr< Scantable > calb1;
1511 CountedPtr< Scantable > calb2;
1512
1513 msg=String("Processing dototalpower for subset of the data");
1514 os << msg << LogIO::POST;
1515 // Debug for IRC CS data
1516 //float tcal1=7.0;
1517 //float tcal2=4.0;
1518 sig1 = dototalpower(sctables[0], sctables[1], tcal=tcal);
1519 ref1 = dototalpower(sctables[2], sctables[3], tcal=tcal);
1520 ref2 = dototalpower(sctables[4], sctables[5], tcal=tcal);
1521 sig2 = dototalpower(sctables[6], sctables[7], tcal=tcal);
1522
1523 // correction of user-specified tsys for elevation here
1524
1525 // dosigref calibration
1526 msg=String("Processing dosigref for subset of the data");
1527 os << msg << endl;
1528 calb1=dosigref(sig1,ref2,smoothref,tsysv,tau);
1529 calb2=dosigref(sig2,ref1,smoothref,tsysv,tau);
1530
1531 // iteration by scanno or cycle no.
1532 Table& tcalb1 = calb1->table();
1533 Table& tcalb2 = calb2->table();
1534 TableIterator sit(tcalb1, "SCANNO");
1535 TableIterator s2it(tcalb2, "SCANNO");
1536 while ( !sit.pastEnd() ) {
1537 Table t1 = sit.table();
1538 Table t2= s2it.table();
1539 ArrayColumn<Float> outspecCol(t1, "SPECTRA");
1540 ArrayColumn<Float> outtsysCol(t1, "TSYS");
1541 ArrayColumn<uChar> outflagCol(t1, "FLAGTRA");
1542 ScalarColumn<Double> outintCol(t1, "INTERVAL");
1543 ArrayColumn<Float> t2specCol(t2, "SPECTRA");
1544 ROArrayColumn<Float> t2tsysCol(t2, "TSYS");
1545 ArrayColumn<uChar> t2flagCol(t2, "FLAGTRA");
1546 ROScalarColumn<Double> t2intCol(t2, "INTERVAL");
1547 for (uInt i=0; i < t1.nrow(); ++i) {
1548 Vector<Float> spec1, spec2;
1549 // to store scalar (mean) tsys
1550 Vector<Float> tsys1, tsys2;
1551 Vector<uChar> flag1, flag2;
1552 Double tint1, tint2;
1553 outspecCol.get(i, spec1);
1554 t2specCol.get(i, spec2);
1555 outflagCol.get(i, flag1);
1556 t2flagCol.get(i, flag2);
1557 outtsysCol.get(i, tsys1);
1558 t2tsysCol.get(i, tsys2);
1559 outintCol.get(i, tint1);
1560 t2intCol.get(i, tint2);
1561 // average
1562 // assume scalar tsys for weights
1563 Float wt1, wt2, tsyssq1, tsyssq2;
1564 tsyssq1 = tsys1[0]*tsys1[0];
1565 tsyssq2 = tsys2[0]*tsys2[0];
1566 wt1 = Float(tint1)/tsyssq1;
1567 wt2 = Float(tint2)/tsyssq2;
1568 Float invsumwt=1/(wt1+wt2);
1569 MaskedArray<Float> mspec1 = maskedArray(spec1, flag1);
1570 MaskedArray<Float> mspec2 = maskedArray(spec2, flag2);
1571 MaskedArray<Float> avspec = invsumwt * (wt1*mspec1 + wt2*mspec2);
1572 //Array<Float> avtsys = Float(0.5) * (tsys1 + tsys2);
1573 // cerr<< "Tsys1="<<tsys1<<" Tsys2="<<tsys2<<endl;
1574 // LogIO os( LogOrigin( "STMath", "donod", WHERE ) ) ;
1575 // os<< "Tsys1="<<tsys1<<" Tsys2="<<tsys2<<LogIO::POST;
1576 tsys1[0] = sqrt(tsyssq1 + tsyssq2);
1577 Array<Float> avtsys = tsys1;
1578
1579 outspecCol.put(i, avspec.getArray());
1580 outflagCol.put(i, flagsFromMA(avspec));
1581 outtsysCol.put(i, avtsys);
1582 }
1583 ++sit;
1584 ++s2it;
1585 }
1586
1587 calb1->setFluxUnit("K");
1588
1589 return calb1;
1590}
1591
1592//GBTIDL version of frequency switched data calibration
1593CountedPtr< Scantable > STMath::dofs( const CountedPtr< Scantable >& s,
1594 const std::vector<int>& scans,
1595 int smoothref,
1596 casa::Float tsysv,
1597 casa::Float tau,
1598 casa::Float tcal )
1599{
1600
1601
1602 (void) scans; //currently unused
1603 STSelector sel;
1604 CountedPtr< Scantable > ws = getScantable(s, false);
1605 CountedPtr< Scantable > sig, sigwcal, ref, refwcal;
1606 CountedPtr< Scantable > calsig, calref, out, out1, out2;
1607 Bool nofold=False;
1608 vector<int> types ;
1609
1610 //split the data
1611 //sel.setName("*_fs");
1612 types.push_back( SrcType::FSON ) ;
1613 sel.setTypes( types ) ;
1614 ws->setSelection(sel);
1615 sig = getScantable(ws,false);
1616 sel.reset();
1617 types.clear() ;
1618 //sel.setName("*_fs_calon");
1619 types.push_back( SrcType::FONCAL ) ;
1620 sel.setTypes( types ) ;
1621 ws->setSelection(sel);
1622 sigwcal = getScantable(ws,false);
1623 sel.reset();
1624 types.clear() ;
1625 //sel.setName("*_fsr");
1626 types.push_back( SrcType::FSOFF ) ;
1627 sel.setTypes( types ) ;
1628 ws->setSelection(sel);
1629 ref = getScantable(ws,false);
1630 sel.reset();
1631 types.clear() ;
1632 //sel.setName("*_fsr_calon");
1633 types.push_back( SrcType::FOFFCAL ) ;
1634 sel.setTypes( types ) ;
1635 ws->setSelection(sel);
1636 refwcal = getScantable(ws,false);
1637 sel.reset() ;
1638 types.clear() ;
1639
1640 calsig = dototalpower(sigwcal, sig, tcal=tcal);
1641 calref = dototalpower(refwcal, ref, tcal=tcal);
1642
1643 out1=dosigref(calsig,calref,smoothref,tsysv,tau);
1644 out2=dosigref(calref,calsig,smoothref,tsysv,tau);
1645
1646 Table& tabout1=out1->table();
1647 Table& tabout2=out2->table();
1648 ROScalarColumn<uInt> freqidCol1(tabout1, "FREQ_ID");
1649 ScalarColumn<uInt> freqidCol2(tabout2, "FREQ_ID");
1650 ROArrayColumn<Float> specCol(tabout2, "SPECTRA");
1651 Vector<Float> spec; specCol.get(0, spec);
1652 uInt nchan = spec.nelements();
1653 uInt freqid1; freqidCol1.get(0,freqid1);
1654 uInt freqid2; freqidCol2.get(0,freqid2);
1655 Double rp1, rp2, rv1, rv2, inc1, inc2;
1656 out1->frequencies().getEntry(rp1, rv1, inc1, freqid1);
1657 out2->frequencies().getEntry(rp2, rv2, inc2, freqid2);
1658 //cerr << out1->frequencies().table().nrow() << " " << out2->frequencies().table().nrow() << endl ;
1659 //LogIO os( LogOrigin( "STMath", "dofs()", WHERE ) ) ;
1660 //os << out1->frequencies().table().nrow() << " " << out2->frequencies().table().nrow() << LogIO::POST ;
1661 if (rp1==rp2) {
1662 Double foffset = rv1 - rv2;
1663 uInt choffset = static_cast<uInt>(foffset/abs(inc2));
1664 if (choffset >= nchan) {
1665 //cerr<<"out-band frequency switching, no folding"<<endl;
1666 LogIO os( LogOrigin( "STMath", "dofs()", WHERE ) ) ;
1667 os<<"out-band frequency switching, no folding"<<LogIO::POST;
1668 nofold = True;
1669 }
1670 }
1671
1672 if (nofold) {
1673 std::vector< CountedPtr< Scantable > > tabs;
1674 tabs.push_back(out1);
1675 tabs.push_back(out2);
1676 out = merge(tabs);
1677 }
1678 else {
1679 //out = out1;
1680 Double choffset = ( rv1 - rv2 ) / inc2 ;
1681 out = dofold( out1, out2, choffset ) ;
1682 }
1683
1684 out->setFluxUnit("K");
1685
1686 return out;
1687}
1688
1689CountedPtr<Scantable> STMath::dofold( const CountedPtr<Scantable> &sig,
1690 const CountedPtr<Scantable> &ref,
1691 Double choffset,
1692 Double choffset2 )
1693{
1694 LogIO os( LogOrigin( "STMath", "dofold", WHERE ) ) ;
1695 os << "choffset=" << choffset << " choffset2=" << choffset2 << LogIO::POST ;
1696
1697 // output scantable
1698 CountedPtr<Scantable> out = getScantable( sig, false ) ;
1699
1700 // separate choffset to integer part and decimal part
1701 Int ioffset = (Int)choffset ;
1702 Double doffset = choffset - ioffset ;
1703 Int ioffset2 = (Int)choffset2 ;
1704 Double doffset2 = choffset2 - ioffset2 ;
1705 os << "ioffset=" << ioffset << " doffset=" << doffset << LogIO::POST ;
1706 os << "ioffset2=" << ioffset2 << " doffset2=" << doffset2 << LogIO::POST ;
1707
1708 // get column
1709 ROArrayColumn<Float> specCol1( sig->table(), "SPECTRA" ) ;
1710 ROArrayColumn<Float> specCol2( ref->table(), "SPECTRA" ) ;
1711 ROArrayColumn<Float> tsysCol1( sig->table(), "TSYS" ) ;
1712 ROArrayColumn<Float> tsysCol2( ref->table(), "TSYS" ) ;
1713 ROArrayColumn<uChar> flagCol1( sig->table(), "FLAGTRA" ) ;
1714 ROArrayColumn<uChar> flagCol2( ref->table(), "FLAGTRA" ) ;
1715 ROScalarColumn<Double> mjdCol1( sig->table(), "TIME" ) ;
1716 ROScalarColumn<Double> mjdCol2( ref->table(), "TIME" ) ;
1717 ROScalarColumn<Double> intervalCol1( sig->table(), "INTERVAL" ) ;
1718 ROScalarColumn<Double> intervalCol2( ref->table(), "INTERVAL" ) ;
1719
1720 // check
1721 if ( ioffset == 0 ) {
1722 LogIO os( LogOrigin( "STMath", "dofold()", WHERE ) ) ;
1723 os << "channel offset is zero, no folding" << LogIO::POST ;
1724 return out ;
1725 }
1726 int nchan = ref->nchan() ;
1727 if ( abs(ioffset) >= nchan ) {
1728 LogIO os( LogOrigin( "STMath", "dofold()", WHERE ) ) ;
1729 os << "out-band frequency switching, no folding" << LogIO::POST ;
1730 return out ;
1731 }
1732
1733 // attach column for output scantable
1734 ArrayColumn<Float> specColOut( out->table(), "SPECTRA" ) ;
1735 ArrayColumn<uChar> flagColOut( out->table(), "FLAGTRA" ) ;
1736 ArrayColumn<Float> tsysColOut( out->table(), "TSYS" ) ;
1737 ScalarColumn<Double> mjdColOut( out->table(), "TIME" ) ;
1738 ScalarColumn<Double> intervalColOut( out->table(), "INTERVAL" ) ;
1739 ScalarColumn<uInt> fidColOut( out->table(), "FREQ_ID" ) ;
1740
1741 // for each row
1742 // assume that the data order are same between sig and ref
1743 RowAccumulator acc( asap::W_TINTSYS ) ;
1744 for ( int i = 0 ; i < sig->nrow() ; i++ ) {
1745 // get values
1746 Vector<Float> spsig ;
1747 specCol1.get( i, spsig ) ;
1748 Vector<Float> spref ;
1749 specCol2.get( i, spref ) ;
1750 Vector<Float> tsyssig ;
1751 tsysCol1.get( i, tsyssig ) ;
1752 Vector<Float> tsysref ;
1753 tsysCol2.get( i, tsysref ) ;
1754 Vector<uChar> flagsig ;
1755 flagCol1.get( i, flagsig ) ;
1756 Vector<uChar> flagref ;
1757 flagCol2.get( i, flagref ) ;
1758 Double timesig ;
1759 mjdCol1.get( i, timesig ) ;
1760 Double timeref ;
1761 mjdCol2.get( i, timeref ) ;
1762 Double intsig ;
1763 intervalCol1.get( i, intsig ) ;
1764 Double intref ;
1765 intervalCol2.get( i, intref ) ;
1766
1767 // shift reference spectra
1768 int refchan = spref.nelements() ;
1769 Vector<Float> sspref( spref.nelements() ) ;
1770 Vector<Float> stsysref( tsysref.nelements() ) ;
1771 Vector<uChar> sflagref( flagref.nelements() ) ;
1772 if ( ioffset > 0 ) {
1773 // SPECTRA and FLAGTRA
1774 for ( int j = 0 ; j < refchan-ioffset ; j++ ) {
1775 sspref[j] = spref[j+ioffset] ;
1776 sflagref[j] = flagref[j+ioffset] ;
1777 }
1778 for ( int j = refchan-ioffset ; j < refchan ; j++ ) {
1779 sspref[j] = spref[j-refchan+ioffset] ;
1780 sflagref[j] = flagref[j-refchan+ioffset] ;
1781 }
1782 spref = sspref.copy() ;
1783 flagref = sflagref.copy() ;
1784 for ( int j = 0 ; j < refchan - 1 ; j++ ) {
1785 sspref[j] = doffset * spref[j+1] + ( 1.0 - doffset ) * spref[j] ;
1786 sflagref[j] = flagref[j+1] + flagref[j] ;
1787 }
1788 sspref[refchan-1] = doffset * spref[0] + ( 1.0 - doffset ) * spref[refchan-1] ;
1789 sflagref[refchan-1] = flagref[0] + flagref[refchan-1] ;
1790
1791 // TSYS
1792 if ( spref.nelements() == tsysref.nelements() ) {
1793 for ( int j = 0 ; j < refchan-ioffset ; j++ ) {
1794 stsysref[j] = tsysref[j+ioffset] ;
1795 }
1796 for ( int j = refchan-ioffset ; j < refchan ; j++ ) {
1797 stsysref[j] = tsysref[j-refchan+ioffset] ;
1798 }
1799 tsysref = stsysref.copy() ;
1800 for ( int j = 0 ; j < refchan - 1 ; j++ ) {
1801 stsysref[j] = doffset * tsysref[j+1] + ( 1.0 - doffset ) * tsysref[j] ;
1802 }
1803 stsysref[refchan-1] = doffset * tsysref[0] + ( 1.0 - doffset ) * tsysref[refchan-1] ;
1804 }
1805 }
1806 else {
1807 // SPECTRA and FLAGTRA
1808 for ( int j = 0 ; j < abs(ioffset) ; j++ ) {
1809 sspref[j] = spref[refchan+ioffset+j] ;
1810 sflagref[j] = flagref[refchan+ioffset+j] ;
1811 }
1812 for ( int j = abs(ioffset) ; j < refchan ; j++ ) {
1813 sspref[j] = spref[j+ioffset] ;
1814 sflagref[j] = flagref[j+ioffset] ;
1815 }
1816 spref = sspref.copy() ;
1817 flagref = sflagref.copy() ;
1818 sspref[0] = doffset * spref[refchan-1] + ( 1.0 - doffset ) * spref[0] ;
1819 sflagref[0] = flagref[0] + flagref[refchan-1] ;
1820 for ( int j = 1 ; j < refchan ; j++ ) {
1821 sspref[j] = doffset * spref[j-1] + ( 1.0 - doffset ) * spref[j] ;
1822 sflagref[j] = flagref[j-1] + flagref[j] ;
1823 }
1824 // TSYS
1825 if ( spref.nelements() == tsysref.nelements() ) {
1826 for ( int j = 0 ; j < abs(ioffset) ; j++ ) {
1827 stsysref[j] = tsysref[refchan+ioffset+j] ;
1828 }
1829 for ( int j = abs(ioffset) ; j < refchan ; j++ ) {
1830 stsysref[j] = tsysref[j+ioffset] ;
1831 }
1832 tsysref = stsysref.copy() ;
1833 stsysref[0] = doffset * tsysref[refchan-1] + ( 1.0 - doffset ) * tsysref[0] ;
1834 for ( int j = 1 ; j < refchan ; j++ ) {
1835 stsysref[j] = doffset * tsysref[j-1] + ( 1.0 - doffset ) * tsysref[j] ;
1836 }
1837 }
1838 }
1839
1840 // shift signal spectra if necessary (only for APEX?)
1841 if ( choffset2 != 0.0 ) {
1842 int sigchan = spsig.nelements() ;
1843 Vector<Float> sspsig( spsig.nelements() ) ;
1844 Vector<Float> stsyssig( tsyssig.nelements() ) ;
1845 Vector<uChar> sflagsig( flagsig.nelements() ) ;
1846 if ( ioffset2 > 0 ) {
1847 // SPECTRA and FLAGTRA
1848 for ( int j = 0 ; j < sigchan-ioffset2 ; j++ ) {
1849 sspsig[j] = spsig[j+ioffset2] ;
1850 sflagsig[j] = flagsig[j+ioffset2] ;
1851 }
1852 for ( int j = sigchan-ioffset2 ; j < sigchan ; j++ ) {
1853 sspsig[j] = spsig[j-sigchan+ioffset2] ;
1854 sflagsig[j] = flagsig[j-sigchan+ioffset2] ;
1855 }
1856 spsig = sspsig.copy() ;
1857 flagsig = sflagsig.copy() ;
1858 for ( int j = 0 ; j < sigchan - 1 ; j++ ) {
1859 sspsig[j] = doffset2 * spsig[j+1] + ( 1.0 - doffset2 ) * spsig[j] ;
1860 sflagsig[j] = flagsig[j+1] || flagsig[j] ;
1861 }
1862 sspsig[sigchan-1] = doffset2 * spsig[0] + ( 1.0 - doffset2 ) * spsig[sigchan-1] ;
1863 sflagsig[sigchan-1] = flagsig[0] || flagsig[sigchan-1] ;
1864 // TSTS
1865 if ( spsig.nelements() == tsyssig.nelements() ) {
1866 for ( int j = 0 ; j < sigchan-ioffset2 ; j++ ) {
1867 stsyssig[j] = tsyssig[j+ioffset2] ;
1868 }
1869 for ( int j = sigchan-ioffset2 ; j < sigchan ; j++ ) {
1870 stsyssig[j] = tsyssig[j-sigchan+ioffset2] ;
1871 }
1872 tsyssig = stsyssig.copy() ;
1873 for ( int j = 0 ; j < sigchan - 1 ; j++ ) {
1874 stsyssig[j] = doffset2 * tsyssig[j+1] + ( 1.0 - doffset2 ) * tsyssig[j] ;
1875 }
1876 stsyssig[sigchan-1] = doffset2 * tsyssig[0] + ( 1.0 - doffset2 ) * tsyssig[sigchan-1] ;
1877 }
1878 }
1879 else {
1880 // SPECTRA and FLAGTRA
1881 for ( int j = 0 ; j < abs(ioffset2) ; j++ ) {
1882 sspsig[j] = spsig[sigchan+ioffset2+j] ;
1883 sflagsig[j] = flagsig[sigchan+ioffset2+j] ;
1884 }
1885 for ( int j = abs(ioffset2) ; j < sigchan ; j++ ) {
1886 sspsig[j] = spsig[j+ioffset2] ;
1887 sflagsig[j] = flagsig[j+ioffset2] ;
1888 }
1889 spsig = sspsig.copy() ;
1890 flagsig = sflagsig.copy() ;
1891 sspsig[0] = doffset2 * spsig[sigchan-1] + ( 1.0 - doffset2 ) * spsig[0] ;
1892 sflagsig[0] = flagsig[0] + flagsig[sigchan-1] ;
1893 for ( int j = 1 ; j < sigchan ; j++ ) {
1894 sspsig[j] = doffset2 * spsig[j-1] + ( 1.0 - doffset2 ) * spsig[j] ;
1895 sflagsig[j] = flagsig[j-1] + flagsig[j] ;
1896 }
1897 // TSYS
1898 if ( spsig.nelements() == tsyssig.nelements() ) {
1899 for ( int j = 0 ; j < abs(ioffset2) ; j++ ) {
1900 stsyssig[j] = tsyssig[sigchan+ioffset2+j] ;
1901 }
1902 for ( int j = abs(ioffset2) ; j < sigchan ; j++ ) {
1903 stsyssig[j] = tsyssig[j+ioffset2] ;
1904 }
1905 tsyssig = stsyssig.copy() ;
1906 stsyssig[0] = doffset2 * tsyssig[sigchan-1] + ( 1.0 - doffset2 ) * tsyssig[0] ;
1907 for ( int j = 1 ; j < sigchan ; j++ ) {
1908 stsyssig[j] = doffset2 * tsyssig[j-1] + ( 1.0 - doffset2 ) * tsyssig[j] ;
1909 }
1910 }
1911 }
1912 }
1913
1914 // folding
1915 acc.add( spsig, !flagsig, tsyssig, intsig, timesig ) ;
1916 acc.add( sspref, !sflagref, stsysref, intref, timeref ) ;
1917
1918 // put result
1919 specColOut.put( i, acc.getSpectrum() ) ;
1920 const Vector<Bool> &msk = acc.getMask() ;
1921 Vector<uChar> flg( msk.shape() ) ;
1922 convertArray( flg, !msk ) ;
1923 flagColOut.put( i, flg ) ;
1924 tsysColOut.put( i, acc.getTsys() ) ;
1925 intervalColOut.put( i, acc.getInterval() ) ;
1926 mjdColOut.put( i, acc.getTime() ) ;
1927 // change FREQ_ID to unshifted IF setting (only for APEX?)
1928 if ( choffset2 != 0.0 ) {
1929 uInt freqid = fidColOut( 0 ) ; // assume single-IF data
1930 double refpix, refval, increment ;
1931 out->frequencies().getEntry( refpix, refval, increment, freqid ) ;
1932 refval -= choffset * increment ;
1933 uInt newfreqid = out->frequencies().addEntry( refpix, refval, increment ) ;
1934 Vector<uInt> freqids = fidColOut.getColumn() ;
1935 for ( uInt j = 0 ; j < freqids.nelements() ; j++ ) {
1936 if ( freqids[j] == freqid )
1937 freqids[j] = newfreqid ;
1938 }
1939 fidColOut.putColumn( freqids ) ;
1940 }
1941
1942 acc.reset() ;
1943 }
1944
1945 return out ;
1946}
1947
1948
1949CountedPtr< Scantable > STMath::freqSwitch( const CountedPtr< Scantable >& in )
1950{
1951 // make copy or reference
1952 CountedPtr< Scantable > out = getScantable(in, false);
1953 Table& tout = out->table();
1954 Block<String> cols(4);
1955 cols[0] = String("SCANNO");
1956 cols[1] = String("CYCLENO");
1957 cols[2] = String("BEAMNO");
1958 cols[3] = String("POLNO");
1959 TableIterator iter(tout, cols);
1960 while (!iter.pastEnd()) {
1961 Table subt = iter.table();
1962 // this should leave us with two rows for the two IFs....if not ignore
1963 if (subt.nrow() != 2 ) {
1964 continue;
1965 }
1966 ArrayColumn<Float> specCol(subt, "SPECTRA");
1967 ArrayColumn<Float> tsysCol(subt, "TSYS");
1968 ArrayColumn<uChar> flagCol(subt, "FLAGTRA");
1969 Vector<Float> onspec,offspec, ontsys, offtsys;
1970 Vector<uChar> onflag, offflag;
1971 tsysCol.get(0, ontsys); tsysCol.get(1, offtsys);
1972 specCol.get(0, onspec); specCol.get(1, offspec);
1973 flagCol.get(0, onflag); flagCol.get(1, offflag);
1974 MaskedArray<Float> on = maskedArray(onspec, onflag);
1975 MaskedArray<Float> off = maskedArray(offspec, offflag);
1976 MaskedArray<Float> oncopy = on.copy();
1977
1978 on /= off; on -= 1.0f;
1979 on *= ontsys[0];
1980 off /= oncopy; off -= 1.0f;
1981 off *= offtsys[0];
1982 specCol.put(0, on.getArray());
1983 const Vector<Bool>& m0 = on.getMask();
1984 Vector<uChar> flags0(m0.shape());
1985 convertArray(flags0, !m0);
1986 flagCol.put(0, flags0);
1987
1988 specCol.put(1, off.getArray());
1989 const Vector<Bool>& m1 = off.getMask();
1990 Vector<uChar> flags1(m1.shape());
1991 convertArray(flags1, !m1);
1992 flagCol.put(1, flags1);
1993 ++iter;
1994 }
1995
1996 return out;
1997}
1998
1999std::vector< float > STMath::statistic( const CountedPtr< Scantable > & in,
2000 const std::vector< bool > & mask,
2001 const std::string& which )
2002{
2003
2004 Vector<Bool> m(mask);
2005 const Table& tab = in->table();
2006 ROArrayColumn<Float> specCol(tab, "SPECTRA");
2007 ROArrayColumn<uChar> flagCol(tab, "FLAGTRA");
2008 std::vector<float> out;
2009 for (uInt i=0; i < tab.nrow(); ++i ) {
2010 Vector<Float> spec; specCol.get(i, spec);
2011 Vector<uChar> flag; flagCol.get(i, flag);
2012 MaskedArray<Float> ma = maskedArray(spec, flag);
2013 float outstat = 0.0;
2014 if ( spec.nelements() == m.nelements() ) {
2015 outstat = mathutil::statistics(which, ma(m));
2016 } else {
2017 outstat = mathutil::statistics(which, ma);
2018 }
2019 out.push_back(outstat);
2020 }
2021 return out;
2022}
2023
2024std::vector< float > STMath::statisticRow( const CountedPtr< Scantable > & in,
2025 const std::vector< bool > & mask,
2026 const std::string& which,
2027 int row )
2028{
2029
2030 Vector<Bool> m(mask);
2031 const Table& tab = in->table();
2032 ROArrayColumn<Float> specCol(tab, "SPECTRA");
2033 ROArrayColumn<uChar> flagCol(tab, "FLAGTRA");
2034 std::vector<float> out;
2035
2036 Vector<Float> spec; specCol.get(row, spec);
2037 Vector<uChar> flag; flagCol.get(row, flag);
2038 MaskedArray<Float> ma = maskedArray(spec, flag);
2039 float outstat = 0.0;
2040 if ( spec.nelements() == m.nelements() ) {
2041 outstat = mathutil::statistics(which, ma(m));
2042 } else {
2043 outstat = mathutil::statistics(which, ma);
2044 }
2045 out.push_back(outstat);
2046
2047 return out;
2048}
2049
2050std::vector< int > STMath::minMaxChan( const CountedPtr< Scantable > & in,
2051 const std::vector< bool > & mask,
2052 const std::string& which )
2053{
2054
2055 Vector<Bool> m(mask);
2056 const Table& tab = in->table();
2057 ROArrayColumn<Float> specCol(tab, "SPECTRA");
2058 ROArrayColumn<uChar> flagCol(tab, "FLAGTRA");
2059 std::vector<int> out;
2060 for (uInt i=0; i < tab.nrow(); ++i ) {
2061 Vector<Float> spec; specCol.get(i, spec);
2062 Vector<uChar> flag; flagCol.get(i, flag);
2063 MaskedArray<Float> ma = maskedArray(spec, flag);
2064 if (ma.ndim() != 1) {
2065 throw (ArrayError(
2066 "std::vector<int> STMath::minMaxChan("
2067 "ContedPtr<Scantable> &in, std::vector<bool> &mask, "
2068 " std::string &which)"
2069 " - MaskedArray is not 1D"));
2070 }
2071 IPosition outpos(1,0);
2072 if ( spec.nelements() == m.nelements() ) {
2073 outpos = mathutil::minMaxPos(which, ma(m));
2074 } else {
2075 outpos = mathutil::minMaxPos(which, ma);
2076 }
2077 out.push_back(outpos[0]);
2078 }
2079 return out;
2080}
2081
2082CountedPtr< Scantable > STMath::bin( const CountedPtr< Scantable > & in,
2083 int width )
2084{
2085 if ( !in->getSelection().empty() ) throw(AipsError("Can't bin subset of the data."));
2086 CountedPtr< Scantable > out = getScantable(in, false);
2087 Table& tout = out->table();
2088 out->frequencies().rescale(width, "BIN");
2089 ArrayColumn<Float> specCol(tout, "SPECTRA");
2090 ArrayColumn<uChar> flagCol(tout, "FLAGTRA");
2091 ArrayColumn<Float> tsysCol(tout, "TSYS");
2092
2093 for (uInt i=0; i < tout.nrow(); ++i ) {
2094 MaskedArray<Float> main = maskedArray(specCol(i), flagCol(i));
2095 MaskedArray<Float> maout;
2096 LatticeUtilities::bin(maout, main, 0, Int(width));
2097 specCol.put(i, maout.getArray());
2098 flagCol.put(i, flagsFromMA(maout));
2099 if (tsysCol(i).nelements() == specCol(i).nelements()) {
2100 MaskedArray<Float> matsysin = maskedArray(tsysCol(i), flagCol(i));
2101 MaskedArray<Float> matsysout;
2102 LatticeUtilities::bin(matsysout, matsysin, 0, Int(width));
2103 tsysCol.put(i, matsysout.getArray());
2104 }
2105 // take only the first binned spectrum's length for the deprecated
2106 // global header item nChan
2107 if (i==0) tout.rwKeywordSet().define(String("nChan"),
2108 Int(maout.getArray().nelements()));
2109 }
2110 return out;
2111}
2112
2113CountedPtr< Scantable > STMath::resample( const CountedPtr< Scantable >& in,
2114 const std::string& method,
2115 float width )
2116//
2117// Should add the possibility of width being specified in km/s. This means
2118// that for each freqID (SpectralCoordinate) we will need to convert to an
2119// average channel width (say at the reference pixel). Then we would need
2120// to be careful to make sure each spectrum (of different freqID)
2121// is the same length.
2122//
2123{
2124 //InterpolateArray1D<Double,Float>::InterpolationMethod interp;
2125 Int interpMethod(stringToIMethod(method));
2126
2127 CountedPtr< Scantable > out = getScantable(in, false);
2128 Table& tout = out->table();
2129
2130// Resample SpectralCoordinates (one per freqID)
2131 out->frequencies().rescale(width, "RESAMPLE");
2132 TableIterator iter(tout, "IFNO");
2133 TableRow row(tout);
2134 while ( !iter.pastEnd() ) {
2135 Table tab = iter.table();
2136 ArrayColumn<Float> specCol(tab, "SPECTRA");
2137 //ArrayColumn<Float> tsysCol(tout, "TSYS");
2138 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
2139 Vector<Float> spec;
2140 Vector<uChar> flag;
2141 specCol.get(0,spec); // the number of channels should be constant per IF
2142 uInt nChanIn = spec.nelements();
2143 Vector<Float> xIn(nChanIn); indgen(xIn);
2144 Int fac = Int(nChanIn/width);
2145 Vector<Float> xOut(fac+10); // 10 to be safe - resize later
2146 uInt k = 0;
2147 Float x = 0.0;
2148 while (x < Float(nChanIn) ) {
2149 xOut(k) = x;
2150 k++;
2151 x += width;
2152 }
2153 uInt nChanOut = k;
2154 xOut.resize(nChanOut, True);
2155 // process all rows for this IFNO
2156 Vector<Float> specOut;
2157 Vector<Bool> maskOut;
2158 Vector<uChar> flagOut;
2159 for (uInt i=0; i < tab.nrow(); ++i) {
2160 specCol.get(i, spec);
2161 flagCol.get(i, flag);
2162 Vector<Bool> mask(flag.nelements());
2163 convertArray(mask, flag);
2164
2165 IPosition shapeIn(spec.shape());
2166 //sh.nchan = nChanOut;
2167 InterpolateArray1D<Float,Float>::interpolate(specOut, maskOut, xOut,
2168 xIn, spec, mask,
2169 interpMethod, True, True);
2170 /// @todo do the same for channel based Tsys
2171 flagOut.resize(maskOut.nelements());
2172 convertArray(flagOut, maskOut);
2173 specCol.put(i, specOut);
2174 flagCol.put(i, flagOut);
2175 }
2176 ++iter;
2177 }
2178
2179 return out;
2180}
2181
2182STMath::imethod STMath::stringToIMethod(const std::string& in)
2183{
2184 static STMath::imap lookup;
2185
2186 // initialize the lookup table if necessary
2187 if ( lookup.empty() ) {
2188 lookup["nearest"] = InterpolateArray1D<Double,Float>::nearestNeighbour;
2189 lookup["linear"] = InterpolateArray1D<Double,Float>::linear;
2190 lookup["cubic"] = InterpolateArray1D<Double,Float>::cubic;
2191 lookup["spline"] = InterpolateArray1D<Double,Float>::spline;
2192 }
2193
2194 STMath::imap::const_iterator iter = lookup.find(in);
2195
2196 if ( lookup.end() == iter ) {
2197 std::string message = in;
2198 message += " is not a valid interpolation mode";
2199 throw(AipsError(message));
2200 }
2201 return iter->second;
2202}
2203
2204WeightType STMath::stringToWeight(const std::string& in)
2205{
2206 static std::map<std::string, WeightType> lookup;
2207
2208 // initialize the lookup table if necessary
2209 if ( lookup.empty() ) {
2210 lookup["NONE"] = asap::W_NONE;
2211 lookup["TINT"] = asap::W_TINT;
2212 lookup["TINTSYS"] = asap::W_TINTSYS;
2213 lookup["TSYS"] = asap::W_TSYS;
2214 lookup["VAR"] = asap::W_VAR;
2215 }
2216
2217 std::map<std::string, WeightType>::const_iterator iter = lookup.find(in);
2218
2219 if ( lookup.end() == iter ) {
2220 std::string message = in;
2221 message += " is not a valid weighting mode";
2222 throw(AipsError(message));
2223 }
2224 return iter->second;
2225}
2226
2227CountedPtr< Scantable > STMath::gainElevation( const CountedPtr< Scantable >& in,
2228 const vector< float > & coeff,
2229 const std::string & filename,
2230 const std::string& method)
2231{
2232 LogIO os( LogOrigin( "STMath", "gainElevation", WHERE ) ) ;
2233 // Get elevation data from Scantable and convert to degrees
2234 CountedPtr< Scantable > out = getScantable(in, false);
2235 Table& tab = out->table();
2236 ROScalarColumn<Float> elev(tab, "ELEVATION");
2237 Vector<Float> x = elev.getColumn();
2238 x *= Float(180 / C::pi); // Degrees
2239
2240 Vector<Float> coeffs(coeff);
2241 const uInt nc = coeffs.nelements();
2242 if ( filename.length() > 0 && nc > 0 ) {
2243 throw(AipsError("You must choose either polynomial coefficients or an ascii file, not both"));
2244 }
2245
2246 // Correct
2247 if ( nc > 0 || filename.length() == 0 ) {
2248 // Find instrument
2249 Bool throwit = True;
2250 Instrument inst =
2251 STAttr::convertInstrument(tab.keywordSet().asString("AntennaName"),
2252 throwit);
2253
2254 // Set polynomial
2255 Polynomial<Float>* ppoly = 0;
2256 Vector<Float> coeff;
2257 String msg;
2258 if ( nc > 0 ) {
2259 ppoly = new Polynomial<Float>(nc-1);
2260 coeff = coeffs;
2261 msg = String("user");
2262 } else {
2263 STAttr sdAttr;
2264 coeff = sdAttr.gainElevationPoly(inst);
2265 ppoly = new Polynomial<Float>(coeff.nelements()-1);
2266 msg = String("built in");
2267 }
2268
2269 if ( coeff.nelements() > 0 ) {
2270 ppoly->setCoefficients(coeff);
2271 } else {
2272 delete ppoly;
2273 throw(AipsError("There is no known gain-elevation polynomial known for this instrument"));
2274 }
2275 os << "Making polynomial correction with " << msg << " coefficients:" << endl;
2276 os << " " << coeff << LogIO::POST;
2277 const uInt nrow = tab.nrow();
2278 Vector<Float> factor(nrow);
2279 for ( uInt i=0; i < nrow; ++i ) {
2280 factor[i] = 1.0 / (*ppoly)(x[i]);
2281 }
2282 delete ppoly;
2283 scaleByVector(tab, factor, true);
2284
2285 } else {
2286 // Read and correct
2287 os << "Making correction from ascii Table" << LogIO::POST;
2288 scaleFromAsciiTable(tab, filename, method, x, true);
2289 }
2290 return out;
2291}
2292
2293void STMath::scaleFromAsciiTable(Table& in, const std::string& filename,
2294 const std::string& method,
2295 const Vector<Float>& xout, bool dotsys)
2296{
2297
2298// Read gain-elevation ascii file data into a Table.
2299
2300 String formatString;
2301 Table tbl = readAsciiTable(formatString, Table::Memory, filename, "", "", False);
2302 scaleFromTable(in, tbl, method, xout, dotsys);
2303}
2304
2305void STMath::scaleFromTable(Table& in,
2306 const Table& table,
2307 const std::string& method,
2308 const Vector<Float>& xout, bool dotsys)
2309{
2310
2311 ROScalarColumn<Float> geElCol(table, "ELEVATION");
2312 ROScalarColumn<Float> geFacCol(table, "FACTOR");
2313 Vector<Float> xin = geElCol.getColumn();
2314 Vector<Float> yin = geFacCol.getColumn();
2315 Vector<Bool> maskin(xin.nelements(),True);
2316
2317 // Interpolate (and extrapolate) with desired method
2318
2319 InterpolateArray1D<Double,Float>::InterpolationMethod interp = stringToIMethod(method);
2320
2321 Vector<Float> yout;
2322 Vector<Bool> maskout;
2323 InterpolateArray1D<Float,Float>::interpolate(yout, maskout, xout,
2324 xin, yin, maskin, interp,
2325 True, True);
2326
2327 scaleByVector(in, Float(1.0)/yout, dotsys);
2328}
2329
2330void STMath::scaleByVector( Table& in,
2331 const Vector< Float >& factor,
2332 bool dotsys )
2333{
2334 uInt nrow = in.nrow();
2335 if ( factor.nelements() != nrow ) {
2336 throw(AipsError("factors.nelements() != table.nelements()"));
2337 }
2338 ArrayColumn<Float> specCol(in, "SPECTRA");
2339 ArrayColumn<uChar> flagCol(in, "FLAGTRA");
2340 ArrayColumn<Float> tsysCol(in, "TSYS");
2341 for (uInt i=0; i < nrow; ++i) {
2342 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
2343 ma *= factor[i];
2344 specCol.put(i, ma.getArray());
2345 flagCol.put(i, flagsFromMA(ma));
2346 if ( dotsys ) {
2347 Vector<Float> tsys = tsysCol(i);
2348 tsys *= factor[i];
2349 tsysCol.put(i,tsys);
2350 }
2351 }
2352}
2353
2354CountedPtr< Scantable > STMath::convertFlux( const CountedPtr< Scantable >& in,
2355 float d, float etaap,
2356 float jyperk )
2357{
2358 LogIO os( LogOrigin( "STMath", "convertFlux", WHERE ) ) ;
2359
2360 CountedPtr< Scantable > out = getScantable(in, false);
2361 Table& tab = in->table();
2362 Table& outtab = out->table();
2363 Unit fluxUnit(tab.keywordSet().asString("FluxUnit"));
2364 Unit K(String("K"));
2365 Unit JY(String("Jy"));
2366
2367 bool tokelvin = true;
2368 Double cfac = 1.0;
2369
2370 if ( fluxUnit == JY ) {
2371 os << "Converting to K" << LogIO::POST;
2372 Quantum<Double> t(1.0,fluxUnit);
2373 Quantum<Double> t2 = t.get(JY);
2374 cfac = (t2 / t).getValue(); // value to Jy
2375
2376 tokelvin = true;
2377 out->setFluxUnit("K");
2378 } else if ( fluxUnit == K ) {
2379 os << "Converting to Jy" << LogIO::POST;
2380 Quantum<Double> t(1.0,fluxUnit);
2381 Quantum<Double> t2 = t.get(K);
2382 cfac = (t2 / t).getValue(); // value to K
2383
2384 tokelvin = false;
2385 out->setFluxUnit("Jy");
2386 } else {
2387 throw(AipsError("Unrecognized brightness units in Table - must be consistent with Jy or K"));
2388 }
2389 // Make sure input values are converted to either Jy or K first...
2390 Float factor = cfac;
2391
2392 // Select method
2393 if (jyperk > 0.0) {
2394 factor *= jyperk;
2395 if ( tokelvin ) factor = 1.0 / jyperk;
2396 os << "Jy/K = " << jyperk << LogIO::POST;
2397 Vector<Float> factors(outtab.nrow(), factor);
2398 scaleByVector(outtab,factors, false);
2399 } else if ( etaap > 0.0) {
2400 if (d < 0) {
2401 Instrument inst =
2402 STAttr::convertInstrument(tab.keywordSet().asString("AntennaName"),
2403 True);
2404 STAttr sda;
2405 d = sda.diameter(inst);
2406 }
2407 jyperk = STAttr::findJyPerK(etaap, d);
2408 os << "Jy/K = " << jyperk << LogIO::POST;
2409 factor *= jyperk;
2410 if ( tokelvin ) {
2411 factor = 1.0 / factor;
2412 }
2413 Vector<Float> factors(outtab.nrow(), factor);
2414 scaleByVector(outtab, factors, False);
2415 } else {
2416
2417 // OK now we must deal with automatic look up of values.
2418 // We must also deal with the fact that the factors need
2419 // to be computed per IF and may be different and may
2420 // change per integration.
2421
2422 os <<"Looking up conversion factors" << LogIO::POST;
2423 convertBrightnessUnits(out, tokelvin, cfac);
2424 }
2425
2426 return out;
2427}
2428
2429void STMath::convertBrightnessUnits( CountedPtr<Scantable>& in,
2430 bool tokelvin, float cfac )
2431{
2432 Table& table = in->table();
2433 Instrument inst =
2434 STAttr::convertInstrument(table.keywordSet().asString("AntennaName"), True);
2435 TableIterator iter(table, "FREQ_ID");
2436 STFrequencies stfreqs = in->frequencies();
2437 STAttr sdAtt;
2438 while (!iter.pastEnd()) {
2439 Table tab = iter.table();
2440 ArrayColumn<Float> specCol(tab, "SPECTRA");
2441 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
2442 ROScalarColumn<uInt> freqidCol(tab, "FREQ_ID");
2443 MEpoch::ROScalarColumn timeCol(tab, "TIME");
2444
2445 uInt freqid; freqidCol.get(0, freqid);
2446 Vector<Float> tmpspec; specCol.get(0, tmpspec);
2447 // STAttr.JyPerK has a Vector interface... change sometime.
2448 Vector<Float> freqs(1,stfreqs.getRefFreq(freqid, tmpspec.nelements()));
2449 for ( uInt i=0; i<tab.nrow(); ++i) {
2450 Float jyperk = (sdAtt.JyPerK(inst, timeCol(i), freqs))[0];
2451 Float factor = cfac * jyperk;
2452 if ( tokelvin ) factor = Float(1.0) / factor;
2453 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
2454 ma *= factor;
2455 specCol.put(i, ma.getArray());
2456 flagCol.put(i, flagsFromMA(ma));
2457 }
2458 ++iter;
2459 }
2460}
2461
2462CountedPtr< Scantable > STMath::opacity( const CountedPtr< Scantable > & in,
2463 const std::vector<float>& tau )
2464{
2465 CountedPtr< Scantable > out = getScantable(in, false);
2466
2467 Table outtab = out->table();
2468
2469 const Int ntau = uInt(tau.size());
2470 std::vector<float>::const_iterator tauit = tau.begin();
2471 AlwaysAssert((ntau == 1 || ntau == in->nif() || ntau == in->nif() * in->npol()),
2472 AipsError);
2473 TableIterator iiter(outtab, "IFNO");
2474 while ( !iiter.pastEnd() ) {
2475 Table itab = iiter.table();
2476 TableIterator piter(itab, "POLNO");
2477 while ( !piter.pastEnd() ) {
2478 Table tab = piter.table();
2479 ROScalarColumn<Float> elev(tab, "ELEVATION");
2480 ArrayColumn<Float> specCol(tab, "SPECTRA");
2481 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
2482 ArrayColumn<Float> tsysCol(tab, "TSYS");
2483 for ( uInt i=0; i<tab.nrow(); ++i) {
2484 Float zdist = Float(C::pi_2) - elev(i);
2485 Float factor = exp(*tauit/cos(zdist));
2486 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
2487 ma *= factor;
2488 specCol.put(i, ma.getArray());
2489 flagCol.put(i, flagsFromMA(ma));
2490 Vector<Float> tsys;
2491 tsysCol.get(i, tsys);
2492 tsys *= factor;
2493 tsysCol.put(i, tsys);
2494 }
2495 if (ntau == in->nif()*in->npol() ) {
2496 tauit++;
2497 }
2498 piter++;
2499 }
2500 if (ntau >= in->nif() ) {
2501 tauit++;
2502 }
2503 iiter++;
2504 }
2505 return out;
2506}
2507
2508CountedPtr< Scantable > STMath::smoothOther( const CountedPtr< Scantable >& in,
2509 const std::string& kernel,
2510 float width, int order)
2511{
2512 CountedPtr< Scantable > out = getScantable(in, false);
2513 Table table = out->table();
2514
2515 TableIterator iter(table, "IFNO");
2516 while (!iter.pastEnd()) {
2517 Table tab = iter.table();
2518 ArrayColumn<Float> specCol(tab, "SPECTRA");
2519 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
2520 Vector<Float> spec;
2521 Vector<uChar> flag;
2522 for (uInt i = 0; i < tab.nrow(); ++i) {
2523 specCol.get(i, spec);
2524 flagCol.get(i, flag);
2525 Vector<Bool> mask(flag.nelements());
2526 convertArray(mask, flag);
2527 Vector<Float> specout;
2528 Vector<Bool> maskout;
2529 if (kernel == "hanning") {
2530 mathutil::hanning(specout, maskout, spec, !mask);
2531 } else if (kernel == "rmedian") {
2532 mathutil::runningMedian(specout, maskout, spec , mask, width);
2533 } else if (kernel == "poly") {
2534 mathutil::polyfit(specout, maskout, spec, !mask, width, order);
2535 }
2536
2537 for (uInt j = 0; j < flag.nelements(); ++j) {
2538 uChar userFlag = 1 << 7;
2539 if (maskout[j]==True) userFlag = 0 << 7;
2540 flag(j) = userFlag;
2541 }
2542
2543 flagCol.put(i, flag);
2544 specCol.put(i, specout);
2545 }
2546 ++iter;
2547 }
2548 return out;
2549}
2550
2551CountedPtr< Scantable > STMath::smooth( const CountedPtr< Scantable >& in,
2552 const std::string& kernel, float width,
2553 int order)
2554{
2555 if (kernel == "rmedian" || kernel == "hanning" || kernel == "poly") {
2556 return smoothOther(in, kernel, width, order);
2557 }
2558 CountedPtr< Scantable > out = getScantable(in, false);
2559 Table& table = out->table();
2560 VectorKernel::KernelTypes type = VectorKernel::toKernelType(kernel);
2561 // same IFNO should have same no of channels
2562 // this saves overhead
2563 TableIterator iter(table, "IFNO");
2564 while (!iter.pastEnd()) {
2565 Table tab = iter.table();
2566 ArrayColumn<Float> specCol(tab, "SPECTRA");
2567 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
2568 Vector<Float> spec = specCol( 0 );
2569 uInt nchan = spec.nelements();
2570 Vector<Float> kvec = VectorKernel::make(type, width, nchan, True, False);
2571 Convolver<Float> conv(kvec, IPosition(1,nchan));
2572 Vector<uChar> flag;
2573 Vector<Bool> mask(nchan);
2574 for ( uInt i=0; i<tab.nrow(); ++i) {
2575 specCol.get(i, spec);
2576 flagCol.get(i, flag);
2577 convertArray(mask, flag);
2578 Vector<Float> specout;
2579 //mathutil::replaceMaskByZero(specout, mask);
2580 mathutil::replaceMaskByZero(spec, !mask);
2581 //std::vector<bool> vmask;
2582 //(!mask).tovector(vmask);
2583 //mathutil::doZeroOrderInterpolation(spec, vmask);
2584 conv.linearConv(specout, spec);
2585 specCol.put(i, specout);
2586 }
2587 ++iter;
2588 }
2589 return out;
2590}
2591
2592CountedPtr< Scantable >
2593STMath::merge( const std::vector< CountedPtr < Scantable > >& in,
2594 const std::string &freqTol )
2595{
2596 Double freqTolInHz = 0.0; // default is 0.0Hz (merge only when exact match)
2597 if (freqTol.size() > 0) {
2598 Quantum<Double> freqTolInQuantity;
2599 if (!Quantum<Double>::read(freqTolInQuantity, freqTol)) {
2600 throw(AipsError("Failed to convert freqTol string to quantity"));
2601 }
2602 if (!freqTolInQuantity.isConform("Hz")) {
2603 throw(AipsError("Invalid freqTol string"));
2604 }
2605 freqTolInHz = freqTolInQuantity.getValue("Hz");
2606 LogIO os(LogOrigin("STMath", "merge", WHERE));
2607 os << "frequency tolerance = " << freqTolInHz << "Hz" << LogIO::POST;
2608 }
2609
2610 if ( in.size() < 2 ) {
2611 throw(AipsError("Need at least two scantables to perform a merge."));
2612 }
2613 std::vector<CountedPtr < Scantable > >::const_iterator it = in.begin();
2614 bool insitu = insitu_;
2615 setInsitu(false);
2616 CountedPtr< Scantable > out = getScantable(*it, false);
2617 setInsitu(insitu);
2618 Table& tout = out->table();
2619 ScalarColumn<uInt> freqidcol(tout,"FREQ_ID"), molidcol(tout, "MOLECULE_ID");
2620 ScalarColumn<uInt> scannocol(tout,"SCANNO"), focusidcol(tout,"FOCUS_ID");
2621 ScalarColumn<uInt> ifnocol(tout, "IFNO");
2622 // Renumber SCANNO to be 0-based
2623 Vector<uInt> scannos = scannocol.getColumn();
2624 uInt offset = min(scannos);
2625 scannos -= offset;
2626 scannocol.putColumn(scannos);
2627 uInt newscanno = max(scannos)+1;
2628 ++it;
2629
2630 // new IFNO
2631 uInt ifnoCounter = max(ifnocol.getColumn()) + 1;
2632
2633 // Here we assume that each IFNO has unique MOLECULE_ID
2634 // molIdMap:
2635 // KEY: IFNO
2636 // VALUE: MOLECULE_ID
2637 map<uInt, uInt> molIdMap;
2638 {
2639 TableIterator ifit(tout, "IFNO");
2640 while (!ifit.pastEnd()) {
2641 ROTableRow row(ifit.table());
2642 const TableRecord& rec = row.get(0);
2643 molIdMap[rec.asuInt("IFNO")] = rec.asuInt("MOLECULE_ID");
2644 ifit.next();
2645 }
2646 }
2647
2648 while ( it != in.end() ){
2649 // Check FREQUENCIES/BASEFRAME
2650 if ( out->frequencies().getFrame(true) != (*it)->frequencies().getFrame(true) ) {
2651 throw(AipsError("BASEFRAME is not identical"));
2652 }
2653
2654 if ( ! (*it)->conformant(*out) ) {
2655 // non conformant.
2656 LogIO os( LogOrigin( "STMath", "merge()", WHERE ) ) ;
2657 os << LogIO::SEVERE << "Can't merge scantables as header informations (any one of AntennaName, Equinox, and FluxUnit) differ." << LogIO::EXCEPTION ;
2658 }
2659 out->appendToHistoryTable((*it)->history());
2660 const Table& tab = (*it)->table();
2661
2662 Block<String> cols(3);
2663 cols[0] = String("FREQ_ID");
2664 cols[1] = String("MOLECULE_ID");
2665 cols[2] = String("FOCUS_ID");
2666
2667 TableIterator scanit(tab, "SCANNO");
2668 while (!scanit.pastEnd()) {
2669 TableIterator subit(scanit.table(), cols);
2670 while ( !subit.pastEnd() ) {
2671 uInt nrow = tout.nrow();
2672 Table thetab = subit.table();
2673 ROTableRow row(thetab);
2674 Vector<uInt> thecolvals(thetab.nrow());
2675 // The selected subset of table should have
2676 // the equal FREQ_ID, MOLECULE_ID, and FOCUS_ID values.
2677 const TableRecord& rec = row.get(0);
2678 tout.addRow(thetab.nrow());
2679 TableCopy::copyRows(tout, thetab, nrow, 0, thetab.nrow());
2680
2681 Slicer slice(IPosition(1, nrow), IPosition(1, thetab.nrow()),
2682 Slicer::endIsLength);
2683
2684 // Set the proper FREQ_ID
2685 Double rv,rp,inc;
2686 (*it)->frequencies().getEntry(rp, rv, inc, rec.asuInt("FREQ_ID"));
2687 uInt id;
2688
2689 // default value is new unique IFNO
2690 uInt newifno = ifnoCounter;
2691 Bool isIfMerged = False;
2692 uInt nchan = rec.asArrayFloat("SPECTRA").shape()[0];
2693 //id = out->frequencies().addEntry(rp, rv, inc);
2694 if ( !out->frequencies().match(rp, rv, inc, freqTolInHz, id) ) {
2695 // add new entry to FREQUENCIES table
2696 id = out->frequencies().addEntry(rp, rv, inc);
2697
2698 // increment counter for IFNO
2699 ifnoCounter++;
2700 }
2701 else {
2702 // should renumber IFNO to be same as existing rows that have same FREQ_ID
2703 LogIO os(LogOrigin("STMath", "merge", WHERE));
2704 Table outFreqIdSelected = tout(tout.col("FREQ_ID") == id);
2705 TableIterator _iter(outFreqIdSelected, "IFNO");
2706 map<uInt, uInt> nchanMap;
2707 while (!_iter.pastEnd()) {
2708 const Table _table = _iter.table();
2709 ROTableRow _row(_table);
2710 const TableRecord &_rec = _row.get(0);
2711 uInt nchan = _rec.asArrayFloat("SPECTRA").shape()[0];
2712 if (nchanMap.find(nchan) != nchanMap.end()) {
2713 throw(AipsError("There are non-unique IFNOs assigned to spectra that have same FREQ_ID and same nchan. Something wrong."));
2714 }
2715 nchanMap[nchan] = _rec.asuInt("IFNO");
2716 _iter.next();
2717 }
2718
2719 os << LogIO::DEBUGGING << "nchanMap for " << id << ":" << LogIO::POST;
2720 for (map<uInt, uInt>::iterator i = nchanMap.begin(); i != nchanMap.end(); ++i) {
2721 os << LogIO::DEBUGGING << "nchanMap[" << i->first << "] = " << i->second << LogIO::POST;
2722 }
2723
2724 if (nchanMap.find(nchan) == nchanMap.end()) {
2725 // increment counter for IFNO
2726 ifnoCounter++;
2727 }
2728 else {
2729 // renumber IFNO to be same as existing value that corresponds to nchan
2730 newifno = nchanMap[nchan];
2731 isIfMerged = True;
2732 }
2733 os << LogIO::DEBUGGING << "newifno = " << newifno << LogIO::POST;
2734 }
2735 thecolvals = id;
2736 freqidcol.putColumnRange(slice, thecolvals);
2737
2738 thecolvals = newifno;
2739 ifnocol.putColumnRange(slice, thecolvals);
2740
2741 // Set the proper MOLECULE_ID
2742 Vector<String> name,fname;Vector<Double> rf;
2743 (*it)->molecules().getEntry(rf, name, fname, rec.asuInt("MOLECULE_ID"));
2744 id = out->molecules().addEntry(rf, name, fname);
2745 if (molIdMap.find(newifno) == molIdMap.end()) {
2746 // add new entry to molIdMap
2747 molIdMap[newifno] = id;
2748 }
2749 if (isIfMerged) {
2750 id = molIdMap[newifno];
2751 }
2752 thecolvals = id;
2753 molidcol.putColumnRange(slice, thecolvals);
2754
2755 // Set the proper FOCUS_ID
2756 Float fpa,frot,fax,ftan,fhand,fmount,fuser, fxy, fxyp;
2757 (*it)->focus().getEntry(fpa, fax, ftan, frot, fhand, fmount,fuser,
2758 fxy, fxyp, rec.asuInt("FOCUS_ID"));
2759 id = out->focus().addEntry(fpa, fax, ftan, frot, fhand, fmount,fuser,
2760 fxy, fxyp);
2761 thecolvals = id;
2762 focusidcol.putColumnRange(slice, thecolvals);
2763
2764 // Set the proper SCANNO
2765 thecolvals = newscanno;
2766 scannocol.putColumnRange(slice, thecolvals);
2767
2768 ++subit;
2769 }
2770 ++newscanno;
2771 ++scanit;
2772 }
2773 ++it;
2774 }
2775 return out;
2776}
2777
2778CountedPtr< Scantable >
2779 STMath::invertPhase( const CountedPtr < Scantable >& in )
2780{
2781 return applyToPol(in, &STPol::invertPhase, Float(0.0));
2782}
2783
2784CountedPtr< Scantable >
2785 STMath::rotateXYPhase( const CountedPtr < Scantable >& in, float phase )
2786{
2787 return applyToPol(in, &STPol::rotatePhase, Float(phase));
2788}
2789
2790CountedPtr< Scantable >
2791 STMath::rotateLinPolPhase( const CountedPtr < Scantable >& in, float phase )
2792{
2793 return applyToPol(in, &STPol::rotateLinPolPhase, Float(phase));
2794}
2795
2796CountedPtr< Scantable > STMath::applyToPol( const CountedPtr<Scantable>& in,
2797 STPol::polOperation fptr,
2798 Float phase )
2799{
2800 CountedPtr< Scantable > out = getScantable(in, false);
2801 Table& tout = out->table();
2802 Block<String> cols(4);
2803 cols[0] = String("SCANNO");
2804 cols[1] = String("BEAMNO");
2805 cols[2] = String("IFNO");
2806 cols[3] = String("CYCLENO");
2807 TableIterator iter(tout, cols);
2808 CountedPtr<STPol> stpol = STPol::getPolClass(out->factories_,
2809 out->getPolType() );
2810 while (!iter.pastEnd()) {
2811 Table t = iter.table();
2812 ArrayColumn<Float> speccol(t, "SPECTRA");
2813 ScalarColumn<uInt> focidcol(t, "FOCUS_ID");
2814 Matrix<Float> pols(speccol.getColumn());
2815 try {
2816 stpol->setSpectra(pols);
2817 Float fang,fhand;
2818 fang = in->focusTable_.getTotalAngle(focidcol(0));
2819 fhand = in->focusTable_.getFeedHand(focidcol(0));
2820 stpol->setPhaseCorrections(fang, fhand);
2821 // use a member function pointer in STPol. This only works on
2822 // the STPol pointer itself, not the Counted Pointer so
2823 // derefernce it.
2824 (&(*(stpol))->*fptr)(phase);
2825 speccol.putColumn(stpol->getSpectra());
2826 } catch (AipsError& e) {
2827 //delete stpol;stpol=0;
2828 throw(e);
2829 }
2830 ++iter;
2831 }
2832 //delete stpol;stpol=0;
2833 return out;
2834}
2835
2836CountedPtr< Scantable >
2837 STMath::swapPolarisations( const CountedPtr< Scantable > & in )
2838{
2839 CountedPtr< Scantable > out = getScantable(in, false);
2840 Table& tout = out->table();
2841 Table t0 = tout(tout.col("POLNO") == 0);
2842 Table t1 = tout(tout.col("POLNO") == 1);
2843 if ( t0.nrow() != t1.nrow() )
2844 throw(AipsError("Inconsistent number of polarisations"));
2845 ArrayColumn<Float> speccol0(t0, "SPECTRA");
2846 ArrayColumn<uChar> flagcol0(t0, "FLAGTRA");
2847 ArrayColumn<Float> speccol1(t1, "SPECTRA");
2848 ArrayColumn<uChar> flagcol1(t1, "FLAGTRA");
2849 Matrix<Float> s0 = speccol0.getColumn();
2850 Matrix<uChar> f0 = flagcol0.getColumn();
2851 speccol0.putColumn(speccol1.getColumn());
2852 flagcol0.putColumn(flagcol1.getColumn());
2853 speccol1.putColumn(s0);
2854 flagcol1.putColumn(f0);
2855 return out;
2856}
2857
2858CountedPtr< Scantable >
2859 STMath::averagePolarisations( const CountedPtr< Scantable > & in,
2860 const std::vector<bool>& mask,
2861 const std::string& weight )
2862{
2863 if (in->npol() < 2 )
2864 throw(AipsError("averagePolarisations can only be applied to two or more"
2865 "polarisations"));
2866 bool insitu = insitu_;
2867 setInsitu(false);
2868 CountedPtr< Scantable > pols = getScantable(in, true);
2869 setInsitu(insitu);
2870 Table& tout = pols->table();
2871 std::string taql = "SELECT FROM $1 WHERE POLNO IN [0,1]";
2872 Table tab = tableCommand(taql, in->table());
2873 if (tab.nrow() == 0 )
2874 throw(AipsError("Could not find any rows with POLNO==0 and POLNO==1"));
2875 TableCopy::copyRows(tout, tab);
2876 TableVector<uInt> vec(tout, "POLNO");
2877 vec = 0;
2878 pols->table_.rwKeywordSet().define("nPol", Int(1));
2879 pols->table_.rwKeywordSet().define("POLTYPE", String("stokes"));
2880 //pols->table_.rwKeywordSet().define("POLTYPE", in->getPolType());
2881 std::vector<CountedPtr<Scantable> > vpols;
2882 vpols.push_back(pols);
2883 CountedPtr< Scantable > out = average(vpols, mask, weight, "SCAN");
2884 return out;
2885}
2886
2887CountedPtr< Scantable >
2888 STMath::averageBeams( const CountedPtr< Scantable > & in,
2889 const std::vector<bool>& mask,
2890 const std::string& weight )
2891{
2892 bool insitu = insitu_;
2893 setInsitu(false);
2894 CountedPtr< Scantable > beams = getScantable(in, false);
2895 setInsitu(insitu);
2896 Table& tout = beams->table();
2897 // give all rows the same BEAMNO
2898 TableVector<uInt> vec(tout, "BEAMNO");
2899 vec = 0;
2900 beams->table_.rwKeywordSet().define("nBeam", Int(1));
2901 std::vector<CountedPtr<Scantable> > vbeams;
2902 vbeams.push_back(beams);
2903 CountedPtr< Scantable > out = average(vbeams, mask, weight, "SCAN");
2904 return out;
2905}
2906
2907
2908CountedPtr< Scantable >
2909 asap::STMath::frequencyAlign( const CountedPtr< Scantable > & in,
2910 const std::string & refTime,
2911 const std::string & method)
2912{
2913 LogIO os( casa::LogOrigin("STMath", "frequencyAlign()", WHERE));
2914 // clone as this is not working insitu
2915 bool insitu = insitu_;
2916 setInsitu(false);
2917 CountedPtr< Scantable > out = getScantable(in, false);
2918 setInsitu(insitu);
2919 Table& tout = out->table();
2920 // Get reference Epoch to time of first row or given String
2921 Unit DAY(String("d"));
2922 MEpoch::Ref epochRef(in->getTimeReference());
2923 MEpoch refEpoch;
2924 if (refTime.length()>0) {
2925 Quantum<Double> qt;
2926 if (MVTime::read(qt,refTime)) {
2927 MVEpoch mv(qt);
2928 refEpoch = MEpoch(mv, epochRef);
2929 } else {
2930 throw(AipsError("Invalid format for Epoch string"));
2931 }
2932 } else {
2933 refEpoch = in->timeCol_(0);
2934 }
2935 MPosition refPos = in->getAntennaPosition();
2936
2937 InterpolateArray1D<Double,Float>::InterpolationMethod interp = stringToIMethod(method);
2938 /*
2939 // Comment from MV.
2940 // the following code has been commented out because different FREQ_IDs have to be aligned together even
2941 // if the frame doesn't change. So far, lack of this check didn't cause any problems.
2942 // test if user frame is different to base frame
2943 if ( in->frequencies().getFrameString(true)
2944 == in->frequencies().getFrameString(false) ) {
2945 throw(AipsError("Can't convert as no output frame has been set"
2946 " (use set_freqframe) or it is aligned already."));
2947 }
2948 */
2949 MFrequency::Types system = in->frequencies().getFrame();
2950 MVTime mvt(refEpoch.getValue());
2951 String epochout = mvt.string(MVTime::YMD) + String(" (") + refEpoch.getRefString() + String(")");
2952 os << "Aligning at reference Epoch " << epochout
2953 << " in frame " << MFrequency::showType(system) << LogIO::POST;
2954 // set up the iterator
2955 Block<String> cols(4);
2956 // select by constant direction
2957 cols[0] = String("SRCNAME");
2958 cols[1] = String("BEAMNO");
2959 // select by IF ( no of channels varies over this )
2960 cols[2] = String("IFNO");
2961 // select by restfrequency
2962 cols[3] = String("MOLECULE_ID");
2963 TableIterator iter(tout, cols);
2964 while ( !iter.pastEnd() ) {
2965 Table t = iter.table();
2966 ROScalarColumn<String> snCol(t, "SRCNAME");
2967 os << "Aligning to position of source '" << snCol(0) << "'" << LogIO::POST;
2968 MDirection::ROScalarColumn dirCol(t, "DIRECTION");
2969 TableIterator fiter(t, "FREQ_ID");
2970 // determine nchan from the first row. This should work as
2971 // we are iterating over BEAMNO and IFNO
2972 // we should have constant direction
2973
2974 ROArrayColumn<Float> sCol(t, "SPECTRA");
2975 const MDirection direction = dirCol(0);
2976 const uInt nchan = sCol(0).nelements();
2977
2978 // skip operations if there is nothing to align
2979 if (fiter.pastEnd()) {
2980 continue;
2981 }
2982
2983 Table ftab = fiter.table();
2984 // align all frequency ids with respect to the first encountered id
2985 ScalarColumn<uInt> freqidCol(ftab, "FREQ_ID");
2986 // get the SpectralCoordinate for the freqid, which we are iterating over
2987 SpectralCoordinate sC = \
2988 in->frequencies().getSpectralCoordinate(freqidCol(0));
2989 FrequencyAligner<Float> fa( sC, nchan, refEpoch,
2990 direction, refPos, system );
2991 // realign the SpectralCoordinate and put into the output Scantable
2992 Vector<String> units(1);
2993 units = String("Hz");
2994 Bool linear=True;
2995 SpectralCoordinate sc2 = fa.alignedSpectralCoordinate(linear);
2996 sc2.setWorldAxisUnits(units);
2997 const uInt id = out->frequencies().addEntry(sc2.referencePixel()[0],
2998 sc2.referenceValue()[0],
2999 sc2.increment()[0]);
3000 while ( !fiter.pastEnd() ) {
3001
3002 ftab = fiter.table();
3003 // spectral coordinate for the current FREQ_ID
3004 ScalarColumn<uInt> freqidCol2(ftab, "FREQ_ID");
3005 sC = in->frequencies().getSpectralCoordinate(freqidCol2(0));
3006 // create the "global" abcissa for alignment with same FREQ_ID
3007 Vector<Double> abc(nchan);
3008 for (uInt i=0; i<nchan; i++) {
3009 Double w;
3010 sC.toWorld(w,Double(i));
3011 abc[i] = w;
3012 }
3013 TableVector<uInt> tvec(ftab, "FREQ_ID");
3014 // assign new frequency id to all rows
3015 tvec = id;
3016 // cache abcissa for same time stamps, so iterate over those
3017 TableIterator timeiter(ftab, "TIME");
3018 while ( !timeiter.pastEnd() ) {
3019 Table tab = timeiter.table();
3020 ArrayColumn<Float> specCol(tab, "SPECTRA");
3021 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
3022 MEpoch::ROScalarColumn timeCol(tab, "TIME");
3023 // use align abcissa cache after the first row
3024 // these rows should be just be POLNO
3025 bool first = true;
3026 for (int i=0; i<int(tab.nrow()); ++i) {
3027 // input values
3028 Vector<uChar> flag = flagCol(i);
3029 Vector<Bool> mask(flag.shape());
3030 Vector<Float> specOut, spec;
3031 spec = specCol(i);
3032 Vector<Bool> maskOut;Vector<uChar> flagOut;
3033 convertArray(mask, flag);
3034 // alignment
3035 Bool ok = fa.align(specOut, maskOut, abc, spec,
3036 mask, timeCol(i), !first,
3037 interp, False);
3038 (void) ok; // unused stop compiler nagging
3039 // back into scantable
3040 flagOut.resize(maskOut.nelements());
3041 convertArray(flagOut, maskOut);
3042 flagCol.put(i, flagOut);
3043 specCol.put(i, specOut);
3044 // start abcissa caching
3045 first = false;
3046 }
3047 // next timestamp
3048 ++timeiter;
3049 }
3050 // next FREQ_ID
3051 ++fiter;
3052 }
3053 // next aligner
3054 ++iter;
3055 }
3056 // set this afterwards to ensure we are doing insitu correctly.
3057 out->frequencies().setFrame(system, true);
3058 return out;
3059}
3060
3061CountedPtr<Scantable>
3062 asap::STMath::convertPolarisation( const CountedPtr<Scantable>& in,
3063 const std::string & newtype )
3064{
3065 if (in->npol() != 2 && in->npol() != 4)
3066 throw(AipsError("Can only convert two or four polarisations."));
3067 if ( in->getPolType() == newtype )
3068 throw(AipsError("No need to convert."));
3069 if ( ! in->selector_.empty() )
3070 throw(AipsError("Can only convert whole scantable. Unset the selection."));
3071 bool insitu = insitu_;
3072 setInsitu(false);
3073 CountedPtr< Scantable > out = getScantable(in, true);
3074 setInsitu(insitu);
3075 Table& tout = out->table();
3076 tout.rwKeywordSet().define("POLTYPE", String(newtype));
3077
3078 Block<String> cols(4);
3079 cols[0] = "SCANNO";
3080 cols[1] = "CYCLENO";
3081 cols[2] = "BEAMNO";
3082 cols[3] = "IFNO";
3083 TableIterator it(in->originalTable_, cols);
3084 String basetype = in->getPolType();
3085 STPol* stpol = STPol::getPolClass(in->factories_, basetype);
3086 try {
3087 while ( !it.pastEnd() ) {
3088 Table tab = it.table();
3089 uInt row = tab.rowNumbers()[0];
3090 stpol->setSpectra(in->getPolMatrix(row));
3091 Float fang,fhand;
3092 fang = in->focusTable_.getTotalAngle(in->mfocusidCol_(row));
3093 fhand = in->focusTable_.getFeedHand(in->mfocusidCol_(row));
3094 stpol->setPhaseCorrections(fang, fhand);
3095 Int npolout = 0;
3096 for (uInt i=0; i<tab.nrow(); ++i) {
3097 Vector<Float> outvec = stpol->getSpectrum(i, newtype);
3098 if ( outvec.nelements() > 0 ) {
3099 tout.addRow();
3100 TableCopy::copyRows(tout, tab, tout.nrow()-1, 0, 1);
3101 ArrayColumn<Float> sCol(tout,"SPECTRA");
3102 ScalarColumn<uInt> pCol(tout,"POLNO");
3103 sCol.put(tout.nrow()-1 ,outvec);
3104 pCol.put(tout.nrow()-1 ,uInt(npolout));
3105 npolout++;
3106 }
3107 }
3108 tout.rwKeywordSet().define("nPol", npolout);
3109 ++it;
3110 }
3111 } catch (AipsError& e) {
3112 delete stpol;
3113 throw(e);
3114 }
3115 delete stpol;
3116 return out;
3117}
3118
3119CountedPtr< Scantable >
3120 asap::STMath::mxExtract( const CountedPtr< Scantable > & in,
3121 const std::string & scantype )
3122{
3123 bool insitu = insitu_;
3124 setInsitu(false);
3125 CountedPtr< Scantable > out = getScantable(in, true);
3126 setInsitu(insitu);
3127 Table& tout = out->table();
3128 std::string taql = "SELECT FROM $1 WHERE BEAMNO != REFBEAMNO";
3129 if (scantype == "on") {
3130 taql = "SELECT FROM $1 WHERE BEAMNO == REFBEAMNO";
3131 }
3132 Table tab = tableCommand(taql, in->table());
3133 TableCopy::copyRows(tout, tab);
3134 if (scantype == "on") {
3135 // re-index SCANNO to 0
3136 TableVector<uInt> vec(tout, "SCANNO");
3137 vec = 0;
3138 }
3139 return out;
3140}
3141
3142std::vector<float>
3143 asap::STMath::fft( const casa::CountedPtr< Scantable > & in,
3144 const std::vector<int>& whichrow,
3145 bool getRealImag )
3146{
3147 std::vector<float> res;
3148 Table tab = in->table();
3149 std::vector<bool> mask;
3150
3151 if (whichrow.size() < 1) { // for all rows (by default)
3152 int nrow = int(tab.nrow());
3153 for (int i = 0; i < nrow; ++i) {
3154 res = in->execFFT(i, mask, getRealImag);
3155 }
3156 } else { // for specified rows
3157 for (uInt i = 0; i < whichrow.size(); ++i) {
3158 res = in->execFFT(i, mask, getRealImag);
3159 }
3160 }
3161
3162 return res;
3163}
3164
3165
3166CountedPtr<Scantable>
3167 asap::STMath::lagFlag( const CountedPtr<Scantable>& in,
3168 double start, double end,
3169 const std::string& mode )
3170{
3171 CountedPtr<Scantable> out = getScantable(in, false);
3172 Table& tout = out->table();
3173 TableIterator iter(tout, "FREQ_ID");
3174 FFTServer<Float,Complex> ffts;
3175
3176 while ( !iter.pastEnd() ) {
3177 Table tab = iter.table();
3178 Double rp,rv,inc;
3179 ROTableRow row(tab);
3180 const TableRecord& rec = row.get(0);
3181 uInt freqid = rec.asuInt("FREQ_ID");
3182 out->frequencies().getEntry(rp, rv, inc, freqid);
3183 ArrayColumn<Float> specCol(tab, "SPECTRA");
3184 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
3185
3186 for (int i=0; i<int(tab.nrow()); ++i) {
3187 Vector<Float> spec = specCol(i);
3188 Vector<uChar> flag = flagCol(i);
3189 std::vector<bool> mask;
3190 for (uInt j = 0; j < flag.nelements(); ++j) {
3191 mask.push_back(!(flag[j]>0));
3192 }
3193 mathutil::doZeroOrderInterpolation(spec, mask);
3194
3195 Vector<Complex> lags;
3196 ffts.fft0(lags, spec);
3197
3198 Int lag0(start+0.5);
3199 Int lag1(end+0.5);
3200 if (mode == "frequency") {
3201 lag0 = Int(spec.nelements()*abs(inc)/(start)+0.5);
3202 lag1 = Int(spec.nelements()*abs(inc)/(end)+0.5);
3203 }
3204 Int lstart = max(0, lag0);
3205 Int lend = min(Int(lags.nelements()-1), lag1);
3206 if (lstart == lend) {
3207 lags[lstart] = Complex(0.0);
3208 } else {
3209 if (lstart > lend) {
3210 Int tmp = lend;
3211 lend = lstart;
3212 lstart = tmp;
3213 }
3214 for (int j=lstart; j <=lend ;++j) {
3215 lags[j] = Complex(0.0);
3216 }
3217 }
3218
3219 ffts.fft0(spec, lags);
3220
3221 specCol.put(i, spec);
3222 }
3223 ++iter;
3224 }
3225 return out;
3226}
3227
3228// Averaging spectra with different channel/resolution
3229CountedPtr<Scantable>
3230STMath::new_average( const std::vector<CountedPtr<Scantable> >& in,
3231 const bool& compel,
3232 const std::vector<bool>& mask,
3233 const std::string& weight,
3234 const std::string& avmode )
3235 throw ( casa::AipsError )
3236{
3237 LogIO os( LogOrigin( "STMath", "new_average()", WHERE ) ) ;
3238 if ( avmode == "SCAN" && in.size() != 1 )
3239 throw(AipsError("Can't perform 'SCAN' averaging on multiple tables.\n"
3240 "Use merge first."));
3241
3242 CountedPtr<Scantable> out ; // processed result
3243 if ( compel ) {
3244 std::vector< CountedPtr<Scantable> > newin ; // input for average process
3245 uInt insize = in.size() ; // number of input scantables
3246
3247 // setup newin
3248 bool oldInsitu = insitu_ ;
3249 setInsitu( false ) ;
3250 newin.resize( insize ) ;
3251 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
3252 newin[itable] = getScantable( in[itable], false ) ;
3253 }
3254 setInsitu( oldInsitu ) ;
3255
3256 // warning
3257 os << "Average spectra with different spectral resolution" << LogIO::POST ;
3258
3259 // temporarily set coordinfo
3260 vector<string> oldinfo( insize ) ;
3261 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
3262 vector<string> coordinfo = in[itable]->getCoordInfo() ;
3263 oldinfo[itable] = coordinfo[0] ;
3264 coordinfo[0] = "Hz" ;
3265 newin[itable]->setCoordInfo( coordinfo ) ;
3266 }
3267
3268 ostringstream oss ;
3269
3270 // check IF frequency coverage
3271 // freqid: list of FREQ_ID, which is used, in each table
3272 // iffreq: list of minimum and maximum frequency for each FREQ_ID in
3273 // each table
3274 // freqid[insize][numIF]
3275 // freqid: [[id00, id01, ...],
3276 // [id10, id11, ...],
3277 // ...
3278 // [idn0, idn1, ...]]
3279 // iffreq[insize][numIF*2]
3280 // iffreq: [[min_id00, max_id00, min_id01, max_id01, ...],
3281 // [min_id10, max_id10, min_id11, max_id11, ...],
3282 // ...
3283 // [min_idn0, max_idn0, min_idn1, max_idn1, ...]]
3284 //os << "Check IF settings in each table" << LogIO::POST ;
3285 vector< vector<uInt> > freqid( insize );
3286 vector< vector<double> > iffreq( insize ) ;
3287 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
3288 Vector<uInt> freqIds = newin[itable]->mfreqidCol_.getColumn() ;
3289 vector<uInt> uniqueFreqId = newin[itable]->getNumbers(newin[itable]->mfreqidCol_) ;
3290 for ( vector<uInt>::iterator i = uniqueFreqId.begin() ;
3291 i != uniqueFreqId.end() ; i++ ) {
3292 //os << "itable = " << itable << ": IF " << id << " is included in the list" << LogIO::POST ;
3293 uInt target = 0 ;
3294 while ( freqIds[target] != *i )
3295 target++ ;
3296 vector<double> abcissa = newin[itable]->getAbcissa( target ) ;
3297 freqid[itable].push_back( *i ) ;
3298 double incr = abs( abcissa[1] - abcissa[0] ) ;
3299 iffreq[itable].push_back( (*min_element(abcissa.begin(),abcissa.end()))-0.5*incr ) ;
3300 iffreq[itable].push_back( (*max_element(abcissa.begin(),abcissa.end()))+0.5*incr ) ;
3301 }
3302 }
3303
3304 // debug
3305// os << "IF settings summary:" << endl ;
3306// for ( uInt i = 0 ; i < freqid.size() ; i++ ) {
3307// os << " Table" << i << endl ;
3308// for ( uInt j = 0 ; j < freqid[i].size() ; j++ ) {
3309// os << " id = " << freqid[i][j] << " (min,max) = (" << iffreq[i][2*j] << "," << iffreq[i][2*j+1] << ")" << endl ;
3310// }
3311// }
3312// os << endl ;
3313// os.post() ;
3314
3315 // IF grouping based on their frequency coverage
3316 // ifgrp: number of member in each IF group
3317 // ifgrp[numgrp]
3318 // ifgrp: [n0, n1, ...]
3319 //os << "IF grouping based on their frequency coverage" << LogIO::POST ;
3320
3321 // parameter for IF grouping
3322 // groupmode = OR retrieve all region
3323 // AND only retrieve overlaped region
3324 //string groupmode = "AND" ;
3325 string groupmode = "OR" ;
3326 uInt sizecr = 0 ;
3327 if ( groupmode == "AND" )
3328 sizecr = 1 ;
3329 else if ( groupmode == "OR" )
3330 sizecr = 0 ;
3331
3332 vector<double> sortedfreq ;
3333 for ( uInt i = 0 ; i < iffreq.size() ; i++ ) {
3334 for ( uInt j = 0 ; j < iffreq[i].size() ; j++ ) {
3335 if ( count( sortedfreq.begin(), sortedfreq.end(), iffreq[i][j] ) == 0 )
3336 sortedfreq.push_back( iffreq[i][j] ) ;
3337 }
3338 }
3339 sort( sortedfreq.begin(), sortedfreq.end() ) ;
3340 vector<uInt> ifgrp( sortedfreq.size()-1, 0 ) ;
3341 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
3342 for ( uInt iif = 0 ; iif < freqid[itable].size() ; iif++ ) {
3343 double range0 = iffreq[itable][2*iif] ;
3344 double range1 = iffreq[itable][2*iif+1] ;
3345 for ( uInt j = 0 ; j < sortedfreq.size()-1 ; j++ ) {
3346 double fmin = max( range0, sortedfreq[j] ) ;
3347 double fmax = min( range1, sortedfreq[j+1] ) ;
3348 if ( fmin < fmax ) {
3349 ifgrp[j]++ ;
3350 }
3351 }
3352 }
3353 }
3354
3355 // Grouping continuous IF groups (without frequency gap)
3356 // freqgrp: list of IF group indexes in each frequency group
3357 // freqgrp[numgrp][nummember]
3358 // freqgrp: [[ifgrp00, ifgrp01, ifgrp02, ...],
3359 // [ifgrp10, ifgrp11, ifgrp12, ...],
3360 // ...
3361 // [ifgrpn0, ifgrpn1, ifgrpn2, ...]]
3362 // grprange[2*numgrp]
3363 // grprange: [fmin0,fmax0,fmin1,fmax1,...]
3364 vector< vector<uInt> > freqgrp ;
3365 vector<double> grprange ;
3366 vector<uInt> grpedge ;
3367 for ( uInt igrp = 0 ; igrp < ifgrp.size() ; igrp++ ) {
3368 if ( ifgrp[igrp] <= sizecr ) {
3369 grpedge.push_back( igrp ) ;
3370 }
3371 }
3372 grpedge.push_back( ifgrp.size() ) ;
3373 uInt itmp = 0 ;
3374 for ( uInt i = 0 ; i < grpedge.size() ; i++ ) {
3375 int n = grpedge[i] - itmp ;
3376 if ( n > 0 ) {
3377 vector<uInt> members( n ) ;
3378 for ( int j = 0 ; j < n ; j++ ) {
3379 members[j] = itmp+j ;
3380 }
3381 freqgrp.push_back( members ) ;
3382 grprange.push_back( sortedfreq[itmp] ) ;
3383 grprange.push_back( sortedfreq[grpedge[i]] ) ;
3384 }
3385 itmp += n + 1 ;
3386 }
3387
3388 // print frequency group
3389 oss.str("") ;
3390 oss << "Frequency Group summary: " << endl ;
3391 oss << " GROUP_ID: [FREQ_MIN, FREQ_MAX]" << endl ;
3392 for ( uInt i = 0 ; i < freqgrp.size() ; i++ ) {
3393 oss << " GROUP " << setw( 2 ) << i << ": [" << grprange[2*i] << "," << grprange[2*i+1] << "]" ;
3394 oss << endl ;
3395 }
3396 oss << endl ;
3397 os << oss.str() << LogIO::POST ;
3398
3399 // groups: list of frequency group index whose frequency range overlaps
3400 // with that of each table and IF
3401 // groups[numtable][numIF]
3402 // groups: [[grpx, grpy,...],
3403 // [grpa, grpb,...],
3404 // ...
3405 // [grpk, grpm,...]]
3406 vector< vector<uInt> > groups( insize ) ;
3407 for ( uInt i = 0 ; i < insize ; i++ ) {
3408 groups[i].resize( freqid[i].size() ) ;
3409 }
3410 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
3411 for ( uInt ifreq = 0 ; ifreq < freqid[itable].size() ; ifreq++ ) {
3412 double minf = iffreq[itable][2*ifreq] ;
3413 uInt groupid ;
3414 for ( uInt igrp = 0 ; igrp < freqgrp.size() ; igrp++ ) {
3415 vector<uInt> memberlist = freqgrp[igrp] ;
3416 if ( (minf >= grprange[2*igrp]) && (minf <= grprange[2*igrp+1]) ) {
3417 groupid = igrp ;
3418 break ;
3419 }
3420 }
3421 groups[itable][ifreq] = groupid ;
3422 }
3423 }
3424
3425
3426 // print membership
3427 oss.str("") ;
3428 for ( uInt i = 0 ; i < insize ; i++ ) {
3429 oss << "Table " << i << endl ;
3430 for ( uInt j = 0 ; j < groups[i].size() ; j++ ) {
3431 oss << " FREQ_ID " << setw( 2 ) << freqid[i][j] << ": " ;
3432 oss << setw( 2 ) << groups[i][j] ;
3433 oss << endl ;
3434 }
3435 }
3436 os << oss.str() << LogIO::POST ;
3437
3438 // reset SCANNO and IFNO/FREQ_ID: IF is reset by the result of sortation
3439 //os << "All IF number is set to IF group index" << LogIO::POST ;
3440 // reset SCANNO only when avmode != "SCAN"
3441 if ( avmode != "SCAN" ) {
3442 os << "All scan number is set to 0" << LogIO::POST ;
3443 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
3444 uInt nrow = newin[itable]->nrow() ;
3445 Vector<uInt> resetScan( nrow, 0 ) ;
3446 newin[itable]->scanCol_.putColumn( resetScan ) ;
3447 }
3448 }
3449
3450 // reset spectra and flagtra: align spectral resolution
3451 //os << "Align spectral resolution" << LogIO::POST ;
3452 // gmaxdnu: the coarsest frequency resolution in the frequency group
3453 // gminfreq: lower frequency edge of the frequency group
3454 // gnchan: number of channels for the frequency group
3455 vector<double> gmaxdnu( freqgrp.size(), 0.0 ) ;
3456 vector<double> gminfreq( freqgrp.size() ) ;
3457 vector<double> gnchan( freqgrp.size() ) ;
3458 for ( uInt i = 0 ; i < insize ; i++ ) {
3459 vector<uInt> members = groups[i] ;
3460 for ( uInt j = 0 ; j < members.size() ; j++ ) {
3461 uInt groupid = members[j] ;
3462 Double rp,rv,ic ;
3463 newin[i]->frequencies().getEntry( rp, rv, ic, j ) ;
3464 if ( abs(ic) > abs(gmaxdnu[groupid]) )
3465 gmaxdnu[groupid] = ic ;
3466 }
3467 }
3468 for ( uInt igrp = 0 ; igrp < freqgrp.size() ; igrp++ ) {
3469 gminfreq[igrp] = grprange[2*igrp] ;
3470 double maxfreq = grprange[2*igrp+1] ;
3471 gnchan[igrp] = (int)(abs((maxfreq-gminfreq[igrp])/gmaxdnu[igrp])+0.9) ;
3472 }
3473
3474 // regrid spectral data and update frequency info
3475 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
3476 Vector<uInt> oldFreqId = newin[itable]->mfreqidCol_.getColumn() ;
3477 Vector<uInt> newFreqId( oldFreqId.nelements() ) ;
3478
3479 // update MAIN
3480 for ( uInt irow = 0 ; irow < newin[itable]->nrow() ; irow++ ) {
3481 uInt groupid = groups[itable][oldFreqId[irow]] ;
3482 newFreqId[irow] = groupid ;
3483 newin[itable]->regridChannel( gnchan[groupid],
3484 gmaxdnu[groupid],
3485 gminfreq[groupid],
3486 irow ) ;
3487 }
3488 newin[itable]->mfreqidCol_.putColumn( newFreqId ) ;
3489 newin[itable]->ifCol_.putColumn( newFreqId ) ;
3490
3491 // update FREQUENCIES
3492 Table tab = newin[itable]->frequencies().table() ;
3493 ScalarColumn<uInt> fIdCol( tab, "ID" ) ;
3494 ScalarColumn<Double> fRefPixCol( tab, "REFPIX" ) ;
3495 ScalarColumn<Double> fRefValCol( tab, "REFVAL" ) ;
3496 ScalarColumn<Double> fIncrCol( tab, "INCREMENT" ) ;
3497 if ( freqgrp.size() > tab.nrow() ) {
3498 tab.addRow( freqgrp.size()-tab.nrow() ) ;
3499 }
3500 for ( uInt irow = 0 ; irow < freqgrp.size() ; irow++ ) {
3501 Double refval = gminfreq[irow] + 0.5 * abs(gmaxdnu[irow]) ;
3502 Double refpix = (gmaxdnu[irow] > 0.0) ? 0 : gnchan[irow]-1 ;
3503 Double increment = gmaxdnu[irow] ;
3504 fIdCol.put( irow, irow ) ;
3505 fRefPixCol.put( irow, refpix ) ;
3506 fRefValCol.put( irow, refval ) ;
3507 fIncrCol.put( irow, increment ) ;
3508 }
3509 }
3510
3511 // set back coordinfo
3512 for ( uInt itable = 0 ; itable < insize ; itable++ ) {
3513 vector<string> coordinfo = newin[itable]->getCoordInfo() ;
3514 coordinfo[0] = oldinfo[itable] ;
3515 newin[itable]->setCoordInfo( coordinfo ) ;
3516 }
3517
3518 // average
3519 out = average( newin, mask, weight, avmode ) ;
3520 }
3521 else {
3522 // simple average
3523 out = average( in, mask, weight, avmode ) ;
3524 }
3525
3526 return out;
3527}
3528
3529CountedPtr<Scantable> STMath::cwcal( const CountedPtr<Scantable>& s,
3530 const String calmode,
3531 const String antname )
3532{
3533 // frequency switch
3534 if ( calmode == "fs" ) {
3535 return cwcalfs( s, antname ) ;
3536 }
3537 else {
3538 vector<bool> masks = s->getMask( 0 ) ;
3539 vector<int> types ;
3540
3541 // save original table selection
3542 Table torg = s->table_ ;
3543
3544 // sky scan
3545 bool insitu = insitu_ ;
3546 insitu_ = false ;
3547 // share calibration scans before average with out
3548 CountedPtr<Scantable> out = getScantable( s, true ) ;
3549 insitu_ = insitu ;
3550 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::SKY ) ;
3551 out->attach() ;
3552 CountedPtr<Scantable> asky = averageWithinSession( out,
3553 masks,
3554 "TINT" ) ;
3555 // hot scan
3556 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::HOT ) ;
3557 out->attach() ;
3558 CountedPtr<Scantable> ahot = averageWithinSession( out,
3559 masks,
3560 "TINT" ) ;
3561 // cold scan
3562 CountedPtr<Scantable> acold ;
3563// out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::COLD ) ;
3564// out->attach() ;
3565// CountedPtr<Scantable> acold = averageWithinSession( out,
3566// masks,
3567// "TINT" ) ;
3568
3569 // off scan
3570 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::PSOFF ) ;
3571 out->attach() ;
3572 CountedPtr<Scantable> aoff = averageWithinSession( out,
3573 masks,
3574 "TINT" ) ;
3575
3576 // on scan
3577 s->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::PSON ) ;
3578 s->attach() ;
3579 out->table_ = out->originalTable_ ;
3580 out->attach() ;
3581 out->table().addRow( s->nrow() ) ;
3582 copyRows( out->table(), s->table(), 0, 0, s->nrow(), False, True, False ) ;
3583
3584 // process each on scan
3585 STSelector sel ;
3586 vector<string> cols( 3 ) ;
3587 cols[0] = "BEAMNO" ;
3588 cols[1] = "POLNO" ;
3589 cols[2] = "IFNO" ;
3590 STIdxIter2 iter(out, cols);
3591 while ( !iter.pastEnd() ) {
3592 Record ids = iter.currentValue();
3593 stringstream ss ;
3594 ss << "SELECT FROM $1 WHERE "
3595 << "BEAMNO==" << ids.asuInt("BEAMNO") << "&&"
3596 << "POLNO==" << ids.asuInt("POLNO") << "&&"
3597 << "IFNO==" << ids.asuInt("IFNO") ;
3598 //cout << "TaQL string: " << ss.str() << endl ;
3599 sel.setTaQL( ss.str() ) ;
3600 aoff->setSelection( sel ) ;
3601 ahot->setSelection( sel ) ;
3602 asky->setSelection( sel ) ;
3603 Vector<uInt> rows = iter.getRows( SHARE ) ;
3604 // out should be an exact copy of s except that SPECTRA column is empty
3605 calibrateCW( out, s, aoff, asky, ahot, acold, rows, antname ) ;
3606 aoff->unsetSelection() ;
3607 ahot->unsetSelection() ;
3608 asky->unsetSelection() ;
3609 sel.reset() ;
3610 iter.next() ;
3611 }
3612 s->table_ = torg ;
3613 s->attach() ;
3614
3615 // flux unit
3616 out->setFluxUnit( "K" ) ;
3617
3618 return out ;
3619 }
3620}
3621
3622CountedPtr<Scantable> STMath::almacal( const CountedPtr<Scantable>& s,
3623 const String calmode )
3624{
3625 // frequency switch
3626 if ( calmode == "fs" ) {
3627 return almacalfs( s ) ;
3628 }
3629 else {
3630// double t0, t1 ;
3631// t0 = mathutil::gettimeofday_sec() ;
3632 vector<bool> masks = s->getMask( 0 ) ;
3633
3634 // save original table selection
3635 Table torg = s->table_ ;
3636
3637 // off scan
3638 // TODO 2010/01/08 TN
3639 // Grouping by time should be needed before averaging.
3640 // Each group must have own unique SCANNO (should be renumbered).
3641 // See PIPELINE/SDCalibration.py
3642 bool insitu = insitu_ ;
3643 insitu_ = false ;
3644 // share off scan before average with out
3645 CountedPtr<Scantable> out = getScantable( s, true ) ;
3646 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::PSOFF ) ;
3647 out->attach() ;
3648 insitu_ = insitu ;
3649 CountedPtr<Scantable> aoff = averageWithinSession( out,
3650 masks,
3651 "TINT" ) ;
3652
3653 // on scan
3654// t0 = mathutil::gettimeofday_sec() ;
3655 s->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::PSON ) ;
3656 s->attach() ;
3657 out->table_ = out->originalTable_ ;
3658 out->attach() ;
3659 out->table().addRow( s->nrow() ) ;
3660 copyRows( out->table(), s->table(), 0, 0, s->nrow(), False ) ;
3661// t1 = mathutil::gettimeofday_sec() ;
3662// cout << "elapsed time for preparing output table: " << t1-t0 << " sec" << endl ;
3663
3664 // process each on scan
3665// t0 = mathutil::gettimeofday_sec() ;
3666
3667 // using STIdxIter2
3668 vector<string> cols( 3 ) ;
3669 cols[0] = "BEAMNO" ;
3670 cols[1] = "POLNO" ;
3671 cols[2] = "IFNO" ;
3672 STIdxIter2 iter( out, cols ) ;
3673 STSelector sel ;
3674 while ( !iter.pastEnd() ) {
3675 Record ids = iter.currentValue() ;
3676 stringstream ss ;
3677 ss << "SELECT FROM $1 WHERE "
3678 << "BEAMNO==" << ids.asuInt(cols[0]) << "&&"
3679 << "POLNO==" << ids.asuInt(cols[1]) << "&&"
3680 << "IFNO==" << ids.asuInt(cols[2]) ;
3681 //cout << "TaQL string: " << ss.str() << endl ;
3682 sel.setTaQL( ss.str() ) ;
3683 aoff->setSelection( sel ) ;
3684 Vector<uInt> rows = iter.getRows( SHARE ) ;
3685 // out should be an exact copy of s except that SPECTRA column is empty
3686 calibrateALMA( out, s, aoff, rows ) ;
3687 aoff->unsetSelection() ;
3688 sel.reset() ;
3689 iter.next() ;
3690 }
3691 s->table_ = torg ;
3692 s->attach() ;
3693
3694// t1 = mathutil::gettimeofday_sec() ;
3695// cout << "elapsed time for calibration: " << t1-t0 << " sec" << endl ;
3696
3697 // flux unit
3698 out->setFluxUnit( "K" ) ;
3699
3700 return out ;
3701 }
3702}
3703
3704CountedPtr<Scantable> STMath::cwcalfs( const CountedPtr<Scantable>& s,
3705 const String antname )
3706{
3707 vector<int> types ;
3708
3709 // APEX calibration mode
3710 int apexcalmode = 1 ;
3711
3712 if ( antname.find( "APEX" ) != string::npos ) {
3713 // check if off scan exists or not
3714 STSelector sel = STSelector() ;
3715 //sel.setName( offstr1 ) ;
3716 types.push_back( SrcType::FLOOFF ) ;
3717 sel.setTypes( types ) ;
3718 try {
3719 s->setSelection( sel ) ;
3720 }
3721 catch ( AipsError &e ) {
3722 apexcalmode = 0 ;
3723 }
3724 sel.reset() ;
3725 }
3726 s->unsetSelection() ;
3727 types.clear() ;
3728
3729 vector<bool> masks = s->getMask( 0 ) ;
3730 CountedPtr<Scantable> ssig, sref ;
3731 //CountedPtr<Scantable> out ;
3732 bool insitu = insitu_ ;
3733 insitu_ = False ;
3734 CountedPtr<Scantable> out = getScantable( s, true ) ;
3735 insitu_ = insitu ;
3736
3737 if ( antname.find( "APEX" ) != string::npos ) {
3738 // APEX calibration
3739 // sky scan
3740 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::FLOSKY ) ;
3741 out->attach() ;
3742 CountedPtr<Scantable> askylo = averageWithinSession( out,
3743 masks,
3744 "TINT" ) ;
3745 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::FHISKY ) ;
3746 out->attach() ;
3747 CountedPtr<Scantable> askyhi = averageWithinSession( out,
3748 masks,
3749 "TINT" ) ;
3750
3751 // hot scan
3752 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::FLOHOT ) ;
3753 out->attach() ;
3754 CountedPtr<Scantable> ahotlo = averageWithinSession( out,
3755 masks,
3756 "TINT" ) ;
3757 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::FHIHOT ) ;
3758 out->attach() ;
3759 CountedPtr<Scantable> ahothi = averageWithinSession( out,
3760 masks,
3761 "TINT" ) ;
3762
3763 // cold scan
3764 CountedPtr<Scantable> acoldlo, acoldhi ;
3765// out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::FLOCOLD ) ;
3766// out->attach() ;
3767// CountedPtr<Scantable> acoldlo = averageWithinSession( out,
3768// masks,
3769// "TINT" ) ;
3770// out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::FHICOLD ) ;
3771// out->attach() ;
3772// CountedPtr<Scantable> acoldhi = averageWithinSession( out,
3773// masks,
3774// "TINT" ) ;
3775
3776 // ref scan
3777 insitu_ = false ;
3778 sref = getScantable( s, true ) ;
3779 CountedPtr<Scantable> rref = getScantable( s, true ) ;
3780 insitu_ = insitu ;
3781 rref->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::FSLO ) ;
3782 rref->attach() ;
3783 copyRows( sref->table_, rref->table_, 0, 0, rref->nrow(), False, True, False ) ;
3784
3785 // sig scan
3786 insitu_ = false ;
3787 ssig = getScantable( s, true ) ;
3788 CountedPtr<Scantable> rsig = getScantable( s, true ) ;
3789 insitu_ = insitu ;
3790 rsig->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::FSHI ) ;
3791 rsig->attach() ;
3792 copyRows( ssig->table_, rsig->table_, 0, 0, rsig->nrow(), False, True, False ) ;
3793
3794 if ( apexcalmode == 0 ) {
3795 // using STIdxIter2
3796 vector<string> cols( 3 ) ;
3797 cols[0] = "BEAMNO" ;
3798 cols[1] = "POLNO" ;
3799 cols[2] = "IFNO" ;
3800 STIdxIter2 iter(ssig, cols) ;
3801 STSelector sel ;
3802 vector< CountedPtr<Scantable> > on( 2 ) ;
3803 on[0] = rsig ;
3804 on[1] = rref ;
3805 vector< CountedPtr<Scantable> > sky( 2 ) ;
3806 sky[0] = askylo ;
3807 sky[1] = askyhi ;
3808 vector< CountedPtr<Scantable> > hot( 2 ) ;
3809 hot[0] = ahotlo ;
3810 hot[1] = ahothi ;
3811 vector< CountedPtr<Scantable> > cold( 2 ) ;
3812 while ( !iter.pastEnd() ) {
3813 Record ids = iter.currentValue() ;
3814 stringstream ss ;
3815 ss << "SELECT FROM $1 WHERE "
3816 << "BEAMNO==" << ids.asuInt("BEAMNO") << "&&"
3817 << "POLNO==" << ids.asuInt("POLNO") << "&&"
3818 << "IFNO==" << ids.asuInt("IFNO") ;
3819 //cout << "TaQL string: " << ss.str() << endl ;
3820 sel.setTaQL( ss.str() ) ;
3821 sky[0]->setSelection( sel ) ;
3822 sky[1]->setSelection( sel ) ;
3823 hot[0]->setSelection( sel ) ;
3824 hot[1]->setSelection( sel ) ;
3825 Vector<uInt> rows = iter.getRows( SHARE ) ;
3826 calibrateAPEXFS( ssig, sref, on, sky, hot, cold, rows ) ;
3827 sky[0]->unsetSelection() ;
3828 sky[1]->unsetSelection() ;
3829 hot[0]->unsetSelection() ;
3830 hot[1]->unsetSelection() ;
3831 sel.reset() ;
3832 iter.next() ;
3833 }
3834
3835 }
3836 else if ( apexcalmode == 1 ) {
3837 // APEX fs data with off scan
3838 // off scan
3839 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::FLOOFF ) ;
3840 out->attach() ;
3841 CountedPtr<Scantable> aofflo = averageWithinSession( out,
3842 masks,
3843 "TINT" ) ;
3844 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::FHIOFF ) ;
3845 out->attach() ;
3846 CountedPtr<Scantable> aoffhi = averageWithinSession( out,
3847 masks,
3848 "TINT" ) ;
3849
3850 // process each sig and ref scan
3851// STSelector sel ;
3852 vector<string> cols( 3 ) ;
3853 cols[0] = "BEAMNO" ;
3854 cols[1] = "POLNO" ;
3855 cols[2] = "IFNO" ;
3856 STIdxIter2 iter(ssig, cols);
3857 STSelector sel ;
3858 while ( !iter.pastEnd() ) {
3859 Record ids = iter.currentValue() ;
3860 stringstream ss ;
3861 ss << "SELECT FROM $1 WHERE "
3862 << "BEAMNO==" << ids.asuInt("BEAMNO") << "&&"
3863 << "POLNO==" << ids.asuInt("POLNO") << "&&"
3864 << "IFNO==" << ids.asuInt("IFNO") ;
3865 //cout << "TaQL string: " << ss.str() << endl ;
3866 sel.setTaQL( ss.str() ) ;
3867 aofflo->setSelection( sel ) ;
3868 ahotlo->setSelection( sel ) ;
3869 askylo->setSelection( sel ) ;
3870 Vector<uInt> rows = iter.getRows( SHARE ) ;
3871 calibrateCW( ssig, rsig, aofflo, askylo, ahotlo, acoldlo, rows, antname ) ;
3872 aofflo->unsetSelection() ;
3873 ahotlo->unsetSelection() ;
3874 askylo->unsetSelection() ;
3875 sel.reset() ;
3876 iter.next() ;
3877 }
3878 iter = STIdxIter2(sref, cols);
3879 while ( !iter.pastEnd() ) {
3880 Record ids = iter.currentValue() ;
3881 stringstream ss ;
3882 ss << "SELECT FROM $1 WHERE "
3883 << "BEAMNO==" << ids.asuInt("BEAMNO") << "&&"
3884 << "POLNO==" << ids.asuInt("POLNO") << "&&"
3885 << "IFNO==" << ids.asuInt("IFNO") ;
3886 //cout << "TaQL string: " << ss.str() << endl ;
3887 sel.setTaQL( ss.str() ) ;
3888 aoffhi->setSelection( sel ) ;
3889 ahothi->setSelection( sel ) ;
3890 askyhi->setSelection( sel ) ;
3891 Vector<uInt> rows = iter.getRows( SHARE ) ;
3892 calibrateCW( sref, rref, aoffhi, askyhi, ahothi, acoldhi, rows, antname ) ;
3893 aoffhi->unsetSelection() ;
3894 ahothi->unsetSelection() ;
3895 askyhi->unsetSelection() ;
3896 sel.reset() ;
3897 iter.next() ;
3898 }
3899 }
3900 }
3901 else {
3902 // non-APEX fs data
3903 // sky scan
3904 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::SKY ) ;
3905 out->attach() ;
3906 CountedPtr<Scantable> asky = averageWithinSession( out,
3907 masks,
3908 "TINT" ) ;
3909 STSelector sel = STSelector() ;
3910
3911 // hot scan
3912 out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::HOT ) ;
3913 out->attach() ;
3914 CountedPtr<Scantable> ahot = averageWithinSession( out,
3915 masks,
3916 "TINT" ) ;
3917
3918 // cold scan
3919 CountedPtr<Scantable> acold ;
3920// out->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::COLD ) ;
3921// out->attach() ;
3922// CountedPtr<Scantable> acold = averageWithinSession( out,
3923// masks,
3924// "TINT" ) ;
3925
3926 // ref scan
3927 bool insitu = insitu_ ;
3928 insitu_ = false ;
3929 sref = getScantable( s, true ) ;
3930 CountedPtr<Scantable> rref = getScantable( s, true ) ;
3931 insitu_ = insitu ;
3932 rref->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::PSOFF ) ;
3933 rref->attach() ;
3934 copyRows( sref->table_, rref->table_, 0, 0, rref->nrow(), False, True, False ) ;
3935
3936 // sig scan
3937 insitu_ = false ;
3938 ssig = getScantable( s, true ) ;
3939 CountedPtr<Scantable> rsig = getScantable( s, true ) ;
3940 insitu_ = insitu ;
3941 rsig->table_ = s->table_( s->table_.col("SRCTYPE") == (Int)SrcType::PSON ) ;
3942 rsig->attach() ;
3943 copyRows( ssig->table_, rsig->table_, 0, 0, rsig->nrow(), False, True, False ) ;
3944
3945 // process each sig and ref scan
3946 vector<string> cols( 3 ) ;
3947 cols[0] = "BEAMNO" ;
3948 cols[1] = "POLNO" ;
3949 cols[2] = "IFNO" ;
3950 STIdxIter2 iter(ssig, cols);
3951 while ( !iter.pastEnd() ) {
3952 Record ids = iter.currentValue() ;
3953 stringstream ss ;
3954 ss << "SELECT FROM $1 WHERE "
3955 << "BEAMNO==" << ids.asuInt("BEAMNO") << "&&"
3956 << "POLNO==" << ids.asuInt("POLNO") << "&&"
3957 << "IFNO==" << ids.asuInt("IFNO") ;
3958 //cout << "TaQL string: " << ss.str() << endl ;
3959 sel.setTaQL( ss.str() ) ;
3960 ahot->setSelection( sel ) ;
3961 asky->setSelection( sel ) ;
3962 Vector<uInt> rows = iter.getRows( SHARE ) ;
3963 // out should be an exact copy of s except that SPECTRA column is empty
3964 calibrateFS( ssig, sref, rsig, rref, asky, ahot, acold, rows ) ;
3965 ahot->unsetSelection() ;
3966 asky->unsetSelection() ;
3967 sel.reset() ;
3968 iter.next() ;
3969 }
3970 }
3971
3972 // do folding if necessary
3973 Table sigtab = ssig->table() ;
3974 Table reftab = sref->table() ;
3975 ScalarColumn<uInt> reffidCol ;
3976 Int nchan = (Int)ssig->nchan() ;
3977 reffidCol.attach( reftab, "FREQ_ID" ) ;
3978 Vector<uInt> sfids = ssig->mfreqidCol_.getColumn() ;
3979 Vector<uInt> rfids = sref->mfreqidCol_.getColumn() ;
3980 vector<uInt> sfids_unique ;
3981 vector<uInt> rfids_unique ;
3982 vector<uInt> sifno_unique ;
3983 vector<uInt> rifno_unique ;
3984 for ( uInt i = 0 ; i < sfids.nelements() ; i++ ) {
3985 if ( count( sfids_unique.begin(), sfids_unique.end(), sfids[i] ) == 0 ) {
3986 sfids_unique.push_back( sfids[i] ) ;
3987 sifno_unique.push_back( ssig->getIF( i ) ) ;
3988 }
3989 if ( count( rfids_unique.begin(), rfids_unique.end(), rfids[i] ) == 0 ) {
3990 rfids_unique.push_back( rfids[i] ) ;
3991 rifno_unique.push_back( sref->getIF( i ) ) ;
3992 }
3993 }
3994 double refpix_sig, refval_sig, increment_sig ;
3995 double refpix_ref, refval_ref, increment_ref ;
3996 vector< CountedPtr<Scantable> > tmp( sfids_unique.size() ) ;
3997 for ( uInt i = 0 ; i < sfids_unique.size() ; i++ ) {
3998 ssig->frequencies().getEntry( refpix_sig, refval_sig, increment_sig, sfids_unique[i] ) ;
3999 sref->frequencies().getEntry( refpix_ref, refval_ref, increment_ref, rfids_unique[i] ) ;
4000 if ( refpix_sig == refpix_ref ) {
4001 double foffset = refval_ref - refval_sig ;
4002 int choffset = static_cast<int>(foffset/increment_sig) ;
4003 double doffset = foffset / increment_sig ;
4004 if ( abs(choffset) >= nchan ) {
4005 LogIO os( LogOrigin( "STMath", "cwcalfs", WHERE ) ) ;
4006 os << "FREQ_ID=[" << sfids_unique[i] << "," << rfids_unique[i] << "]: out-band frequency switching, no folding" << LogIO::POST ;
4007 os << "Just return signal data" << LogIO::POST ;
4008 //std::vector< CountedPtr<Scantable> > tabs ;
4009 //tabs.push_back( ssig ) ;
4010 //tabs.push_back( sref ) ;
4011 //out = merge( tabs ) ;
4012 tmp[i] = ssig ;
4013 }
4014 else {
4015 STSelector sel = STSelector() ;
4016 vector<int> v( 1, sifno_unique[i] ) ;
4017 sel.setIFs( v ) ;
4018 ssig->setSelection( sel ) ;
4019 sel.reset() ;
4020 v[0] = rifno_unique[i] ;
4021 sel.setIFs( v ) ;
4022 sref->setSelection( sel ) ;
4023 sel.reset() ;
4024 if ( antname.find( "APEX" ) != string::npos ) {
4025 tmp[i] = dofold( ssig, sref, 0.5*doffset, -0.5*doffset ) ;
4026 //tmp[i] = dofold( ssig, sref, doffset ) ;
4027 }
4028 else {
4029 tmp[i] = dofold( ssig, sref, doffset ) ;
4030 }
4031 ssig->unsetSelection() ;
4032 sref->unsetSelection() ;
4033 }
4034 }
4035 }
4036
4037 if ( tmp.size() > 1 ) {
4038 out = merge( tmp ) ;
4039 }
4040 else {
4041 out = tmp[0] ;
4042 }
4043
4044 // flux unit
4045 out->setFluxUnit( "K" ) ;
4046
4047 return out ;
4048}
4049
4050CountedPtr<Scantable> STMath::almacalfs( const CountedPtr<Scantable>& s )
4051{
4052 (void) s; //currently unused
4053 CountedPtr<Scantable> out ;
4054
4055 return out ;
4056}
4057
4058void STMath::calibrateCW( CountedPtr<Scantable> &out,
4059 const CountedPtr<Scantable>& on,
4060 const CountedPtr<Scantable>& off,
4061 const CountedPtr<Scantable>& sky,
4062 const CountedPtr<Scantable>& hot,
4063 const CountedPtr<Scantable>& cold,
4064 const Vector<uInt> &rows,
4065 const String &antname )
4066{
4067 // 2012/05/22 TN
4068 // Assume that out has empty SPECTRA column
4069
4070 // if rows is empty, just return
4071 if ( rows.nelements() == 0 )
4072 return ;
4073 ROScalarColumn<Double> timeCol( off->table(), "TIME" ) ;
4074 Vector<Double> timeOff = timeCol.getColumn() ;
4075 timeCol.attach( sky->table(), "TIME" ) ;
4076 Vector<Double> timeSky = timeCol.getColumn() ;
4077 timeCol.attach( hot->table(), "TIME" ) ;
4078 Vector<Double> timeHot = timeCol.getColumn() ;
4079 timeCol.attach( on->table(), "TIME" ) ;
4080 ROArrayColumn<Float> arrayFloatCol( off->table(), "SPECTRA" ) ;
4081 SpectralData offspectra(arrayFloatCol.getColumn());
4082 arrayFloatCol.attach( sky->table(), "SPECTRA" ) ;
4083 SpectralData skyspectra(arrayFloatCol.getColumn());
4084 arrayFloatCol.attach( hot->table(), "SPECTRA" ) ;
4085 SpectralData hotspectra(arrayFloatCol.getColumn());
4086 TcalData tcaldata(sky);
4087 TsysData tsysdata(sky);
4088 unsigned int spsize = on->nchan( on->getIF(rows[0]) ) ;
4089 // I know that the data is contiguous
4090 const uInt *p = rows.data() ;
4091 vector<int> ids( 2 ) ;
4092 Block<uInt> flagchan( spsize ) ;
4093 uInt nflag = 0 ;
4094 for ( int irow = 0 ; irow < rows.nelements() ; irow++ ) {
4095 double reftime = timeCol.asdouble(*p) ;
4096 ids = getRowIdFromTime( reftime, timeOff ) ;
4097 Vector<Float> spoff = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeOff, ids, offspectra, "linear");
4098 ids = getRowIdFromTime( reftime, timeSky ) ;
4099 Vector<Float> spsky = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeSky, ids, skyspectra, "linear");
4100 Vector<Float> tcal = SimpleInterpolationHelper<TcalData>::GetFromTime(reftime, timeSky, ids, tcaldata, "linear");
4101 Vector<Float> tsys = SimpleInterpolationHelper<TsysData>::GetFromTime(reftime, timeSky, ids, tsysdata, "linear");
4102 ids = getRowIdFromTime( reftime, timeHot ) ;
4103 Vector<Float> sphot = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeHot, ids, hotspectra, "linear");
4104 Vector<Float> spec = on->specCol_( *p ) ;
4105 if ( antname.find( "APEX" ) != String::npos ) {
4106 // using gain array
4107 for ( unsigned int j = 0 ; j < tcal.size() ; j++ ) {
4108 if ( spoff[j] == 0.0 || (sphot[j]-spsky[j]) == 0.0 ) {
4109 spec[j] = 0.0 ;
4110 flagchan[nflag++] = j ;
4111 }
4112 else {
4113 spec[j] = ( ( spec[j] - spoff[j] ) / spoff[j] )
4114 * ( spsky[j] / ( sphot[j] - spsky[j] ) ) * tcal[j] ;
4115 }
4116 }
4117 }
4118 else {
4119 // Chopper-Wheel calibration (Ulich & Haas 1976)
4120 for ( unsigned int j = 0 ; j < tcal.size() ; j++ ) {
4121 if ( (sphot[j]-spsky[j]) == 0.0 ) {
4122 spec[j] = 0.0 ;
4123 flagchan[nflag++] = j ;
4124 }
4125 else {
4126 spec[j] = ( spec[j] - spoff[j] ) / ( sphot[j] - spsky[j] ) * tcal[j] ;
4127 }
4128 }
4129 }
4130 out->specCol_.put( *p, spec ) ;
4131 out->tsysCol_.put( *p, tsys ) ;
4132 if ( nflag > 0 ) {
4133 Vector<uChar> fl = out->flagsCol_( *p ) ;
4134 for ( unsigned int j = 0 ; j < nflag ; j++ ) {
4135 fl[flagchan[j]] = (uChar)True ;
4136 }
4137 out->flagsCol_.put( *p, fl ) ;
4138 }
4139 nflag = 0 ;
4140 p++ ;
4141 }
4142}
4143
4144void STMath::calibrateALMA( CountedPtr<Scantable>& out,
4145 const CountedPtr<Scantable>& on,
4146 const CountedPtr<Scantable>& off,
4147 const Vector<uInt>& rows )
4148{
4149 // 2012/05/22 TN
4150 // Assume that out has empty SPECTRA column
4151
4152 // if rows is empty, just return
4153 if ( rows.nelements() == 0 )
4154 return ;
4155 ROScalarColumn<Double> timeCol( off->table(), "TIME" ) ;
4156 Vector<Double> timeVec = timeCol.getColumn() ;
4157 timeCol.attach( on->table(), "TIME" ) ;
4158 ROArrayColumn<Float> arrayFloatCol( off->table(), "SPECTRA" ) ;
4159 SpectralData offspectra(arrayFloatCol.getColumn());
4160 unsigned int spsize = on->nchan( on->getIF(rows[0]) ) ;
4161 // I know that the data is contiguous
4162 const uInt *p = rows.data() ;
4163 vector<int> ids( 2 ) ;
4164 Block<uInt> flagchan( spsize ) ;
4165 uInt nflag = 0 ;
4166 for ( int irow = 0 ; irow < rows.nelements() ; irow++ ) {
4167 double reftime = timeCol.asdouble(*p) ;
4168 ids = getRowIdFromTime( reftime, timeVec ) ;
4169 Vector<Float> spoff = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeVec, ids, offspectra, "linear");
4170 Vector<Float> spec = on->specCol_( *p ) ;
4171 Vector<Float> tsys = on->tsysCol_( *p ) ;
4172 // ALMA Calibration
4173 //
4174 // Ta* = Tsys * ( ON - OFF ) / OFF
4175 //
4176 // 2010/01/07 Takeshi Nakazato
4177 unsigned int tsyssize = tsys.nelements() ;
4178 for ( unsigned int j = 0 ; j < spsize ; j++ ) {
4179 if ( spoff[j] == 0.0 ) {
4180 spec[j] = 0.0 ;
4181 flagchan[nflag++] = j ;
4182 }
4183 else {
4184 spec[j] = ( spec[j] - spoff[j] ) / spoff[j] ;
4185 }
4186 if ( tsyssize == spsize )
4187 spec[j] *= tsys[j] ;
4188 else
4189 spec[j] *= tsys[0] ;
4190 }
4191 out->specCol_.put( *p, spec ) ;
4192 if ( nflag > 0 ) {
4193 Vector<uChar> fl = out->flagsCol_( *p ) ;
4194 for ( unsigned int j = 0 ; j < nflag ; j++ ) {
4195 fl[flagchan[j]] = (uChar)True ;
4196 }
4197 out->flagsCol_.put( *p, fl ) ;
4198 }
4199 nflag = 0 ;
4200 p++ ;
4201 }
4202}
4203
4204void STMath::calibrateAPEXFS( CountedPtr<Scantable> &sig,
4205 CountedPtr<Scantable> &ref,
4206 const vector< CountedPtr<Scantable> >& on,
4207 const vector< CountedPtr<Scantable> >& sky,
4208 const vector< CountedPtr<Scantable> >& hot,
4209 const vector< CountedPtr<Scantable> >& cold,
4210 const Vector<uInt> &rows )
4211{
4212 // if rows is empty, just return
4213 if ( rows.nelements() == 0 )
4214 return ;
4215 ROScalarColumn<Double> timeCol( sky[0]->table(), "TIME" ) ;
4216 Vector<Double> timeSkyS = timeCol.getColumn() ;
4217 timeCol.attach( sky[1]->table(), "TIME" ) ;
4218 Vector<Double> timeSkyR = timeCol.getColumn() ;
4219 timeCol.attach( hot[0]->table(), "TIME" ) ;
4220 Vector<Double> timeHotS = timeCol.getColumn() ;
4221 timeCol.attach( hot[1]->table(), "TIME" ) ;
4222 Vector<Double> timeHotR = timeCol.getColumn() ;
4223 timeCol.attach( sig->table(), "TIME" ) ;
4224 ROScalarColumn<Double> timeCol2( ref->table(), "TIME" ) ;
4225 ROArrayColumn<Float> arrayFloatCol( sky[0]->table(), "SPECTRA" ) ;
4226 SpectralData skyspectraS(arrayFloatCol.getColumn());
4227 arrayFloatCol.attach( sky[1]->table(), "SPECTRA" ) ;
4228 SpectralData skyspectraR(arrayFloatCol.getColumn());
4229 arrayFloatCol.attach( hot[0]->table(), "SPECTRA" ) ;
4230 SpectralData hotspectraS(arrayFloatCol.getColumn());
4231 arrayFloatCol.attach( hot[1]->table(), "SPECTRA" ) ;
4232 SpectralData hotspectraR(arrayFloatCol.getColumn());
4233 TcalData tcaldataS(sky[0]);
4234 TsysData tsysdataS(sky[0]);
4235 TcalData tcaldataR(sky[1]);
4236 TsysData tsysdataR(sky[1]);
4237 unsigned int spsize = sig->nchan( sig->getIF(rows[0]) ) ;
4238 Vector<Float> spec( spsize ) ;
4239 // I know that the data is contiguous
4240 const uInt *p = rows.data() ;
4241 vector<int> ids( 2 ) ;
4242 Block<uInt> flagchan( spsize ) ;
4243 uInt nflag = 0 ;
4244 for ( int irow = 0 ; irow < rows.nelements() ; irow++ ) {
4245 double reftime = timeCol.asdouble(*p) ;
4246 ids = getRowIdFromTime( reftime, timeSkyS ) ;
4247 Vector<Float> spskyS = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeSkyS, ids, skyspectraS, "linear");
4248 Vector<Float> tcalS = SimpleInterpolationHelper<TcalData>::GetFromTime(reftime, timeSkyS, ids, tcaldataS, "linear");
4249 Vector<Float> tsysS = SimpleInterpolationHelper<TsysData>::GetFromTime(reftime, timeSkyS, ids, tsysdataS, "linear");
4250 ids = getRowIdFromTime( reftime, timeHotS ) ;
4251 Vector<Float> sphotS = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeHotS, ids, hotspectraS, "linear");
4252 reftime = timeCol2.asdouble(*p) ;
4253 ids = getRowIdFromTime( reftime, timeSkyR ) ;
4254 Vector<Float> spskyR = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeSkyR, ids, skyspectraR, "linear");
4255 Vector<Float> tcalR = SimpleInterpolationHelper<TcalData>::GetFromTime(reftime, timeSkyR, ids, tcaldataR, "linear");
4256 Vector<Float> tsysR = SimpleInterpolationHelper<TsysData>::GetFromTime(reftime, timeSkyR, ids, tsysdataR, "linear");
4257 ids = getRowIdFromTime( reftime, timeHotR ) ;
4258 Vector<Float> sphotR = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeHotR, ids, hotspectraR, "linear");
4259 Vector<Float> spsig = on[0]->specCol_( *p ) ;
4260 Vector<Float> spref = on[1]->specCol_( *p ) ;
4261 for ( unsigned int j = 0 ; j < spsize ; j++ ) {
4262 if ( (sphotS[j]-spskyS[j]) == 0.0 || (sphotR[j]-spskyR[j]) == 0.0 ) {
4263 spec[j] = 0.0 ;
4264 flagchan[nflag++] = j ;
4265 }
4266 else {
4267 spec[j] = tcalS[j] * spsig[j] / ( sphotS[j] - spskyS[j] )
4268 - tcalR[j] * spref[j] / ( sphotR[j] - spskyR[j] ) ;
4269 }
4270 }
4271 sig->specCol_.put( *p, spec ) ;
4272 sig->tsysCol_.put( *p, tsysS ) ;
4273 spec *= (Float)-1.0 ;
4274 ref->specCol_.put( *p, spec ) ;
4275 ref->tsysCol_.put( *p, tsysR ) ;
4276 if ( nflag > 0 ) {
4277 Vector<uChar> flsig = sig->flagsCol_( *p ) ;
4278 Vector<uChar> flref = ref->flagsCol_( *p ) ;
4279 for ( unsigned int j = 0 ; j < nflag ; j++ ) {
4280 flsig[flagchan[j]] = (uChar)True ;
4281 flref[flagchan[j]] = (uChar)True ;
4282 }
4283 sig->flagsCol_.put( *p, flsig ) ;
4284 ref->flagsCol_.put( *p, flref ) ;
4285 }
4286 nflag = 0 ;
4287 p++ ;
4288 }
4289}
4290
4291void STMath::calibrateFS( CountedPtr<Scantable> &sig,
4292 CountedPtr<Scantable> &ref,
4293 const CountedPtr<Scantable>& rsig,
4294 const CountedPtr<Scantable>& rref,
4295 const CountedPtr<Scantable>& sky,
4296 const CountedPtr<Scantable>& hot,
4297 const CountedPtr<Scantable>& cold,
4298 const Vector<uInt> &rows )
4299{
4300 // if rows is empty, just return
4301 if ( rows.nelements() == 0 )
4302 return ;
4303 ROScalarColumn<Double> timeCol( sky->table(), "TIME" ) ;
4304 Vector<Double> timeSky = timeCol.getColumn() ;
4305 timeCol.attach( hot->table(), "TIME" ) ;
4306 Vector<Double> timeHot = timeCol.getColumn() ;
4307 timeCol.attach( sig->table(), "TIME" ) ;
4308 ROScalarColumn<Double> timeCol2( ref->table(), "TIME" ) ;
4309 ROArrayColumn<Float> arrayFloatCol( sky->table(), "SPECTRA" ) ;
4310 SpectralData skyspectra(arrayFloatCol.getColumn());
4311 arrayFloatCol.attach( hot->table(), "SPECTRA" ) ;
4312 SpectralData hotspectra(arrayFloatCol.getColumn());
4313 TcalData tcaldata(sky);
4314 TsysData tsysdata(sky);
4315 unsigned int spsize = sig->nchan( sig->getIF(rows[0]) ) ;
4316 Vector<Float> spec( spsize ) ;
4317 // I know that the data is contiguous
4318 const uInt *p = rows.data() ;
4319 vector<int> ids( 2 ) ;
4320 Block<uInt> flagchan( spsize ) ;
4321 uInt nflag = 0 ;
4322 for ( int irow = 0 ; irow < rows.nelements() ; irow++ ) {
4323 double reftime = timeCol.asdouble(*p) ;
4324 ids = getRowIdFromTime( reftime, timeSky ) ;
4325 Vector<Float> spsky = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeSky, ids, skyspectra, "linear");
4326 Vector<Float> tcal = SimpleInterpolationHelper<TcalData>::GetFromTime(reftime, timeSky, ids, tcaldata, "linear");
4327 Vector<Float> tsys = SimpleInterpolationHelper<TsysData>::GetFromTime(reftime, timeSky, ids, tsysdata, "linear");
4328 ids = getRowIdFromTime( reftime, timeHot ) ;
4329 Vector<Float> sphot = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeHot, ids, hotspectra, "linear");
4330 Vector<Float> spsig = rsig->specCol_( *p ) ;
4331 Vector<Float> spref = rref->specCol_( *p ) ;
4332 // using gain array
4333 for ( unsigned int j = 0 ; j < spsize ; j++ ) {
4334 if ( spref[j] == 0.0 || (sphot[j]-spsky[j]) == 0.0 ) {
4335 spec[j] = 0.0 ;
4336 flagchan[nflag++] = j ;
4337 }
4338 else {
4339 spec[j] = ( ( spsig[j] - spref[j] ) / spref[j] )
4340 * ( spsky[j] / ( sphot[j] - spsky[j] ) ) * tcal[j] ;
4341 }
4342 }
4343 sig->specCol_.put( *p, spec ) ;
4344 sig->tsysCol_.put( *p, tsys ) ;
4345 if ( nflag > 0 ) {
4346 Vector<uChar> fl = sig->flagsCol_( *p ) ;
4347 for ( unsigned int j = 0 ; j < nflag ; j++ ) {
4348 fl[flagchan[j]] = (uChar)True ;
4349 }
4350 sig->flagsCol_.put( *p, fl ) ;
4351 }
4352 nflag = 0 ;
4353
4354 reftime = timeCol2.asdouble(*p) ;
4355 ids = getRowIdFromTime( reftime, timeSky ) ;
4356 spsky = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeSky, ids, skyspectra, "linear");
4357 tcal = SimpleInterpolationHelper<TcalData>::GetFromTime(reftime, timeSky, ids, tcaldata, "linear");
4358 tsys = SimpleInterpolationHelper<TsysData>::GetFromTime(reftime, timeSky, ids, tsysdata, "linear");
4359 ids = getRowIdFromTime( reftime, timeHot ) ;
4360 sphot = SimpleInterpolationHelper<SpectralData>::GetFromTime(reftime, timeHot, ids, hotspectra, "linear");
4361 // using gain array
4362 for ( unsigned int j = 0 ; j < spsize ; j++ ) {
4363 if ( spsig[j] == 0.0 || (sphot[j]-spsky[j]) == 0.0 ) {
4364 spec[j] = 0.0 ;
4365 flagchan[nflag++] = j ;
4366 }
4367 else {
4368 spec[j] = ( ( spref[j] - spsig[j] ) / spsig[j] )
4369 * ( spsky[j] / ( sphot[j] - spsky[j] ) ) * tcal[j] ;
4370 }
4371 }
4372 ref->specCol_.put( *p, spec ) ;
4373 ref->tsysCol_.put( *p, tsys ) ;
4374 if ( nflag > 0 ) {
4375 Vector<uChar> fl = ref->flagsCol_( *p ) ;
4376 for ( unsigned int j = 0 ; j < nflag ; j++ ) {
4377 fl[flagchan[j]] = (uChar)True ;
4378 }
4379 ref->flagsCol_.put( *p, fl ) ;
4380 }
4381 nflag = 0 ;
4382 p++ ;
4383 }
4384}
4385
4386void STMath::copyRows( Table &out,
4387 const Table &in,
4388 uInt startout,
4389 uInt startin,
4390 uInt nrow,
4391 Bool copySpectra,
4392 Bool copyFlagtra,
4393 Bool copyTsys )
4394{
4395 uInt nexclude = 0 ;
4396 Block<String> excludeColsBlock( 3 ) ;
4397 if ( !copySpectra ) {
4398 excludeColsBlock[nexclude] = "SPECTRA" ;
4399 nexclude++ ;
4400 }
4401 if ( !copyFlagtra ) {
4402 excludeColsBlock[nexclude] = "FLAGTRA" ;
4403 nexclude++ ;
4404 }
4405 if ( !copyTsys ) {
4406 excludeColsBlock[nexclude] = "TSYS" ;
4407 nexclude++ ;
4408 }
4409 // if ( nexclude < 3 ) {
4410 // excludeCols.resize( nexclude, True ) ;
4411 // }
4412 Vector<String> excludeCols( IPosition(1,nexclude),
4413 excludeColsBlock.storage(),
4414 SHARE ) ;
4415// cout << "excludeCols=" << excludeCols << endl ;
4416 TableRow rowout( out, excludeCols, True ) ;
4417 ROTableRow rowin( in, excludeCols, True ) ;
4418 uInt rin = startin ;
4419 uInt rout = startout ;
4420 for ( uInt i = 0 ; i < nrow ; i++ ) {
4421 rowin.get( rin ) ;
4422 rowout.putMatchingFields( rout, rowin.record() ) ;
4423 rin++ ;
4424 rout++ ;
4425 }
4426}
4427
4428CountedPtr<Scantable> STMath::averageWithinSession( CountedPtr<Scantable> &s,
4429 vector<bool> &mask,
4430 string weight )
4431{
4432 // prepare output table
4433 bool insitu = insitu_ ;
4434 insitu_ = false ;
4435 CountedPtr<Scantable> a = getScantable( s, true ) ;
4436 insitu_ = insitu ;
4437 Table &atab = a->table() ;
4438 ScalarColumn<Double> timeColOut( atab, "TIME" ) ;
4439
4440 if ( s->nrow() == 0 )
4441 return a ;
4442
4443 // setup RowAccumulator
4444 WeightType wtype = stringToWeight( weight ) ;
4445 RowAccumulator acc( wtype ) ;
4446 Vector<Bool> cmask( mask ) ;
4447 acc.setUserMask( cmask ) ;
4448
4449 vector<string> cols( 3 ) ;
4450 cols[0] = "IFNO" ;
4451 cols[1] = "POLNO" ;
4452 cols[2] = "BEAMNO" ;
4453 STIdxIter2 iter( s, cols ) ;
4454
4455 Table ttab = s->table() ;
4456 ROScalarColumn<Double> *timeCol = new ROScalarColumn<Double>( ttab, "TIME" ) ;
4457 Vector<Double> timeVec = timeCol->getColumn() ;
4458 delete timeCol ;
4459 Vector<Double> interval = s->integrCol_.getColumn() ;
4460 uInt nrow = timeVec.nelements() ;
4461 uInt outrow = 0 ;
4462
4463 while( !iter.pastEnd() ) {
4464
4465 Vector<uInt> rows = iter.getRows( SHARE ) ;
4466 uInt len = rows.nelements() ;
4467
4468 if ( len == 0 ) {
4469 iter.next() ;
4470 continue ;
4471 }
4472
4473 uInt nchan = s->nchan(s->getIF(rows[0])) ;
4474 Vector<uChar> flag( nchan ) ;
4475 Vector<Bool> bflag( nchan ) ;
4476 Vector<Float> spec( nchan ) ;
4477 Vector<Float> tsys( nchan ) ;
4478
4479 Vector<Double> timeSep( len-1 ) ;
4480 for ( uInt i = 0 ; i < len-1 ; i++ ) {
4481 timeSep[i] = timeVec[rows[i+1]] - timeVec[rows[i]] ;
4482 }
4483
4484 uInt irow ;
4485 uInt jrow ;
4486 for ( uInt i = 0 ; i < len-1 ; i++ ) {
4487 irow = rows[i] ;
4488 jrow = rows[i+1] ;
4489 // accumulate data
4490 s->flagsCol_.get( irow, flag ) ;
4491 convertArray( bflag, flag ) ;
4492 s->specCol_.get( irow, spec ) ;
4493 tsys.assign( s->tsysCol_( irow ) ) ;
4494 if ( !allEQ(bflag,True) )
4495 acc.add( spec, !bflag, tsys, interval[irow], timeVec[irow] ) ;
4496 double gap = 2.0 * 86400.0 * timeSep[i] / ( interval[jrow] + interval[irow] ) ;
4497 //cout << "gap[" << i << "]=" << setw(5) << gap << endl ;
4498 if ( gap > 1.1 ) {
4499 //cout << "detected gap between " << i << " and " << i+1 << endl ;
4500 // put data to output table
4501 // reset RowAccumulator
4502 if ( acc.state() ) {
4503 atab.addRow() ;
4504 copyRows( atab, ttab, outrow, irow, 1, False, False, False ) ;
4505 acc.replaceNaN() ;
4506 const Vector<Bool> &msk = acc.getMask() ;
4507 convertArray( flag, !msk ) ;
4508 for (uInt k = 0; k < nchan; ++k) {
4509 uChar userFlag = 1 << 7;
4510 if (msk[k]==True) userFlag = 0 << 7;
4511 flag(k) = userFlag;
4512 }
4513 a->flagsCol_.put( outrow, flag ) ;
4514 a->specCol_.put( outrow, acc.getSpectrum() ) ;
4515 a->tsysCol_.put( outrow, acc.getTsys() ) ;
4516 a->integrCol_.put( outrow, acc.getInterval() ) ;
4517 timeColOut.put( outrow, acc.getTime() ) ;
4518 a->cycleCol_.put( outrow, 0 ) ;
4519 }
4520 acc.reset() ;
4521 outrow++ ;
4522 }
4523 }
4524
4525 // accumulate and add last data
4526 irow = rows[len-1] ;
4527 s->flagsCol_.get( irow, flag ) ;
4528 convertArray( bflag, flag ) ;
4529 s->specCol_.get( irow, spec ) ;
4530 tsys.assign( s->tsysCol_( irow ) ) ;
4531 if (!allEQ(bflag,True) )
4532 acc.add( spec, !bflag, tsys, interval[irow], timeVec[irow] ) ;
4533 if ( acc.state() ) {
4534 atab.addRow() ;
4535 copyRows( atab, ttab, outrow, irow, 1, False, False, False ) ;
4536 acc.replaceNaN() ;
4537 const Vector<Bool> &msk = acc.getMask() ;
4538 convertArray( flag, !msk ) ;
4539 for (uInt k = 0; k < nchan; ++k) {
4540 uChar userFlag = 1 << 7;
4541 if (msk[k]==True) userFlag = 0 << 7;
4542 flag(k) = userFlag;
4543 }
4544 a->flagsCol_.put( outrow, flag ) ;
4545 a->specCol_.put( outrow, acc.getSpectrum() ) ;
4546 a->tsysCol_.put( outrow, acc.getTsys() ) ;
4547 a->integrCol_.put( outrow, acc.getInterval() ) ;
4548 timeColOut.put( outrow, acc.getTime() ) ;
4549 a->cycleCol_.put( outrow, 0 ) ;
4550 }
4551 acc.reset() ;
4552 outrow++ ;
4553
4554 iter.next() ;
4555 }
4556
4557 return a ;
4558}
Note: See TracBrowser for help on using the repository browser.