source: trunk/src/STMath.cpp@ 2919

Last change on this file since 2919 was 2919, checked in by Takeshi Nakazato, 11 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Refactoring.


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