source: trunk/src/STMath.cpp@ 1406

Last change on this file since 1406 was 1391, checked in by Malte Marquarding, 17 years ago

merge from alma branch to get alma/GBT support. Commented out fluxUnit changes as they are using a chnaged interface to PKSreader/writer. Also commented out progress meter related code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 64.9 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
[330]13#include <casa/iomanip.h>
[805]14#include <casa/Exceptions/Error.h>
15#include <casa/Containers/Block.h>
[81]16#include <casa/BasicSL/String.h>
[805]17#include <casa/Arrays/MaskArrLogi.h>
18#include <casa/Arrays/MaskArrMath.h>
19#include <casa/Arrays/ArrayLogical.h>
[81]20#include <casa/Arrays/ArrayMath.h>
[1066]21#include <casa/Arrays/Slice.h>
22#include <casa/Arrays/Slicer.h>
[805]23#include <casa/Containers/RecordField.h>
24#include <tables/Tables/TableRow.h>
25#include <tables/Tables/TableVector.h>
[917]26#include <tables/Tables/TabVecMath.h>
[805]27#include <tables/Tables/ExprNode.h>
28#include <tables/Tables/TableRecord.h>
[1140]29#include <tables/Tables/TableParse.h>
[805]30#include <tables/Tables/ReadAsciiTable.h>
[1140]31#include <tables/Tables/TableIter.h>
32#include <tables/Tables/TableCopy.h>
[1192]33#include <scimath/Mathematics/FFTServer.h>
[2]34
[262]35#include <lattices/Lattices/LatticeUtilities.h>
36
[917]37#include <coordinates/Coordinates/SpectralCoordinate.h>
38#include <coordinates/Coordinates/CoordinateSystem.h>
39#include <coordinates/Coordinates/CoordinateUtil.h>
40#include <coordinates/Coordinates/FrequencyAligner.h>
41
[177]42#include <scimath/Mathematics/VectorKernel.h>
43#include <scimath/Mathematics/Convolver.h>
[234]44#include <scimath/Functionals/Polynomial.h>
[177]45
[38]46#include "MathUtils.h"
[805]47#include "RowAccumulator.h"
[878]48#include "STAttr.h"
[805]49#include "STMath.h"
[1391]50#include "STSelector.h"
[2]51
[805]52using namespace casa;
[2]53
[83]54using namespace asap;
[2]55
[805]56STMath::STMath(bool insitu) :
57 insitu_(insitu)
[716]58{
59}
[170]60
61
[805]62STMath::~STMath()
[170]63{
64}
65
[805]66CountedPtr<Scantable>
[977]67STMath::average( const std::vector<CountedPtr<Scantable> >& in,
[858]68 const std::vector<bool>& mask,
[805]69 const std::string& weight,
[977]70 const std::string& avmode)
[262]71{
[977]72 if ( avmode == "SCAN" && in.size() != 1 )
[1066]73 throw(AipsError("Can't perform 'SCAN' averaging on multiple tables.\n"
74 "Use merge first."));
[805]75 WeightType wtype = stringToWeight(weight);
[926]76
[805]77 // output
78 // clone as this is non insitu
79 bool insitu = insitu_;
80 setInsitu(false);
[977]81 CountedPtr< Scantable > out = getScantable(in[0], true);
[805]82 setInsitu(insitu);
[977]83 std::vector<CountedPtr<Scantable> >::const_iterator stit = in.begin();
[862]84 ++stit;
[977]85 while ( stit != in.end() ) {
[862]86 out->appendToHistoryTable((*stit)->history());
87 ++stit;
88 }
[294]89
[805]90 Table& tout = out->table();
[701]91
[805]92 /// @todo check if all scantables are conformant
[294]93
[805]94 ArrayColumn<Float> specColOut(tout,"SPECTRA");
95 ArrayColumn<uChar> flagColOut(tout,"FLAGTRA");
96 ArrayColumn<Float> tsysColOut(tout,"TSYS");
97 ScalarColumn<Double> mjdColOut(tout,"TIME");
98 ScalarColumn<Double> intColOut(tout,"INTERVAL");
[1008]99 ScalarColumn<uInt> cycColOut(tout,"CYCLENO");
[1145]100 ScalarColumn<uInt> scanColOut(tout,"SCANNO");
[262]101
[805]102 // set up the output table rows. These are based on the structure of the
[862]103 // FIRST scantable in the vector
[977]104 const Table& baset = in[0]->table();
[262]105
[805]106 Block<String> cols(3);
107 cols[0] = String("BEAMNO");
108 cols[1] = String("IFNO");
109 cols[2] = String("POLNO");
110 if ( avmode == "SOURCE" ) {
111 cols.resize(4);
112 cols[3] = String("SRCNAME");
[488]113 }
[977]114 if ( avmode == "SCAN" && in.size() == 1) {
[805]115 cols.resize(4);
116 cols[3] = String("SCANNO");
[2]117 }
[805]118 uInt outrowCount = 0;
119 TableIterator iter(baset, cols);
120 while (!iter.pastEnd()) {
121 Table subt = iter.table();
122 // copy the first row of this selection into the new table
123 tout.addRow();
124 TableCopy::copyRows(tout, subt, outrowCount, 0, 1);
[1145]125 // re-index to 0
126 if ( avmode != "SCAN" && avmode != "SOURCE" ) {
127 scanColOut.put(outrowCount, uInt(0));
128 }
[805]129 ++outrowCount;
130 ++iter;
[144]131 }
[805]132 RowAccumulator acc(wtype);
[858]133 Vector<Bool> cmask(mask);
134 acc.setUserMask(cmask);
[805]135 ROTableRow row(tout);
136 ROArrayColumn<Float> specCol, tsysCol;
137 ROArrayColumn<uChar> flagCol;
138 ROScalarColumn<Double> mjdCol, intCol;
139 ROScalarColumn<Int> scanIDCol;
[144]140
[1333]141 Vector<uInt> rowstodelete;
142
[805]143 for (uInt i=0; i < tout.nrow(); ++i) {
[996]144 for ( int j=0; j < int(in.size()); ++j ) {
[977]145 const Table& tin = in[j]->table();
[805]146 const TableRecord& rec = row.get(i);
147 ROScalarColumn<Double> tmp(tin, "TIME");
148 Double td;tmp.get(0,td);
149 Table basesubt = tin(tin.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
150 && tin.col("IFNO") == Int(rec.asuInt("IFNO"))
151 && tin.col("POLNO") == Int(rec.asuInt("POLNO")) );
152 Table subt;
153 if ( avmode == "SOURCE") {
154 subt = basesubt( basesubt.col("SRCNAME") == rec.asString("SRCNAME") );
155 } else if (avmode == "SCAN") {
156 subt = basesubt( basesubt.col("SCANNO") == Int(rec.asuInt("SCANNO")) );
157 } else {
158 subt = basesubt;
159 }
160 specCol.attach(subt,"SPECTRA");
161 flagCol.attach(subt,"FLAGTRA");
162 tsysCol.attach(subt,"TSYS");
163 intCol.attach(subt,"INTERVAL");
164 mjdCol.attach(subt,"TIME");
165 Vector<Float> spec,tsys;
166 Vector<uChar> flag;
167 Double inter,time;
168 for (uInt k = 0; k < subt.nrow(); ++k ) {
169 flagCol.get(k, flag);
170 Vector<Bool> bflag(flag.shape());
171 convertArray(bflag, flag);
[1314]172 /*
[805]173 if ( allEQ(bflag, True) ) {
[1314]174 continue;//don't accumulate
[144]175 }
[1314]176 */
[805]177 specCol.get(k, spec);
178 tsysCol.get(k, tsys);
179 intCol.get(k, inter);
180 mjdCol.get(k, time);
181 // spectrum has to be added last to enable weighting by the other values
182 acc.add(spec, !bflag, tsys, inter, time);
183 }
184 }
[1333]185 const Vector<Bool>& msk = acc.getMask();
186 if ( allEQ(msk, False) ) {
187 uint n = rowstodelete.nelements();
188 rowstodelete.resize(n+1, True);
189 rowstodelete[n] = i;
190 continue;
191 }
[805]192 //write out
193 Vector<uChar> flg(msk.shape());
194 convertArray(flg, !msk);
195 flagColOut.put(i, flg);
[1333]196 specColOut.put(i, acc.getSpectrum());
[805]197 tsysColOut.put(i, acc.getTsys());
198 intColOut.put(i, acc.getInterval());
199 mjdColOut.put(i, acc.getTime());
[1008]200 // we should only have one cycle now -> reset it to be 0
201 // frequency switched data has different CYCLENO for different IFNO
202 // which requires resetting this value
203 cycColOut.put(i, uInt(0));
[805]204 acc.reset();
[144]205 }
[1333]206 if (rowstodelete.nelements() > 0) {
207 cout << rowstodelete << endl;
208 tout.removeRow(rowstodelete);
209 if (tout.nrow() == 0) {
210 throw(AipsError("Can't average fully flagged data."));
211 }
212 }
[805]213 return out;
[2]214}
[9]215
[1069]216CountedPtr< Scantable >
217 STMath::averageChannel( const CountedPtr < Scantable > & in,
[1078]218 const std::string & mode,
219 const std::string& avmode )
[1069]220{
221 // clone as this is non insitu
222 bool insitu = insitu_;
223 setInsitu(false);
224 CountedPtr< Scantable > out = getScantable(in, true);
225 setInsitu(insitu);
226 Table& tout = out->table();
227 ArrayColumn<Float> specColOut(tout,"SPECTRA");
228 ArrayColumn<uChar> flagColOut(tout,"FLAGTRA");
229 ArrayColumn<Float> tsysColOut(tout,"TSYS");
[1140]230 ScalarColumn<uInt> scanColOut(tout,"SCANNO");
[1232]231 ScalarColumn<Double> intColOut(tout, "INTERVAL");
[1140]232 Table tmp = in->table().sort("BEAMNO");
[1069]233 Block<String> cols(3);
234 cols[0] = String("BEAMNO");
235 cols[1] = String("IFNO");
236 cols[2] = String("POLNO");
[1078]237 if ( avmode == "SCAN") {
238 cols.resize(4);
239 cols[3] = String("SCANNO");
240 }
[1069]241 uInt outrowCount = 0;
242 uChar userflag = 1 << 7;
[1140]243 TableIterator iter(tmp, cols);
[1069]244 while (!iter.pastEnd()) {
245 Table subt = iter.table();
246 ROArrayColumn<Float> specCol, tsysCol;
247 ROArrayColumn<uChar> flagCol;
[1232]248 ROScalarColumn<Double> intCol(subt, "INTERVAL");
[1069]249 specCol.attach(subt,"SPECTRA");
250 flagCol.attach(subt,"FLAGTRA");
251 tsysCol.attach(subt,"TSYS");
252 tout.addRow();
253 TableCopy::copyRows(tout, subt, outrowCount, 0, 1);
[1140]254 if ( avmode != "SCAN") {
255 scanColOut.put(outrowCount, uInt(0));
256 }
[1069]257 Vector<Float> tmp;
258 specCol.get(0, tmp);
259 uInt nchan = tmp.nelements();
[1078]260 // have to do channel by channel here as MaskedArrMath
261 // doesn't have partialMedians
[1069]262 Vector<uChar> flags = flagCol.getColumn(Slicer(Slice(0)));
263 Vector<Float> outspec(nchan);
264 Vector<uChar> outflag(nchan,0);
265 Vector<Float> outtsys(1);/// @fixme when tsys is channel based
266 for (uInt i=0; i<nchan; ++i) {
267 Vector<Float> specs = specCol.getColumn(Slicer(Slice(i)));
268 MaskedArray<Float> ma = maskedArray(specs,flags);
269 outspec[i] = median(ma);
270 if ( allEQ(ma.getMask(), False) )
271 outflag[i] = userflag;// flag data
272 }
273 outtsys[0] = median(tsysCol.getColumn());
274 specColOut.put(outrowCount, outspec);
275 flagColOut.put(outrowCount, outflag);
276 tsysColOut.put(outrowCount, outtsys);
[1232]277 Double intsum = sum(intCol.getColumn());
278 intColOut.put(outrowCount, intsum);
[1069]279 ++outrowCount;
280 ++iter;
281 }
282 return out;
283}
284
[805]285CountedPtr< Scantable > STMath::getScantable(const CountedPtr< Scantable >& in,
286 bool droprows)
[185]287{
[805]288 if (insitu_) return in;
289 else {
290 // clone
291 Scantable* tabp = new Scantable(*in, Bool(droprows));
292 return CountedPtr<Scantable>(tabp);
[234]293 }
[805]294}
[234]295
[805]296CountedPtr< Scantable > STMath::unaryOperate( const CountedPtr< Scantable >& in,
297 float val,
298 const std::string& mode,
299 bool tsys )
300{
301 CountedPtr< Scantable > out = getScantable(in, false);
302 Table& tab = out->table();
303 ArrayColumn<Float> specCol(tab,"SPECTRA");
304 ArrayColumn<Float> tsysCol(tab,"TSYS");
305 for (uInt i=0; i<tab.nrow(); ++i) {
306 Vector<Float> spec;
307 Vector<Float> ts;
308 specCol.get(i, spec);
309 tsysCol.get(i, ts);
[1308]310 if (mode == "MUL" || mode == "DIV") {
311 if (mode == "DIV") val = 1.0/val;
[805]312 spec *= val;
313 specCol.put(i, spec);
314 if ( tsys ) {
315 ts *= val;
316 tsysCol.put(i, ts);
317 }
[1308]318 } else if ( mode == "ADD" || mode == "SUB") {
319 if (mode == "SUB") val *= -1.0;
[805]320 spec += val;
321 specCol.put(i, spec);
322 if ( tsys ) {
323 ts += val;
324 tsysCol.put(i, ts);
325 }
326 }
[234]327 }
[805]328 return out;
329}
[234]330
[1308]331CountedPtr<Scantable> STMath::binaryOperate(const CountedPtr<Scantable>& left,
332 const CountedPtr<Scantable>& right,
333 const std::string& mode)
334{
335 bool insitu = insitu_;
336 if ( ! left->conformant(*right) ) {
337 throw(AipsError("'left' and 'right' scantables are not conformant."));
338 }
339 setInsitu(false);
340 CountedPtr< Scantable > out = getScantable(left, false);
341 setInsitu(insitu);
342 Table& tout = out->table();
343 Block<String> coln(5);
344 coln[0] = "SCANNO"; coln[1] = "CYCLENO"; coln[2] = "BEAMNO";
345 coln[3] = "IFNO"; coln[4] = "POLNO";
346 Table tmpl = tout.sort(coln);
347 Table tmpr = right->table().sort(coln);
348 ArrayColumn<Float> lspecCol(tmpl,"SPECTRA");
349 ROArrayColumn<Float> rspecCol(tmpr,"SPECTRA");
350 ArrayColumn<uChar> lflagCol(tmpl,"FLAGTRA");
351 ROArrayColumn<uChar> rflagCol(tmpr,"FLAGTRA");
352
353 for (uInt i=0; i<tout.nrow(); ++i) {
354 Vector<Float> lspecvec, rspecvec;
355 Vector<uChar> lflagvec, rflagvec;
356 lspecvec = lspecCol(i); rspecvec = rspecCol(i);
357 lflagvec = lflagCol(i); rflagvec = rflagCol(i);
358 MaskedArray<Float> mleft = maskedArray(lspecvec, lflagvec);
359 MaskedArray<Float> mright = maskedArray(rspecvec, rflagvec);
360 if (mode == "ADD") {
361 mleft += mright;
362 } else if ( mode == "SUB") {
363 mleft -= mright;
364 } else if ( mode == "MUL") {
365 mleft *= mright;
366 } else if ( mode == "DIV") {
367 mleft /= mright;
368 } else {
369 throw(AipsError("Illegal binary operator"));
370 }
371 lspecCol.put(i, mleft.getArray());
372 }
373 return out;
374}
375
376
377
[805]378MaskedArray<Float> STMath::maskedArray( const Vector<Float>& s,
379 const Vector<uChar>& f)
380{
381 Vector<Bool> mask;
382 mask.resize(f.shape());
383 convertArray(mask, f);
384 return MaskedArray<Float>(s,!mask);
385}
[248]386
[805]387Vector<uChar> STMath::flagsFromMA(const MaskedArray<Float>& ma)
388{
389 const Vector<Bool>& m = ma.getMask();
390 Vector<uChar> flags(m.shape());
391 convertArray(flags, !m);
392 return flags;
393}
[234]394
[1066]395CountedPtr< Scantable > STMath::autoQuotient( const CountedPtr< Scantable >& in,
396 const std::string & mode,
397 bool preserve )
[805]398{
399 /// @todo make other modes available
400 /// modes should be "nearest", "pair"
401 // make this operation non insitu
402 const Table& tin = in->table();
403 Table ons = tin(tin.col("SRCTYPE") == Int(0));
404 Table offs = tin(tin.col("SRCTYPE") == Int(1));
405 if ( offs.nrow() == 0 )
406 throw(AipsError("No 'off' scans present."));
407 // put all "on" scans into output table
[701]408
[805]409 bool insitu = insitu_;
410 setInsitu(false);
411 CountedPtr< Scantable > out = getScantable(in, true);
412 setInsitu(insitu);
413 Table& tout = out->table();
[248]414
[805]415 TableCopy::copyRows(tout, ons);
416 TableRow row(tout);
417 ROScalarColumn<Double> offtimeCol(offs, "TIME");
418 ArrayColumn<Float> outspecCol(tout, "SPECTRA");
419 ROArrayColumn<Float> outtsysCol(tout, "TSYS");
420 ArrayColumn<uChar> outflagCol(tout, "FLAGTRA");
421 for (uInt i=0; i < tout.nrow(); ++i) {
422 const TableRecord& rec = row.get(i);
423 Double ontime = rec.asDouble("TIME");
[1321]424 Table presel = offs(offs.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
425 && offs.col("IFNO") == Int(rec.asuInt("IFNO"))
426 && offs.col("POLNO") == Int(rec.asuInt("POLNO")) );
427 ROScalarColumn<Double> offtimeCol(presel, "TIME");
428
[805]429 Double mindeltat = min(abs(offtimeCol.getColumn() - ontime));
[1259]430 // Timestamp may vary within a cycle ???!!!
[1321]431 // increase this by 0.01 sec in case of rounding errors...
[1259]432 // There might be a better way to do this.
[1321]433 // fix to this fix. TIME is MJD, so 1.0d not 1.0s
434 mindeltat += 0.01/24./60./60.;
435 Table sel = presel( abs(presel.col("TIME")-ontime) <= mindeltat);
[780]436
[1259]437 if ( sel.nrow() < 1 ) {
438 throw(AipsError("No closest in time found... This could be a rounding "
439 "issue. Try quotient instead."));
440 }
[805]441 TableRow offrow(sel);
442 const TableRecord& offrec = offrow.get(0);//should only be one row
443 RORecordFieldPtr< Array<Float> > specoff(offrec, "SPECTRA");
444 RORecordFieldPtr< Array<Float> > tsysoff(offrec, "TSYS");
445 RORecordFieldPtr< Array<uChar> > flagoff(offrec, "FLAGTRA");
446 /// @fixme this assumes tsys is a scalar not vector
447 Float tsysoffscalar = (*tsysoff)(IPosition(1,0));
448 Vector<Float> specon, tsyson;
449 outtsysCol.get(i, tsyson);
450 outspecCol.get(i, specon);
451 Vector<uChar> flagon;
452 outflagCol.get(i, flagon);
453 MaskedArray<Float> mon = maskedArray(specon, flagon);
454 MaskedArray<Float> moff = maskedArray(*specoff, *flagoff);
455 MaskedArray<Float> quot = (tsysoffscalar * mon / moff);
456 if (preserve) {
457 quot -= tsysoffscalar;
458 } else {
459 quot -= tsyson[0];
[701]460 }
[805]461 outspecCol.put(i, quot.getArray());
462 outflagCol.put(i, flagsFromMA(quot));
463 }
[926]464 // renumber scanno
465 TableIterator it(tout, "SCANNO");
466 uInt i = 0;
467 while ( !it.pastEnd() ) {
468 Table t = it.table();
469 TableVector<uInt> vec(t, "SCANNO");
470 vec = i;
471 ++i;
472 ++it;
473 }
[805]474 return out;
475}
[234]476
[1066]477
478CountedPtr< Scantable > STMath::quotient( const CountedPtr< Scantable > & on,
479 const CountedPtr< Scantable > & off,
480 bool preserve )
481{
482 bool insitu = insitu_;
[1069]483 if ( ! on->conformant(*off) ) {
484 throw(AipsError("'on' and 'off' scantables are not conformant."));
485 }
[1066]486 setInsitu(false);
487 CountedPtr< Scantable > out = getScantable(on, false);
488 setInsitu(insitu);
489 Table& tout = out->table();
490 const Table& toff = off->table();
491 TableIterator sit(tout, "SCANNO");
492 TableIterator s2it(toff, "SCANNO");
493 while ( !sit.pastEnd() ) {
494 Table ton = sit.table();
495 TableRow row(ton);
496 Table t = s2it.table();
497 ArrayColumn<Float> outspecCol(ton, "SPECTRA");
498 ROArrayColumn<Float> outtsysCol(ton, "TSYS");
499 ArrayColumn<uChar> outflagCol(ton, "FLAGTRA");
500 for (uInt i=0; i < ton.nrow(); ++i) {
501 const TableRecord& rec = row.get(i);
502 Table offsel = t( t.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
503 && t.col("IFNO") == Int(rec.asuInt("IFNO"))
504 && t.col("POLNO") == Int(rec.asuInt("POLNO")) );
[1145]505 if ( offsel.nrow() == 0 )
506 throw AipsError("STMath::quotient: no matching off");
[1066]507 TableRow offrow(offsel);
508 const TableRecord& offrec = offrow.get(0);//should be ncycles - take first
509 RORecordFieldPtr< Array<Float> > specoff(offrec, "SPECTRA");
510 RORecordFieldPtr< Array<Float> > tsysoff(offrec, "TSYS");
511 RORecordFieldPtr< Array<uChar> > flagoff(offrec, "FLAGTRA");
512 Float tsysoffscalar = (*tsysoff)(IPosition(1,0));
513 Vector<Float> specon, tsyson;
514 outtsysCol.get(i, tsyson);
515 outspecCol.get(i, specon);
516 Vector<uChar> flagon;
517 outflagCol.get(i, flagon);
518 MaskedArray<Float> mon = maskedArray(specon, flagon);
519 MaskedArray<Float> moff = maskedArray(*specoff, *flagoff);
520 MaskedArray<Float> quot = (tsysoffscalar * mon / moff);
521 if (preserve) {
522 quot -= tsysoffscalar;
523 } else {
524 quot -= tsyson[0];
525 }
526 outspecCol.put(i, quot.getArray());
527 outflagCol.put(i, flagsFromMA(quot));
528 }
529 ++sit;
530 ++s2it;
531 // take the first off for each on scan which doesn't have a
532 // matching off scan
533 // non <= noff: matching pairs, non > noff matching pairs then first off
534 if ( s2it.pastEnd() ) s2it.reset();
535 }
536 return out;
537}
538
[1391]539// dototalpower (migration of GBTIDL procedure dototalpower.pro)
540// calibrate the CAL on-off pair. It calculate Tsys and average CAL on-off subintegrations
541// do it for each cycles in a specific scan.
542CountedPtr< Scantable > STMath::dototalpower( const CountedPtr< Scantable >& calon,
543 const CountedPtr< Scantable >& caloff, Float tcal )
544{
545if ( ! calon->conformant(*caloff) ) {
546 throw(AipsError("'CAL on' and 'CAL off' scantables are not conformant."));
547 }
548 setInsitu(false);
549 CountedPtr< Scantable > out = getScantable(caloff, false);
550 Table& tout = out->table();
551 const Table& tcon = calon->table();
552 Vector<Float> tcalout;
553 Vector<Float> tcalout2; //debug
[1066]554
[1391]555 if ( tout.nrow() != tcon.nrow() ) {
556 throw(AipsError("Mismatch in number of rows to form cal on - off pair."));
557 }
558 // iteration by scanno or cycle no.
559 TableIterator sit(tout, "SCANNO");
560 TableIterator s2it(tcon, "SCANNO");
561 while ( !sit.pastEnd() ) {
562 Table toff = sit.table();
563 TableRow row(toff);
564 Table t = s2it.table();
565 ScalarColumn<Double> outintCol(toff, "INTERVAL");
566 ArrayColumn<Float> outspecCol(toff, "SPECTRA");
567 ArrayColumn<Float> outtsysCol(toff, "TSYS");
568 ArrayColumn<uChar> outflagCol(toff, "FLAGTRA");
569 ROScalarColumn<uInt> outtcalIdCol(toff, "TCAL_ID");
570 ROScalarColumn<uInt> outpolCol(toff, "POLNO");
571 ROScalarColumn<Double> onintCol(t, "INTERVAL");
572 ROArrayColumn<Float> onspecCol(t, "SPECTRA");
573 ROArrayColumn<Float> ontsysCol(t, "TSYS");
574 ROArrayColumn<uChar> onflagCol(t, "FLAGTRA");
575 //ROScalarColumn<uInt> ontcalIdCol(t, "TCAL_ID");
576
577 for (uInt i=0; i < toff.nrow(); ++i) {
578 //skip these checks -> assumes the data order are the same between the cal on off pairs
579 //
580 Vector<Float> specCalon, specCaloff;
581 // to store scalar (mean) tsys
582 Vector<Float> tsysout(1);
583 uInt tcalId, polno;
584 Double offint, onint;
585 outpolCol.get(i, polno);
586 outspecCol.get(i, specCaloff);
587 onspecCol.get(i, specCalon);
588 Vector<uChar> flagCaloff, flagCalon;
589 outflagCol.get(i, flagCaloff);
590 onflagCol.get(i, flagCalon);
591 outtcalIdCol.get(i, tcalId);
592 outintCol.get(i, offint);
593 onintCol.get(i, onint);
594 // caluculate mean Tsys
595 uInt nchan = specCaloff.nelements();
596 // percentage of edge cut off
597 uInt pc = 10;
598 uInt bchan = nchan/pc;
599 uInt echan = nchan-bchan;
600
601 Slicer chansl(IPosition(1,bchan-1), IPosition(1,echan-1), IPosition(1,1),Slicer::endIsLast);
602 Vector<Float> testsubsp = specCaloff(chansl);
603 MaskedArray<Float> spoff = maskedArray( specCaloff(chansl),flagCaloff(chansl) );
604 MaskedArray<Float> spon = maskedArray( specCalon(chansl),flagCalon(chansl) );
605 MaskedArray<Float> spdiff = spon-spoff;
606 uInt noff = spoff.nelementsValid();
607 //uInt non = spon.nelementsValid();
608 uInt ndiff = spdiff.nelementsValid();
609 Float meantsys;
610
611/**
612 Double subspec, subdiff;
613 uInt usednchan;
614 subspec = 0;
615 subdiff = 0;
616 usednchan = 0;
617 for(uInt k=(bchan-1); k<echan; k++) {
618 subspec += specCaloff[k];
619 subdiff += static_cast<Double>(specCalon[k]-specCaloff[k]);
620 ++usednchan;
621 }
622**/
623 // get tcal if input tcal <= 0
624 String tcalt;
625 Float tcalUsed;
626 tcalUsed = tcal;
627 if ( tcal <= 0.0 ) {
628 caloff->tcal().getEntry(tcalt, tcalout, tcalId);
629 if (polno<=3) {
630 tcalUsed = tcalout[polno];
631 }
632 else {
633 tcalUsed = tcalout[0];
634 }
635 }
636
637 Float meanoff;
638 Float meandiff;
639 if (noff && ndiff) {
640 //Debug
641 //if(noff!=ndiff) cerr<<"noff and ndiff is not equal"<<endl;
642 meanoff = sum(spoff)/noff;
643 meandiff = sum(spdiff)/ndiff;
644 meantsys= (meanoff/meandiff )*tcalUsed + tcalUsed/2;
645 }
646 else {
647 meantsys=1;
648 }
649
650 tsysout[0] = Float(meantsys);
651 MaskedArray<Float> mcaloff = maskedArray(specCaloff, flagCaloff);
652 MaskedArray<Float> mcalon = maskedArray(specCalon, flagCalon);
653 MaskedArray<Float> sig = Float(0.5) * (mcaloff + mcalon);
654 //uInt ncaloff = mcaloff.nelementsValid();
655 //uInt ncalon = mcalon.nelementsValid();
656
657 outintCol.put(i, offint+onint);
658 outspecCol.put(i, sig.getArray());
659 outflagCol.put(i, flagsFromMA(sig));
660 outtsysCol.put(i, tsysout);
661 }
662 ++sit;
663 ++s2it;
664 }
665 return out;
666}
667
668//dosigref - migrated from GBT IDL's dosigref.pro, do calibration of position switch
669// observatiions.
670// input: sig and ref scantables, and an optional boxcar smoothing width(default width=0,
671// no smoothing).
672// output: resultant scantable [= (sig-ref/ref)*tsys]
673CountedPtr< Scantable > STMath::dosigref( const CountedPtr < Scantable >& sig,
674 const CountedPtr < Scantable >& ref,
675 int smoothref,
676 casa::Float tsysv,
677 casa::Float tau )
678{
679if ( ! ref->conformant(*sig) ) {
680 throw(AipsError("'sig' and 'ref' scantables are not conformant."));
681 }
682 setInsitu(false);
683 CountedPtr< Scantable > out = getScantable(sig, false);
684 CountedPtr< Scantable > smref;
685 if ( smoothref > 1 ) {
686 float fsmoothref = static_cast<float>(smoothref);
687 std::string inkernel = "boxcar";
688 smref = smooth(ref, inkernel, fsmoothref );
689 ostringstream oss;
690 oss<<"Applied smoothing of "<<fsmoothref<<" on the reference."<<endl;
691 pushLog(String(oss));
692 }
693 else {
694 smref = ref;
695 }
696 Table& tout = out->table();
697 const Table& tref = smref->table();
698 if ( tout.nrow() != tref.nrow() ) {
699 throw(AipsError("Mismatch in number of rows to form on-source and reference pair."));
700 }
701 // iteration by scanno? or cycle no.
702 TableIterator sit(tout, "SCANNO");
703 TableIterator s2it(tref, "SCANNO");
704 while ( !sit.pastEnd() ) {
705 Table ton = sit.table();
706 Table t = s2it.table();
707 ScalarColumn<Double> outintCol(ton, "INTERVAL");
708 ArrayColumn<Float> outspecCol(ton, "SPECTRA");
709 ArrayColumn<Float> outtsysCol(ton, "TSYS");
710 ArrayColumn<uChar> outflagCol(ton, "FLAGTRA");
711 ArrayColumn<Float> refspecCol(t, "SPECTRA");
712 ROScalarColumn<Double> refintCol(t, "INTERVAL");
713 ROArrayColumn<Float> reftsysCol(t, "TSYS");
714 ArrayColumn<uChar> refflagCol(t, "FLAGTRA");
715 ROScalarColumn<Float> refelevCol(t, "ELEVATION");
716 for (uInt i=0; i < ton.nrow(); ++i) {
717
718 Double onint, refint;
719 Vector<Float> specon, specref;
720 // to store scalar (mean) tsys
721 Vector<Float> tsysref;
722 outintCol.get(i, onint);
723 refintCol.get(i, refint);
724 outspecCol.get(i, specon);
725 refspecCol.get(i, specref);
726 Vector<uChar> flagref, flagon;
727 outflagCol.get(i, flagon);
728 refflagCol.get(i, flagref);
729 reftsysCol.get(i, tsysref);
730
731 Float tsysrefscalar;
732 if ( tsysv > 0.0 ) {
733 ostringstream oss;
734 Float elev;
735 refelevCol.get(i, elev);
736 oss << "user specified Tsys = " << tsysv;
737 // do recalc elevation if EL = 0
738 if ( elev == 0 ) {
739 throw(AipsError("EL=0, elevation data is missing."));
740 } else {
741 if ( tau <= 0.0 ) {
742 throw(AipsError("Valid tau is not supplied."));
743 } else {
744 tsysrefscalar = tsysv * exp(tau/elev);
745 }
746 }
747 oss << ", corrected (for El) tsys= "<<tsysrefscalar;
748 pushLog(String(oss));
749 }
750 else {
751 tsysrefscalar = tsysref[0];
752 }
753 //get quotient spectrum
754 MaskedArray<Float> mref = maskedArray(specref, flagref);
755 MaskedArray<Float> mon = maskedArray(specon, flagon);
756 MaskedArray<Float> specres = tsysrefscalar*((mon - mref)/mref);
757 Double resint = onint*refint*smoothref/(onint+refint*smoothref);
758
759 //Debug
760 //cerr<<"Tsys used="<<tsysrefscalar<<endl;
761 // fill the result, replay signal tsys by reference tsys
762 outintCol.put(i, resint);
763 outspecCol.put(i, specres.getArray());
764 outflagCol.put(i, flagsFromMA(specres));
765 outtsysCol.put(i, tsysref);
766 }
767 ++sit;
768 ++s2it;
769 }
770 return out;
771}
772
773CountedPtr< Scantable > STMath::donod(const casa::CountedPtr<Scantable>& s,
774 const std::vector<int>& scans,
775 int smoothref,
776 casa::Float tsysv,
777 casa::Float tau,
778 casa::Float tcal )
779
780{
781 setInsitu(false);
782 STSelector sel;
783 std::vector<int> scan1, scan2, beams;
784 std::vector< vector<int> > scanpair;
785 std::vector<string> calstate;
786 String msg;
787
788 CountedPtr< Scantable > s1b1on, s1b1off, s1b2on, s1b2off;
789 CountedPtr< Scantable > s2b1on, s2b1off, s2b2on, s2b2off;
790
791 std::vector< CountedPtr< Scantable > > sctables;
792 sctables.push_back(s1b1on);
793 sctables.push_back(s1b1off);
794 sctables.push_back(s1b2on);
795 sctables.push_back(s1b2off);
796 sctables.push_back(s2b1on);
797 sctables.push_back(s2b1off);
798 sctables.push_back(s2b2on);
799 sctables.push_back(s2b2off);
800
801 //check scanlist
802 int n=s->checkScanInfo(scans);
803 if (n==1) {
804 throw(AipsError("Incorrect scan pairs. "));
805 }
806
807 // Assume scans contain only a pair of consecutive scan numbers.
808 // It is assumed that first beam, b1, is on target.
809 // There is no check if the first beam is on or not.
810 if ( scans.size()==1 ) {
811 scan1.push_back(scans[0]);
812 scan2.push_back(scans[0]+1);
813 } else if ( scans.size()==2 ) {
814 scan1.push_back(scans[0]);
815 scan2.push_back(scans[1]);
816 } else {
817 if ( scans.size()%2 == 0 ) {
818 for (uInt i=0; i<scans.size(); i++) {
819 if (i%2 == 0) {
820 scan1.push_back(scans[i]);
821 }
822 else {
823 scan2.push_back(scans[i]);
824 }
825 }
826 } else {
827 throw(AipsError("Odd numbers of scans, cannot form pairs."));
828 }
829 }
830 scanpair.push_back(scan1);
831 scanpair.push_back(scan2);
832 calstate.push_back("*calon");
833 calstate.push_back("*[^calon]");
834 CountedPtr< Scantable > ws = getScantable(s, false);
835 uInt l=0;
836 while ( l < sctables.size() ) {
837 for (uInt i=0; i < 2; i++) {
838 for (uInt j=0; j < 2; j++) {
839 for (uInt k=0; k < 2; k++) {
840 sel.reset();
841 sel.setScans(scanpair[i]);
842 sel.setName(calstate[k]);
843 beams.clear();
844 beams.push_back(j);
845 sel.setBeams(beams);
846 ws->setSelection(sel);
847 sctables[l]= getScantable(ws, false);
848 l++;
849 }
850 }
851 }
852 }
853
854 // replace here by splitData or getData functionality
855 CountedPtr< Scantable > sig1;
856 CountedPtr< Scantable > ref1;
857 CountedPtr< Scantable > sig2;
858 CountedPtr< Scantable > ref2;
859 CountedPtr< Scantable > calb1;
860 CountedPtr< Scantable > calb2;
861
862 msg=String("Processing dototalpower for subset of the data");
863 ostringstream oss1;
864 oss1 << msg << endl;
865 pushLog(String(oss1));
866 // Debug for IRC CS data
867 //float tcal1=7.0;
868 //float tcal2=4.0;
869 sig1 = dototalpower(sctables[0], sctables[1], tcal=tcal);
870 ref1 = dototalpower(sctables[2], sctables[3], tcal=tcal);
871 ref2 = dototalpower(sctables[4], sctables[5], tcal=tcal);
872 sig2 = dototalpower(sctables[6], sctables[7], tcal=tcal);
873
874 // correction of user-specified tsys for elevation here
875
876 // dosigref calibration
877 msg=String("Processing dosigref for subset of the data");
878 ostringstream oss2;
879 oss2 << msg << endl;
880 pushLog(String(oss2));
881 calb1=dosigref(sig1,ref2,smoothref,tsysv,tau);
882 calb2=dosigref(sig2,ref1,smoothref,tsysv,tau);
883
884 // iteration by scanno or cycle no.
885 Table& tcalb1 = calb1->table();
886 Table& tcalb2 = calb2->table();
887 TableIterator sit(tcalb1, "SCANNO");
888 TableIterator s2it(tcalb2, "SCANNO");
889 while ( !sit.pastEnd() ) {
890 Table t1 = sit.table();
891 Table t2= s2it.table();
892 ArrayColumn<Float> outspecCol(t1, "SPECTRA");
893 ArrayColumn<Float> outtsysCol(t1, "TSYS");
894 ArrayColumn<uChar> outflagCol(t1, "FLAGTRA");
895 ScalarColumn<Double> outintCol(t1, "INTERVAL");
896 ArrayColumn<Float> t2specCol(t2, "SPECTRA");
897 ROArrayColumn<Float> t2tsysCol(t2, "TSYS");
898 ArrayColumn<uChar> t2flagCol(t2, "FLAGTRA");
899 ROScalarColumn<Double> t2intCol(t2, "INTERVAL");
900 for (uInt i=0; i < t1.nrow(); ++i) {
901 Vector<Float> spec1, spec2;
902 // to store scalar (mean) tsys
903 Vector<Float> tsys1, tsys2;
904 Vector<uChar> flag1, flag2;
905 Double tint1, tint2;
906 outspecCol.get(i, spec1);
907 t2specCol.get(i, spec2);
908 outflagCol.get(i, flag1);
909 t2flagCol.get(i, flag2);
910 outtsysCol.get(i, tsys1);
911 t2tsysCol.get(i, tsys2);
912 outintCol.get(i, tint1);
913 t2intCol.get(i, tint2);
914 // average
915 // assume scalar tsys for weights
916 Float wt1, wt2, tsyssq1, tsyssq2;
917 tsyssq1 = tsys1[0]*tsys1[0];
918 tsyssq2 = tsys2[0]*tsys2[0];
919 wt1 = Float(tint1)/tsyssq1;
920 wt2 = Float(tint2)/tsyssq2;
921 Float invsumwt=1/(wt1+wt2);
922 MaskedArray<Float> mspec1 = maskedArray(spec1, flag1);
923 MaskedArray<Float> mspec2 = maskedArray(spec2, flag2);
924 MaskedArray<Float> avspec = invsumwt * (wt1*mspec1 + wt2*mspec2);
925 //Array<Float> avtsys = Float(0.5) * (tsys1 + tsys2);
926 // cerr<< "Tsys1="<<tsys1<<" Tsys2="<<tsys2<<endl;
927 tsys1[0] = sqrt(tsyssq1 + tsyssq2);
928 Array<Float> avtsys = tsys1;
929
930 outspecCol.put(i, avspec.getArray());
931 outflagCol.put(i, flagsFromMA(avspec));
932 outtsysCol.put(i, avtsys);
933 }
934 ++sit;
935 ++s2it;
936 }
937 return calb1;
938}
939
940//GBTIDL version of frequency switched data calibration
941CountedPtr< Scantable > STMath::dofs( const CountedPtr< Scantable >& s,
942 const std::vector<int>& scans,
943 int smoothref,
944 casa::Float tsysv,
945 casa::Float tau,
946 casa::Float tcal )
947{
948
949
950 STSelector sel;
951 CountedPtr< Scantable > ws = getScantable(s, false);
952 CountedPtr< Scantable > sig, sigwcal, ref, refwcal;
953 CountedPtr< Scantable > calsig, calref, out;
954
955 //split the data
956 sel.setName("*_fs");
957 ws->setSelection(sel);
958 sig = getScantable(ws,false);
959 sel.reset();
960 sel.setName("*_fs_calon");
961 ws->setSelection(sel);
962 sigwcal = getScantable(ws,false);
963 sel.reset();
964 sel.setName("*_fsr");
965 ws->setSelection(sel);
966 ref = getScantable(ws,false);
967 sel.reset();
968 sel.setName("*_fsr_calon");
969 ws->setSelection(sel);
970 refwcal = getScantable(ws,false);
971
972 calsig = dototalpower(sigwcal, sig, tcal=tcal);
973 calref = dototalpower(refwcal, ref, tcal=tcal);
974
975 out=dosigref(calsig,calref,smoothref,tsysv,tau);
976
977 return out;
978}
979
980
[805]981CountedPtr< Scantable > STMath::freqSwitch( const CountedPtr< Scantable >& in )
982{
983 // make copy or reference
984 CountedPtr< Scantable > out = getScantable(in, false);
985 Table& tout = out->table();
[1008]986 Block<String> cols(4);
[805]987 cols[0] = String("SCANNO");
[1008]988 cols[1] = String("CYCLENO");
989 cols[2] = String("BEAMNO");
990 cols[3] = String("POLNO");
[805]991 TableIterator iter(tout, cols);
992 while (!iter.pastEnd()) {
993 Table subt = iter.table();
994 // this should leave us with two rows for the two IFs....if not ignore
995 if (subt.nrow() != 2 ) {
996 continue;
[701]997 }
[1008]998 ArrayColumn<Float> specCol(subt, "SPECTRA");
999 ArrayColumn<Float> tsysCol(subt, "TSYS");
1000 ArrayColumn<uChar> flagCol(subt, "FLAGTRA");
[805]1001 Vector<Float> onspec,offspec, ontsys, offtsys;
1002 Vector<uChar> onflag, offflag;
1003 tsysCol.get(0, ontsys); tsysCol.get(1, offtsys);
1004 specCol.get(0, onspec); specCol.get(1, offspec);
1005 flagCol.get(0, onflag); flagCol.get(1, offflag);
1006 MaskedArray<Float> on = maskedArray(onspec, onflag);
1007 MaskedArray<Float> off = maskedArray(offspec, offflag);
1008 MaskedArray<Float> oncopy = on.copy();
[248]1009
[805]1010 on /= off; on -= 1.0f;
1011 on *= ontsys[0];
1012 off /= oncopy; off -= 1.0f;
1013 off *= offtsys[0];
1014 specCol.put(0, on.getArray());
1015 const Vector<Bool>& m0 = on.getMask();
1016 Vector<uChar> flags0(m0.shape());
1017 convertArray(flags0, !m0);
1018 flagCol.put(0, flags0);
[234]1019
[805]1020 specCol.put(1, off.getArray());
1021 const Vector<Bool>& m1 = off.getMask();
1022 Vector<uChar> flags1(m1.shape());
1023 convertArray(flags1, !m1);
1024 flagCol.put(1, flags1);
[867]1025 ++iter;
[130]1026 }
[780]1027
[805]1028 return out;
[9]1029}
[48]1030
[805]1031std::vector< float > STMath::statistic( const CountedPtr< Scantable > & in,
1032 const std::vector< bool > & mask,
1033 const std::string& which )
[130]1034{
1035
[805]1036 Vector<Bool> m(mask);
1037 const Table& tab = in->table();
1038 ROArrayColumn<Float> specCol(tab, "SPECTRA");
1039 ROArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1040 std::vector<float> out;
1041 for (uInt i=0; i < tab.nrow(); ++i ) {
1042 Vector<Float> spec; specCol.get(i, spec);
[867]1043 Vector<uChar> flag; flagCol.get(i, flag);
1044 MaskedArray<Float> ma = maskedArray(spec, flag);
1045 float outstat = 0.0;
[805]1046 if ( spec.nelements() == m.nelements() ) {
1047 outstat = mathutil::statistics(which, ma(m));
1048 } else {
1049 outstat = mathutil::statistics(which, ma);
1050 }
1051 out.push_back(outstat);
[234]1052 }
[805]1053 return out;
[130]1054}
1055
[805]1056CountedPtr< Scantable > STMath::bin( const CountedPtr< Scantable > & in,
1057 int width )
[144]1058{
[841]1059 if ( !in->getSelection().empty() ) throw(AipsError("Can't bin subset of the data."));
[805]1060 CountedPtr< Scantable > out = getScantable(in, false);
1061 Table& tout = out->table();
1062 out->frequencies().rescale(width, "BIN");
1063 ArrayColumn<Float> specCol(tout, "SPECTRA");
1064 ArrayColumn<uChar> flagCol(tout, "FLAGTRA");
1065 for (uInt i=0; i < tout.nrow(); ++i ) {
1066 MaskedArray<Float> main = maskedArray(specCol(i), flagCol(i));
1067 MaskedArray<Float> maout;
1068 LatticeUtilities::bin(maout, main, 0, Int(width));
1069 /// @todo implement channel based tsys binning
1070 specCol.put(i, maout.getArray());
1071 flagCol.put(i, flagsFromMA(maout));
1072 // take only the first binned spectrum's length for the deprecated
1073 // global header item nChan
1074 if (i==0) tout.rwKeywordSet().define(String("nChan"),
1075 Int(maout.getArray().nelements()));
[169]1076 }
[805]1077 return out;
[146]1078}
1079
[805]1080CountedPtr< Scantable > STMath::resample( const CountedPtr< Scantable >& in,
1081 const std::string& method,
1082 float width )
[299]1083//
1084// Should add the possibility of width being specified in km/s. This means
[780]1085// that for each freqID (SpectralCoordinate) we will need to convert to an
1086// average channel width (say at the reference pixel). Then we would need
1087// to be careful to make sure each spectrum (of different freqID)
[299]1088// is the same length.
1089//
1090{
[996]1091 //InterpolateArray1D<Double,Float>::InterpolationMethod interp;
[805]1092 Int interpMethod(stringToIMethod(method));
[299]1093
[805]1094 CountedPtr< Scantable > out = getScantable(in, false);
1095 Table& tout = out->table();
[299]1096
1097// Resample SpectralCoordinates (one per freqID)
[805]1098 out->frequencies().rescale(width, "RESAMPLE");
1099 TableIterator iter(tout, "IFNO");
1100 TableRow row(tout);
1101 while ( !iter.pastEnd() ) {
1102 Table tab = iter.table();
1103 ArrayColumn<Float> specCol(tab, "SPECTRA");
1104 //ArrayColumn<Float> tsysCol(tout, "TSYS");
1105 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1106 Vector<Float> spec;
1107 Vector<uChar> flag;
1108 specCol.get(0,spec); // the number of channels should be constant per IF
1109 uInt nChanIn = spec.nelements();
1110 Vector<Float> xIn(nChanIn); indgen(xIn);
1111 Int fac = Int(nChanIn/width);
1112 Vector<Float> xOut(fac+10); // 10 to be safe - resize later
1113 uInt k = 0;
1114 Float x = 0.0;
1115 while (x < Float(nChanIn) ) {
1116 xOut(k) = x;
1117 k++;
1118 x += width;
1119 }
1120 uInt nChanOut = k;
1121 xOut.resize(nChanOut, True);
1122 // process all rows for this IFNO
1123 Vector<Float> specOut;
1124 Vector<Bool> maskOut;
1125 Vector<uChar> flagOut;
1126 for (uInt i=0; i < tab.nrow(); ++i) {
1127 specCol.get(i, spec);
1128 flagCol.get(i, flag);
1129 Vector<Bool> mask(flag.nelements());
1130 convertArray(mask, flag);
[299]1131
[805]1132 IPosition shapeIn(spec.shape());
1133 //sh.nchan = nChanOut;
1134 InterpolateArray1D<Float,Float>::interpolate(specOut, maskOut, xOut,
1135 xIn, spec, mask,
1136 interpMethod, True, True);
1137 /// @todo do the same for channel based Tsys
1138 flagOut.resize(maskOut.nelements());
1139 convertArray(flagOut, maskOut);
1140 specCol.put(i, specOut);
1141 flagCol.put(i, flagOut);
1142 }
1143 ++iter;
[299]1144 }
1145
[805]1146 return out;
1147}
[299]1148
[805]1149STMath::imethod STMath::stringToIMethod(const std::string& in)
1150{
1151 static STMath::imap lookup;
[299]1152
[805]1153 // initialize the lookup table if necessary
1154 if ( lookup.empty() ) {
[926]1155 lookup["nearest"] = InterpolateArray1D<Double,Float>::nearestNeighbour;
1156 lookup["linear"] = InterpolateArray1D<Double,Float>::linear;
1157 lookup["cubic"] = InterpolateArray1D<Double,Float>::cubic;
1158 lookup["spline"] = InterpolateArray1D<Double,Float>::spline;
[299]1159 }
1160
[805]1161 STMath::imap::const_iterator iter = lookup.find(in);
[299]1162
[805]1163 if ( lookup.end() == iter ) {
1164 std::string message = in;
1165 message += " is not a valid interpolation mode";
1166 throw(AipsError(message));
[299]1167 }
[805]1168 return iter->second;
[299]1169}
1170
[805]1171WeightType STMath::stringToWeight(const std::string& in)
[146]1172{
[805]1173 static std::map<std::string, WeightType> lookup;
[434]1174
[805]1175 // initialize the lookup table if necessary
1176 if ( lookup.empty() ) {
1177 lookup["NONE"] = asap::NONE;
1178 lookup["TINT"] = asap::TINT;
1179 lookup["TINTSYS"] = asap::TINTSYS;
1180 lookup["TSYS"] = asap::TSYS;
1181 lookup["VAR"] = asap::VAR;
1182 }
[434]1183
[805]1184 std::map<std::string, WeightType>::const_iterator iter = lookup.find(in);
[294]1185
[805]1186 if ( lookup.end() == iter ) {
1187 std::string message = in;
1188 message += " is not a valid weighting mode";
1189 throw(AipsError(message));
1190 }
1191 return iter->second;
[146]1192}
1193
[805]1194CountedPtr< Scantable > STMath::gainElevation( const CountedPtr< Scantable >& in,
[867]1195 const vector< float > & coeff,
[805]1196 const std::string & filename,
1197 const std::string& method)
[165]1198{
[805]1199 // Get elevation data from Scantable and convert to degrees
1200 CountedPtr< Scantable > out = getScantable(in, false);
[926]1201 Table& tab = out->table();
[805]1202 ROScalarColumn<Float> elev(tab, "ELEVATION");
1203 Vector<Float> x = elev.getColumn();
1204 x *= Float(180 / C::pi); // Degrees
[165]1205
[867]1206 Vector<Float> coeffs(coeff);
[805]1207 const uInt nc = coeffs.nelements();
1208 if ( filename.length() > 0 && nc > 0 ) {
1209 throw(AipsError("You must choose either polynomial coefficients or an ascii file, not both"));
[315]1210 }
[165]1211
[805]1212 // Correct
1213 if ( nc > 0 || filename.length() == 0 ) {
1214 // Find instrument
1215 Bool throwit = True;
1216 Instrument inst =
[878]1217 STAttr::convertInstrument(tab.keywordSet().asString("AntennaName"),
[805]1218 throwit);
[165]1219
[805]1220 // Set polynomial
1221 Polynomial<Float>* ppoly = 0;
1222 Vector<Float> coeff;
1223 String msg;
1224 if ( nc > 0 ) {
1225 ppoly = new Polynomial<Float>(nc);
1226 coeff = coeffs;
1227 msg = String("user");
1228 } else {
[878]1229 STAttr sdAttr;
[805]1230 coeff = sdAttr.gainElevationPoly(inst);
1231 ppoly = new Polynomial<Float>(3);
1232 msg = String("built in");
1233 }
[532]1234
[805]1235 if ( coeff.nelements() > 0 ) {
1236 ppoly->setCoefficients(coeff);
1237 } else {
1238 delete ppoly;
1239 throw(AipsError("There is no known gain-elevation polynomial known for this instrument"));
1240 }
1241 ostringstream oss;
1242 oss << "Making polynomial correction with " << msg << " coefficients:" << endl;
1243 oss << " " << coeff;
1244 pushLog(String(oss));
1245 const uInt nrow = tab.nrow();
1246 Vector<Float> factor(nrow);
1247 for ( uInt i=0; i < nrow; ++i ) {
1248 factor[i] = 1.0 / (*ppoly)(x[i]);
1249 }
1250 delete ppoly;
1251 scaleByVector(tab, factor, true);
[532]1252
[805]1253 } else {
1254 // Read and correct
1255 pushLog("Making correction from ascii Table");
1256 scaleFromAsciiTable(tab, filename, method, x, true);
[532]1257 }
[805]1258 return out;
1259}
[165]1260
[805]1261void STMath::scaleFromAsciiTable(Table& in, const std::string& filename,
1262 const std::string& method,
1263 const Vector<Float>& xout, bool dotsys)
1264{
[165]1265
[805]1266// Read gain-elevation ascii file data into a Table.
[165]1267
[805]1268 String formatString;
1269 Table tbl = readAsciiTable(formatString, Table::Memory, filename, "", "", False);
1270 scaleFromTable(in, tbl, method, xout, dotsys);
1271}
[165]1272
[805]1273void STMath::scaleFromTable(Table& in,
1274 const Table& table,
1275 const std::string& method,
1276 const Vector<Float>& xout, bool dotsys)
1277{
[780]1278
[805]1279 ROScalarColumn<Float> geElCol(table, "ELEVATION");
1280 ROScalarColumn<Float> geFacCol(table, "FACTOR");
1281 Vector<Float> xin = geElCol.getColumn();
1282 Vector<Float> yin = geFacCol.getColumn();
1283 Vector<Bool> maskin(xin.nelements(),True);
[165]1284
[805]1285 // Interpolate (and extrapolate) with desired method
[532]1286
[996]1287 InterpolateArray1D<Double,Float>::InterpolationMethod interp = stringToIMethod(method);
[165]1288
[805]1289 Vector<Float> yout;
1290 Vector<Bool> maskout;
1291 InterpolateArray1D<Float,Float>::interpolate(yout, maskout, xout,
[996]1292 xin, yin, maskin, interp,
[805]1293 True, True);
[165]1294
[805]1295 scaleByVector(in, Float(1.0)/yout, dotsys);
[165]1296}
[167]1297
[805]1298void STMath::scaleByVector( Table& in,
1299 const Vector< Float >& factor,
1300 bool dotsys )
[177]1301{
[805]1302 uInt nrow = in.nrow();
1303 if ( factor.nelements() != nrow ) {
1304 throw(AipsError("factors.nelements() != table.nelements()"));
1305 }
1306 ArrayColumn<Float> specCol(in, "SPECTRA");
1307 ArrayColumn<uChar> flagCol(in, "FLAGTRA");
1308 ArrayColumn<Float> tsysCol(in, "TSYS");
1309 for (uInt i=0; i < nrow; ++i) {
1310 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
1311 ma *= factor[i];
1312 specCol.put(i, ma.getArray());
1313 flagCol.put(i, flagsFromMA(ma));
1314 if ( dotsys ) {
[926]1315 Vector<Float> tsys = tsysCol(i);
[805]1316 tsys *= factor[i];
[926]1317 tsysCol.put(i,tsys);
[805]1318 }
1319 }
[177]1320}
1321
[805]1322CountedPtr< Scantable > STMath::convertFlux( const CountedPtr< Scantable >& in,
1323 float d, float etaap,
1324 float jyperk )
[221]1325{
[805]1326 CountedPtr< Scantable > out = getScantable(in, false);
1327 Table& tab = in->table();
1328 Unit fluxUnit(tab.keywordSet().asString("FluxUnit"));
[221]1329 Unit K(String("K"));
1330 Unit JY(String("Jy"));
[701]1331
[805]1332 bool tokelvin = true;
1333 Double cfac = 1.0;
[716]1334
[805]1335 if ( fluxUnit == JY ) {
[716]1336 pushLog("Converting to K");
[701]1337 Quantum<Double> t(1.0,fluxUnit);
1338 Quantum<Double> t2 = t.get(JY);
[805]1339 cfac = (t2 / t).getValue(); // value to Jy
[780]1340
[805]1341 tokelvin = true;
1342 out->setFluxUnit("K");
1343 } else if ( fluxUnit == K ) {
[716]1344 pushLog("Converting to Jy");
[701]1345 Quantum<Double> t(1.0,fluxUnit);
1346 Quantum<Double> t2 = t.get(K);
[805]1347 cfac = (t2 / t).getValue(); // value to K
[780]1348
[805]1349 tokelvin = false;
1350 out->setFluxUnit("Jy");
[221]1351 } else {
[701]1352 throw(AipsError("Unrecognized brightness units in Table - must be consistent with Jy or K"));
[221]1353 }
[701]1354 // Make sure input values are converted to either Jy or K first...
[805]1355 Float factor = cfac;
[221]1356
[701]1357 // Select method
[805]1358 if (jyperk > 0.0) {
1359 factor *= jyperk;
1360 if ( tokelvin ) factor = 1.0 / jyperk;
[716]1361 ostringstream oss;
[805]1362 oss << "Jy/K = " << jyperk;
[716]1363 pushLog(String(oss));
[805]1364 Vector<Float> factors(tab.nrow(), factor);
1365 scaleByVector(tab,factors, false);
1366 } else if ( etaap > 0.0) {
[1319]1367 if (d < 0) {
1368 Instrument inst =
1369 STAttr::convertInstrument(tab.keywordSet().asString("AntennaName"),
1370 True);
1371 STAttr sda;
1372 d = sda.diameter(inst);
1373 }
[996]1374 jyperk = STAttr::findJyPerK(etaap, d);
[716]1375 ostringstream oss;
[805]1376 oss << "Jy/K = " << jyperk;
[716]1377 pushLog(String(oss));
[805]1378 factor *= jyperk;
1379 if ( tokelvin ) {
[701]1380 factor = 1.0 / factor;
1381 }
[805]1382 Vector<Float> factors(tab.nrow(), factor);
1383 scaleByVector(tab, factors, False);
[354]1384 } else {
[780]1385
[701]1386 // OK now we must deal with automatic look up of values.
1387 // We must also deal with the fact that the factors need
1388 // to be computed per IF and may be different and may
1389 // change per integration.
[780]1390
[716]1391 pushLog("Looking up conversion factors");
[805]1392 convertBrightnessUnits(out, tokelvin, cfac);
[701]1393 }
[805]1394
1395 return out;
[221]1396}
1397
[805]1398void STMath::convertBrightnessUnits( CountedPtr<Scantable>& in,
1399 bool tokelvin, float cfac )
[227]1400{
[805]1401 Table& table = in->table();
1402 Instrument inst =
[878]1403 STAttr::convertInstrument(table.keywordSet().asString("AntennaName"), True);
[805]1404 TableIterator iter(table, "FREQ_ID");
1405 STFrequencies stfreqs = in->frequencies();
[878]1406 STAttr sdAtt;
[805]1407 while (!iter.pastEnd()) {
1408 Table tab = iter.table();
1409 ArrayColumn<Float> specCol(tab, "SPECTRA");
1410 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1411 ROScalarColumn<uInt> freqidCol(tab, "FREQ_ID");
1412 MEpoch::ROScalarColumn timeCol(tab, "TIME");
[234]1413
[805]1414 uInt freqid; freqidCol.get(0, freqid);
1415 Vector<Float> tmpspec; specCol.get(0, tmpspec);
[878]1416 // STAttr.JyPerK has a Vector interface... change sometime.
[805]1417 Vector<Float> freqs(1,stfreqs.getRefFreq(freqid, tmpspec.nelements()));
1418 for ( uInt i=0; i<tab.nrow(); ++i) {
1419 Float jyperk = (sdAtt.JyPerK(inst, timeCol(i), freqs))[0];
1420 Float factor = cfac * jyperk;
1421 if ( tokelvin ) factor = Float(1.0) / factor;
1422 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
1423 ma *= factor;
1424 specCol.put(i, ma.getArray());
1425 flagCol.put(i, flagsFromMA(ma));
1426 }
[867]1427 ++iter;
[234]1428 }
[230]1429}
[227]1430
[805]1431CountedPtr< Scantable > STMath::opacity( const CountedPtr< Scantable > & in,
1432 float tau )
[234]1433{
[805]1434 CountedPtr< Scantable > out = getScantable(in, false);
[926]1435
1436 Table tab = out->table();
[234]1437 ROScalarColumn<Float> elev(tab, "ELEVATION");
[805]1438 ArrayColumn<Float> specCol(tab, "SPECTRA");
1439 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1440 for ( uInt i=0; i<tab.nrow(); ++i) {
1441 Float zdist = Float(C::pi_2) - elev(i);
[1318]1442 Float factor = exp(tau/cos(zdist));
[926]1443 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
[805]1444 ma *= factor;
1445 specCol.put(i, ma.getArray());
1446 flagCol.put(i, flagsFromMA(ma));
[234]1447 }
[805]1448 return out;
[234]1449}
1450
[1373]1451CountedPtr< Scantable > STMath::smoothOther( const CountedPtr< Scantable >& in,
1452 const std::string& kernel,
1453 float width )
1454{
1455 CountedPtr< Scantable > out = getScantable(in, false);
1456 Table& table = out->table();
1457 ArrayColumn<Float> specCol(table, "SPECTRA");
1458 ArrayColumn<uChar> flagCol(table, "FLAGTRA");
1459 Vector<Float> spec;
1460 Vector<uChar> flag;
1461 for ( uInt i=0; i<table.nrow(); ++i) {
1462 specCol.get(i, spec);
1463 flagCol.get(i, flag);
1464 Vector<Bool> mask(flag.nelements());
1465 convertArray(mask, flag);
1466 Vector<Float> specout;
1467 Vector<Bool> maskout;
1468 if ( kernel == "hanning" ) {
1469 mathutil::hanning(specout, maskout, spec , !mask);
1470 convertArray(flag, !maskout);
1471 } else if ( kernel == "rmedian" ) {
1472 mathutil::runningMedian(specout, maskout, spec , mask, width);
1473 convertArray(flag, maskout);
1474 }
1475 flagCol.put(i, flag);
1476 specCol.put(i, specout);
1477 }
1478 return out;
1479}
1480
[805]1481CountedPtr< Scantable > STMath::smooth( const CountedPtr< Scantable >& in,
1482 const std::string& kernel, float width )
[457]1483{
[1373]1484 if (kernel == "rmedian" || kernel == "hanning") {
1485 return smoothOther(in, kernel, width);
1486 }
[805]1487 CountedPtr< Scantable > out = getScantable(in, false);
[1033]1488 Table& table = out->table();
[805]1489 VectorKernel::KernelTypes type = VectorKernel::toKernelType(kernel);
1490 // same IFNO should have same no of channels
1491 // this saves overhead
1492 TableIterator iter(table, "IFNO");
1493 while (!iter.pastEnd()) {
1494 Table tab = iter.table();
1495 ArrayColumn<Float> specCol(tab, "SPECTRA");
1496 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1497 Vector<Float> tmpspec; specCol.get(0, tmpspec);
1498 uInt nchan = tmpspec.nelements();
1499 Vector<Float> kvec = VectorKernel::make(type, width, nchan, True, False);
1500 Convolver<Float> conv(kvec, IPosition(1,nchan));
1501 Vector<Float> spec;
1502 Vector<uChar> flag;
1503 for ( uInt i=0; i<tab.nrow(); ++i) {
1504 specCol.get(i, spec);
1505 flagCol.get(i, flag);
1506 Vector<Bool> mask(flag.nelements());
1507 convertArray(mask, flag);
1508 Vector<Float> specout;
[1373]1509 mathutil::replaceMaskByZero(specout, mask);
1510 conv.linearConv(specout, spec);
1511 specCol.put(i, specout);
[805]1512 }
[867]1513 ++iter;
[701]1514 }
[805]1515 return out;
[701]1516}
[841]1517
1518CountedPtr< Scantable >
1519 STMath::merge( const std::vector< CountedPtr < Scantable > >& in )
1520{
1521 if ( in.size() < 2 ) {
[862]1522 throw(AipsError("Need at least two scantables to perform a merge."));
[841]1523 }
1524 std::vector<CountedPtr < Scantable > >::const_iterator it = in.begin();
1525 bool insitu = insitu_;
1526 setInsitu(false);
[862]1527 CountedPtr< Scantable > out = getScantable(*it, false);
[841]1528 setInsitu(insitu);
1529 Table& tout = out->table();
1530 ScalarColumn<uInt> freqidcol(tout,"FREQ_ID"), molidcol(tout, "MOLECULE_ID");
[917]1531 ScalarColumn<uInt> scannocol(tout,"SCANNO"), focusidcol(tout,"FOCUS_ID");
1532 // Renumber SCANNO to be 0-based
[926]1533 Vector<uInt> scannos = scannocol.getColumn();
1534 uInt offset = min(scannos);
[917]1535 scannos -= offset;
[926]1536 scannocol.putColumn(scannos);
1537 uInt newscanno = max(scannos)+1;
[862]1538 ++it;
[841]1539 while ( it != in.end() ){
1540 if ( ! (*it)->conformant(*out) ) {
1541 // log message: "ignoring scantable i, as it isn't
1542 // conformant with the other(s)"
1543 cerr << "oh oh" << endl;
1544 ++it;
1545 continue;
1546 }
[862]1547 out->appendToHistoryTable((*it)->history());
[841]1548 const Table& tab = (*it)->table();
1549 TableIterator scanit(tab, "SCANNO");
1550 while (!scanit.pastEnd()) {
1551 TableIterator freqit(scanit.table(), "FREQ_ID");
1552 while ( !freqit.pastEnd() ) {
1553 Table thetab = freqit.table();
1554 uInt nrow = tout.nrow();
1555 //tout.addRow(thetab.nrow());
1556 TableCopy::copyRows(tout, thetab, nrow, 0, thetab.nrow());
1557 ROTableRow row(thetab);
1558 for ( uInt i=0; i<thetab.nrow(); ++i) {
1559 uInt k = nrow+i;
1560 scannocol.put(k, newscanno);
1561 const TableRecord& rec = row.get(i);
1562 Double rv,rp,inc;
1563 (*it)->frequencies().getEntry(rp, rv, inc, rec.asuInt("FREQ_ID"));
1564 uInt id;
1565 id = out->frequencies().addEntry(rp, rv, inc);
1566 freqidcol.put(k,id);
1567 String name,fname;Double rf;
1568 (*it)->molecules().getEntry(rf, name, fname, rec.asuInt("MOLECULE_ID"));
1569 id = out->molecules().addEntry(rf, name, fname);
1570 molidcol.put(k, id);
[961]1571 Float frot,fax,ftan,fhand,fmount,fuser, fxy, fxyp;
1572 (*it)->focus().getEntry(fax, ftan, frot, fhand,
1573 fmount,fuser, fxy, fxyp,
1574 rec.asuInt("FOCUS_ID"));
1575 id = out->focus().addEntry(fax, ftan, frot, fhand,
1576 fmount,fuser, fxy, fxyp);
[841]1577 focusidcol.put(k, id);
1578 }
1579 ++freqit;
1580 }
1581 ++newscanno;
1582 ++scanit;
1583 }
1584 ++it;
1585 }
1586 return out;
1587}
[896]1588
1589CountedPtr< Scantable >
1590 STMath::invertPhase( const CountedPtr < Scantable >& in )
1591{
[996]1592 return applyToPol(in, &STPol::invertPhase, Float(0.0));
[896]1593}
1594
1595CountedPtr< Scantable >
1596 STMath::rotateXYPhase( const CountedPtr < Scantable >& in, float phase )
1597{
1598 return applyToPol(in, &STPol::rotatePhase, Float(phase));
1599}
1600
1601CountedPtr< Scantable >
1602 STMath::rotateLinPolPhase( const CountedPtr < Scantable >& in, float phase )
1603{
1604 return applyToPol(in, &STPol::rotateLinPolPhase, Float(phase));
1605}
1606
1607CountedPtr< Scantable > STMath::applyToPol( const CountedPtr<Scantable>& in,
1608 STPol::polOperation fptr,
1609 Float phase )
1610{
1611 CountedPtr< Scantable > out = getScantable(in, false);
1612 Table& tout = out->table();
1613 Block<String> cols(4);
1614 cols[0] = String("SCANNO");
1615 cols[1] = String("BEAMNO");
1616 cols[2] = String("IFNO");
1617 cols[3] = String("CYCLENO");
1618 TableIterator iter(tout, cols);
[1384]1619 CountedPtr<STPol> stpol = STPol::getPolClass(out->factories_,
1620 out->getPolType() );
[896]1621 while (!iter.pastEnd()) {
1622 Table t = iter.table();
1623 ArrayColumn<Float> speccol(t, "SPECTRA");
[1015]1624 ScalarColumn<uInt> focidcol(t, "FOCUS_ID");
1625 ScalarColumn<Float> parancol(t, "PARANGLE");
[1384]1626 Matrix<Float> pols(speccol.getColumn());
[896]1627 try {
1628 stpol->setSpectra(pols);
[1015]1629 Float fang,fhand,parang;
1630 fang = in->focusTable_.getTotalFeedAngle(focidcol(0));
1631 fhand = in->focusTable_.getFeedHand(focidcol(0));
1632 parang = parancol(0);
1633 /// @todo re-enable this
1634 // disable total feed angle to support paralactifying Caswell style
1635 stpol->setPhaseCorrections(parang, -parang, fhand);
[1384]1636 // use a member function pointer in STPol. This only works on
1637 // the STPol pointer itself, not the Counted Pointer so
1638 // derefernce it.
1639 (&(*(stpol))->*fptr)(phase);
[896]1640 speccol.putColumn(stpol->getSpectra());
1641 } catch (AipsError& e) {
[1384]1642 //delete stpol;stpol=0;
[896]1643 throw(e);
1644 }
1645 ++iter;
1646 }
[1384]1647 //delete stpol;stpol=0;
[896]1648 return out;
1649}
1650
1651CountedPtr< Scantable >
1652 STMath::swapPolarisations( const CountedPtr< Scantable > & in )
1653{
1654 CountedPtr< Scantable > out = getScantable(in, false);
1655 Table& tout = out->table();
1656 Table t0 = tout(tout.col("POLNO") == 0);
1657 Table t1 = tout(tout.col("POLNO") == 1);
1658 if ( t0.nrow() != t1.nrow() )
1659 throw(AipsError("Inconsistent number of polarisations"));
1660 ArrayColumn<Float> speccol0(t0, "SPECTRA");
1661 ArrayColumn<uChar> flagcol0(t0, "FLAGTRA");
1662 ArrayColumn<Float> speccol1(t1, "SPECTRA");
1663 ArrayColumn<uChar> flagcol1(t1, "FLAGTRA");
1664 Matrix<Float> s0 = speccol0.getColumn();
1665 Matrix<uChar> f0 = flagcol0.getColumn();
1666 speccol0.putColumn(speccol1.getColumn());
1667 flagcol0.putColumn(flagcol1.getColumn());
1668 speccol1.putColumn(s0);
1669 flagcol1.putColumn(f0);
1670 return out;
1671}
[917]1672
1673CountedPtr< Scantable >
[940]1674 STMath::averagePolarisations( const CountedPtr< Scantable > & in,
1675 const std::vector<bool>& mask,
1676 const std::string& weight )
1677{
[1232]1678 if (in->npol() < 2 )
1679 throw(AipsError("averagePolarisations can only be applied to two or more"
1680 "polarisations"));
[1010]1681 bool insitu = insitu_;
1682 setInsitu(false);
[1232]1683 CountedPtr< Scantable > pols = getScantable(in, true);
[1010]1684 setInsitu(insitu);
1685 Table& tout = pols->table();
[1232]1686 std::string taql = "SELECT FROM $1 WHERE POLNO IN [0,1]";
1687 Table tab = tableCommand(taql, in->table());
1688 if (tab.nrow() == 0 )
1689 throw(AipsError("Could not find any rows with POLNO==0 and POLNO==1"));
1690 TableCopy::copyRows(tout, tab);
[1145]1691 TableVector<uInt> vec(tout, "POLNO");
[940]1692 vec = 0;
[1145]1693 pols->table_.rwKeywordSet().define("nPol", Int(1));
[1391]1694 //pols->table_.rwKeywordSet().define("POLTYPE", String("stokes"));
1695 pols->table_.rwKeywordSet().define("POLTYPE", in->getPolType());
[1010]1696 std::vector<CountedPtr<Scantable> > vpols;
1697 vpols.push_back(pols);
[1232]1698 CountedPtr< Scantable > out = average(vpols, mask, weight, "SCAN");
[940]1699 return out;
1700}
1701
[1145]1702CountedPtr< Scantable >
1703 STMath::averageBeams( const CountedPtr< Scantable > & in,
1704 const std::vector<bool>& mask,
1705 const std::string& weight )
1706{
1707 bool insitu = insitu_;
1708 setInsitu(false);
1709 CountedPtr< Scantable > beams = getScantable(in, false);
1710 setInsitu(insitu);
1711 Table& tout = beams->table();
1712 // give all rows the same BEAMNO
1713 TableVector<uInt> vec(tout, "BEAMNO");
1714 vec = 0;
1715 beams->table_.rwKeywordSet().define("nBeam", Int(1));
1716 std::vector<CountedPtr<Scantable> > vbeams;
1717 vbeams.push_back(beams);
[1232]1718 CountedPtr< Scantable > out = average(vbeams, mask, weight, "SCAN");
[1145]1719 return out;
1720}
[940]1721
[1145]1722
[940]1723CountedPtr< Scantable >
[917]1724 asap::STMath::frequencyAlign( const CountedPtr< Scantable > & in,
1725 const std::string & refTime,
[926]1726 const std::string & method)
[917]1727{
[940]1728 // clone as this is not working insitu
1729 bool insitu = insitu_;
1730 setInsitu(false);
[917]1731 CountedPtr< Scantable > out = getScantable(in, false);
[940]1732 setInsitu(insitu);
[917]1733 Table& tout = out->table();
1734 // Get reference Epoch to time of first row or given String
1735 Unit DAY(String("d"));
1736 MEpoch::Ref epochRef(in->getTimeReference());
1737 MEpoch refEpoch;
1738 if (refTime.length()>0) {
1739 Quantum<Double> qt;
1740 if (MVTime::read(qt,refTime)) {
1741 MVEpoch mv(qt);
1742 refEpoch = MEpoch(mv, epochRef);
1743 } else {
1744 throw(AipsError("Invalid format for Epoch string"));
1745 }
1746 } else {
1747 refEpoch = in->timeCol_(0);
1748 }
1749 MPosition refPos = in->getAntennaPosition();
[940]1750
[996]1751 InterpolateArray1D<Double,Float>::InterpolationMethod interp = stringToIMethod(method);
[917]1752 // test if user frame is different to base frame
1753 if ( in->frequencies().getFrameString(true)
1754 == in->frequencies().getFrameString(false) ) {
[985]1755 throw(AipsError("Can't convert as no output frame has been set"
1756 " (use set_freqframe) or it is aligned already."));
[917]1757 }
1758 MFrequency::Types system = in->frequencies().getFrame();
[940]1759 MVTime mvt(refEpoch.getValue());
1760 String epochout = mvt.string(MVTime::YMD) + String(" (") + refEpoch.getRefString() + String(")");
1761 ostringstream oss;
1762 oss << "Aligned at reference Epoch " << epochout
1763 << " in frame " << MFrequency::showType(system);
1764 pushLog(String(oss));
[917]1765 // set up the iterator
[926]1766 Block<String> cols(4);
1767 // select by constant direction
[917]1768 cols[0] = String("SRCNAME");
1769 cols[1] = String("BEAMNO");
1770 // select by IF ( no of channels varies over this )
1771 cols[2] = String("IFNO");
[926]1772 // select by restfrequency
1773 cols[3] = String("MOLECULE_ID");
[917]1774 TableIterator iter(tout, cols);
[926]1775 while ( !iter.pastEnd() ) {
[917]1776 Table t = iter.table();
1777 MDirection::ROScalarColumn dirCol(t, "DIRECTION");
[926]1778 TableIterator fiter(t, "FREQ_ID");
[917]1779 // determine nchan from the first row. This should work as
[926]1780 // we are iterating over BEAMNO and IFNO // we should have constant direction
1781
[917]1782 ROArrayColumn<Float> sCol(t, "SPECTRA");
[926]1783 MDirection direction = dirCol(0);
[917]1784 uInt nchan = sCol(0).nelements();
[926]1785 while ( !fiter.pastEnd() ) {
1786 Table ftab = fiter.table();
1787 ScalarColumn<uInt> freqidCol(ftab, "FREQ_ID");
1788 // get the SpectralCoordinate for the freqid, which we are iterating over
1789 SpectralCoordinate sC = in->frequencies().getSpectralCoordinate(freqidCol(0));
1790 FrequencyAligner<Float> fa( sC, nchan, refEpoch,
1791 direction, refPos, system );
1792 // realign the SpectralCoordinate and put into the output Scantable
1793 Vector<String> units(1);
1794 units = String("Hz");
1795 Bool linear=True;
1796 SpectralCoordinate sc2 = fa.alignedSpectralCoordinate(linear);
1797 sc2.setWorldAxisUnits(units);
[934]1798 uInt id = out->frequencies().addEntry(sc2.referencePixel()[0],
1799 sc2.referenceValue()[0],
1800 sc2.increment()[0]);
1801 TableVector<uInt> tvec(ftab, "FREQ_ID");
1802 tvec = id;
[926]1803 // create the "global" abcissa for alignment with same FREQ_ID
1804 Vector<Double> abc(nchan);
[917]1805 Double w;
1806 for (uInt i=0; i<nchan; i++) {
1807 sC.toWorld(w,Double(i));
1808 abc[i] = w;
1809 }
[926]1810 // cache abcissa for same time stamps, so iterate over those
1811 TableIterator timeiter(ftab, "TIME");
1812 while ( !timeiter.pastEnd() ) {
1813 Table tab = timeiter.table();
1814 ArrayColumn<Float> specCol(tab, "SPECTRA");
1815 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1816 MEpoch::ROScalarColumn timeCol(tab, "TIME");
1817 // use align abcissa cache after the first row
1818 bool first = true;
1819 // these rows should be just be POLNO
[996]1820 for (int i=0; i<int(tab.nrow()); ++i) {
[926]1821 // input values
1822 Vector<uChar> flag = flagCol(i);
1823 Vector<Bool> mask(flag.shape());
1824 Vector<Float> specOut, spec;
1825 spec = specCol(i);
1826 Vector<Bool> maskOut;Vector<uChar> flagOut;
1827 convertArray(mask, flag);
1828 // alignment
1829 Bool ok = fa.align(specOut, maskOut, abc, spec,
1830 mask, timeCol(i), !first,
1831 interp, False);
1832 // back into scantable
1833 flagOut.resize(maskOut.nelements());
1834 convertArray(flagOut, maskOut);
1835 flagCol.put(i, flagOut);
1836 specCol.put(i, specOut);
1837 // start abcissa caching
1838 first = false;
[917]1839 }
[926]1840 // next timestamp
1841 ++timeiter;
[917]1842 }
[940]1843 // next FREQ_ID
[926]1844 ++fiter;
[917]1845 }
1846 // next aligner
1847 ++iter;
1848 }
[940]1849 // set this afterwards to ensure we are doing insitu correctly.
1850 out->frequencies().setFrame(system, true);
[917]1851 return out;
1852}
[992]1853
1854CountedPtr<Scantable>
1855 asap::STMath::convertPolarisation( const CountedPtr<Scantable>& in,
1856 const std::string & newtype )
1857{
1858 if (in->npol() != 2 && in->npol() != 4)
1859 throw(AipsError("Can only convert two or four polarisations."));
1860 if ( in->getPolType() == newtype )
1861 throw(AipsError("No need to convert."));
[1000]1862 if ( ! in->selector_.empty() )
1863 throw(AipsError("Can only convert whole scantable. Unset the selection."));
[992]1864 bool insitu = insitu_;
1865 setInsitu(false);
1866 CountedPtr< Scantable > out = getScantable(in, true);
1867 setInsitu(insitu);
1868 Table& tout = out->table();
1869 tout.rwKeywordSet().define("POLTYPE", String(newtype));
1870
1871 Block<String> cols(4);
1872 cols[0] = "SCANNO";
1873 cols[1] = "CYCLENO";
1874 cols[2] = "BEAMNO";
1875 cols[3] = "IFNO";
1876 TableIterator it(in->originalTable_, cols);
1877 String basetype = in->getPolType();
1878 STPol* stpol = STPol::getPolClass(in->factories_, basetype);
1879 try {
1880 while ( !it.pastEnd() ) {
1881 Table tab = it.table();
1882 uInt row = tab.rowNumbers()[0];
1883 stpol->setSpectra(in->getPolMatrix(row));
1884 Float fang,fhand,parang;
1885 fang = in->focusTable_.getTotalFeedAngle(in->mfocusidCol_(row));
1886 fhand = in->focusTable_.getFeedHand(in->mfocusidCol_(row));
1887 parang = in->paraCol_(row);
1888 /// @todo re-enable this
1889 // disable total feed angle to support paralactifying Caswell style
1890 stpol->setPhaseCorrections(parang, -parang, fhand);
1891 Int npolout = 0;
1892 for (uInt i=0; i<tab.nrow(); ++i) {
1893 Vector<Float> outvec = stpol->getSpectrum(i, newtype);
1894 if ( outvec.nelements() > 0 ) {
1895 tout.addRow();
1896 TableCopy::copyRows(tout, tab, tout.nrow()-1, 0, 1);
1897 ArrayColumn<Float> sCol(tout,"SPECTRA");
1898 ScalarColumn<uInt> pCol(tout,"POLNO");
1899 sCol.put(tout.nrow()-1 ,outvec);
1900 pCol.put(tout.nrow()-1 ,uInt(npolout));
1901 npolout++;
1902 }
1903 }
1904 tout.rwKeywordSet().define("nPol", npolout);
1905 ++it;
1906 }
1907 } catch (AipsError& e) {
1908 delete stpol;
1909 throw(e);
1910 }
1911 delete stpol;
1912 return out;
1913}
[1066]1914
[1143]1915CountedPtr< Scantable >
[1140]1916 asap::STMath::mxExtract( const CountedPtr< Scantable > & in,
1917 const std::string & scantype )
1918{
1919 bool insitu = insitu_;
1920 setInsitu(false);
1921 CountedPtr< Scantable > out = getScantable(in, true);
1922 setInsitu(insitu);
1923 Table& tout = out->table();
1924 std::string taql = "SELECT FROM $1 WHERE BEAMNO != REFBEAMNO";
1925 if (scantype == "on") {
1926 taql = "SELECT FROM $1 WHERE BEAMNO == REFBEAMNO";
1927 }
1928 Table tab = tableCommand(taql, in->table());
1929 TableCopy::copyRows(tout, tab);
1930 if (scantype == "on") {
[1143]1931 // re-index SCANNO to 0
[1140]1932 TableVector<uInt> vec(tout, "SCANNO");
1933 vec = 0;
1934 }
1935 return out;
1936}
[1192]1937
1938CountedPtr< Scantable >
1939 asap::STMath::lagFlag( const CountedPtr< Scantable > & in,
[1200]1940 double frequency, double width )
[1192]1941{
1942 CountedPtr< Scantable > out = getScantable(in, false);
1943 Table& tout = out->table();
1944 TableIterator iter(tout, "FREQ_ID");
1945 FFTServer<Float,Complex> ffts;
1946 while ( !iter.pastEnd() ) {
1947 Table tab = iter.table();
1948 Double rp,rv,inc;
1949 ROTableRow row(tab);
1950 const TableRecord& rec = row.get(0);
1951 uInt freqid = rec.asuInt("FREQ_ID");
1952 out->frequencies().getEntry(rp, rv, inc, freqid);
1953 ArrayColumn<Float> specCol(tab, "SPECTRA");
1954 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1955 for (int i=0; i<int(tab.nrow()); ++i) {
1956 Vector<Float> spec = specCol(i);
1957 Vector<uChar> flag = flagCol(i);
[1200]1958 Int lag0 = Int(spec.nelements()*abs(inc)/(frequency+width)+0.5);
1959 Int lag1 = Int(spec.nelements()*abs(inc)/(frequency-width)+0.5);
[1192]1960 for (int k=0; k < flag.nelements(); ++k ) {
1961 if (flag[k] > 0) {
1962 spec[k] = 0.0;
1963 }
1964 }
1965 Vector<Complex> lags;
[1203]1966 ffts.fft0(lags, spec);
[1200]1967 Int start = max(0, lag0);
1968 Int end = min(Int(lags.nelements()-1), lag1);
[1192]1969 if (start == end) {
1970 lags[start] = Complex(0.0);
1971 } else {
1972 for (int j=start; j <=end ;++j) {
1973 lags[j] = Complex(0.0);
1974 }
1975 }
[1203]1976 ffts.fft0(spec, lags);
[1192]1977 specCol.put(i, spec);
1978 }
1979 ++iter;
1980 }
1981 return out;
1982}
Note: See TracBrowser for help on using the repository browser.