source: trunk/src/STMath.cpp@ 1317

Last change on this file since 1317 was 1314, checked in by mar637, 18 years ago

fixed defect, where scantable averaging output failed if first row in ouput was all flagged

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 49.0 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"
[2]50
[805]51using namespace casa;
[2]52
[83]53using namespace asap;
[2]54
[805]55STMath::STMath(bool insitu) :
56 insitu_(insitu)
[716]57{
58}
[170]59
60
[805]61STMath::~STMath()
[170]62{
63}
64
[805]65CountedPtr<Scantable>
[977]66STMath::average( const std::vector<CountedPtr<Scantable> >& in,
[858]67 const std::vector<bool>& mask,
[805]68 const std::string& weight,
[977]69 const std::string& avmode)
[262]70{
[977]71 if ( avmode == "SCAN" && in.size() != 1 )
[1066]72 throw(AipsError("Can't perform 'SCAN' averaging on multiple tables.\n"
73 "Use merge first."));
[805]74 WeightType wtype = stringToWeight(weight);
[926]75
[805]76 // output
77 // clone as this is non insitu
78 bool insitu = insitu_;
79 setInsitu(false);
[977]80 CountedPtr< Scantable > out = getScantable(in[0], true);
[805]81 setInsitu(insitu);
[977]82 std::vector<CountedPtr<Scantable> >::const_iterator stit = in.begin();
[862]83 ++stit;
[977]84 while ( stit != in.end() ) {
[862]85 out->appendToHistoryTable((*stit)->history());
86 ++stit;
87 }
[294]88
[805]89 Table& tout = out->table();
[701]90
[805]91 /// @todo check if all scantables are conformant
[294]92
[805]93 ArrayColumn<Float> specColOut(tout,"SPECTRA");
94 ArrayColumn<uChar> flagColOut(tout,"FLAGTRA");
95 ArrayColumn<Float> tsysColOut(tout,"TSYS");
96 ScalarColumn<Double> mjdColOut(tout,"TIME");
97 ScalarColumn<Double> intColOut(tout,"INTERVAL");
[1008]98 ScalarColumn<uInt> cycColOut(tout,"CYCLENO");
[1145]99 ScalarColumn<uInt> scanColOut(tout,"SCANNO");
[262]100
[805]101 // set up the output table rows. These are based on the structure of the
[862]102 // FIRST scantable in the vector
[977]103 const Table& baset = in[0]->table();
[262]104
[805]105 Block<String> cols(3);
106 cols[0] = String("BEAMNO");
107 cols[1] = String("IFNO");
108 cols[2] = String("POLNO");
109 if ( avmode == "SOURCE" ) {
110 cols.resize(4);
111 cols[3] = String("SRCNAME");
[488]112 }
[977]113 if ( avmode == "SCAN" && in.size() == 1) {
[805]114 cols.resize(4);
115 cols[3] = String("SCANNO");
[2]116 }
[805]117 uInt outrowCount = 0;
118 TableIterator iter(baset, cols);
119 while (!iter.pastEnd()) {
120 Table subt = iter.table();
121 // copy the first row of this selection into the new table
122 tout.addRow();
123 TableCopy::copyRows(tout, subt, outrowCount, 0, 1);
[1145]124 // re-index to 0
125 if ( avmode != "SCAN" && avmode != "SOURCE" ) {
126 scanColOut.put(outrowCount, uInt(0));
127 }
[805]128 ++outrowCount;
129 ++iter;
[144]130 }
[805]131 RowAccumulator acc(wtype);
[858]132 Vector<Bool> cmask(mask);
133 acc.setUserMask(cmask);
[805]134 ROTableRow row(tout);
135 ROArrayColumn<Float> specCol, tsysCol;
136 ROArrayColumn<uChar> flagCol;
137 ROScalarColumn<Double> mjdCol, intCol;
138 ROScalarColumn<Int> scanIDCol;
[144]139
[805]140 for (uInt i=0; i < tout.nrow(); ++i) {
[996]141 for ( int j=0; j < int(in.size()); ++j ) {
[977]142 const Table& tin = in[j]->table();
[805]143 const TableRecord& rec = row.get(i);
144 ROScalarColumn<Double> tmp(tin, "TIME");
145 Double td;tmp.get(0,td);
146 Table basesubt = tin(tin.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
147 && tin.col("IFNO") == Int(rec.asuInt("IFNO"))
148 && tin.col("POLNO") == Int(rec.asuInt("POLNO")) );
149 Table subt;
150 if ( avmode == "SOURCE") {
151 subt = basesubt( basesubt.col("SRCNAME") == rec.asString("SRCNAME") );
152 } else if (avmode == "SCAN") {
153 subt = basesubt( basesubt.col("SCANNO") == Int(rec.asuInt("SCANNO")) );
154 } else {
155 subt = basesubt;
156 }
157 specCol.attach(subt,"SPECTRA");
158 flagCol.attach(subt,"FLAGTRA");
159 tsysCol.attach(subt,"TSYS");
160 intCol.attach(subt,"INTERVAL");
161 mjdCol.attach(subt,"TIME");
162 Vector<Float> spec,tsys;
163 Vector<uChar> flag;
164 Double inter,time;
165 for (uInt k = 0; k < subt.nrow(); ++k ) {
166 flagCol.get(k, flag);
167 Vector<Bool> bflag(flag.shape());
168 convertArray(bflag, flag);
[1314]169 /*
[805]170 if ( allEQ(bflag, True) ) {
[1314]171 continue;//don't accumulate
[144]172 }
[1314]173 */
[805]174 specCol.get(k, spec);
175 tsysCol.get(k, tsys);
176 intCol.get(k, inter);
177 mjdCol.get(k, time);
178 // spectrum has to be added last to enable weighting by the other values
179 acc.add(spec, !bflag, tsys, inter, time);
180 }
181 }
182 //write out
183 specColOut.put(i, acc.getSpectrum());
184 const Vector<Bool>& msk = acc.getMask();
185 Vector<uChar> flg(msk.shape());
186 convertArray(flg, !msk);
187 flagColOut.put(i, flg);
188 tsysColOut.put(i, acc.getTsys());
189 intColOut.put(i, acc.getInterval());
190 mjdColOut.put(i, acc.getTime());
[1008]191 // we should only have one cycle now -> reset it to be 0
192 // frequency switched data has different CYCLENO for different IFNO
193 // which requires resetting this value
194 cycColOut.put(i, uInt(0));
[805]195 acc.reset();
[144]196 }
[805]197 return out;
[2]198}
[9]199
[1069]200CountedPtr< Scantable >
201 STMath::averageChannel( const CountedPtr < Scantable > & in,
[1078]202 const std::string & mode,
203 const std::string& avmode )
[1069]204{
205 // clone as this is non insitu
206 bool insitu = insitu_;
207 setInsitu(false);
208 CountedPtr< Scantable > out = getScantable(in, true);
209 setInsitu(insitu);
210 Table& tout = out->table();
211 ArrayColumn<Float> specColOut(tout,"SPECTRA");
212 ArrayColumn<uChar> flagColOut(tout,"FLAGTRA");
213 ArrayColumn<Float> tsysColOut(tout,"TSYS");
[1140]214 ScalarColumn<uInt> scanColOut(tout,"SCANNO");
[1232]215 ScalarColumn<Double> intColOut(tout, "INTERVAL");
[1140]216 Table tmp = in->table().sort("BEAMNO");
[1069]217 Block<String> cols(3);
218 cols[0] = String("BEAMNO");
219 cols[1] = String("IFNO");
220 cols[2] = String("POLNO");
[1078]221 if ( avmode == "SCAN") {
222 cols.resize(4);
223 cols[3] = String("SCANNO");
224 }
[1069]225 uInt outrowCount = 0;
226 uChar userflag = 1 << 7;
[1140]227 TableIterator iter(tmp, cols);
[1069]228 while (!iter.pastEnd()) {
229 Table subt = iter.table();
230 ROArrayColumn<Float> specCol, tsysCol;
231 ROArrayColumn<uChar> flagCol;
[1232]232 ROScalarColumn<Double> intCol(subt, "INTERVAL");
[1069]233 specCol.attach(subt,"SPECTRA");
234 flagCol.attach(subt,"FLAGTRA");
235 tsysCol.attach(subt,"TSYS");
236 tout.addRow();
237 TableCopy::copyRows(tout, subt, outrowCount, 0, 1);
[1140]238 if ( avmode != "SCAN") {
239 scanColOut.put(outrowCount, uInt(0));
240 }
[1069]241 Vector<Float> tmp;
242 specCol.get(0, tmp);
243 uInt nchan = tmp.nelements();
[1078]244 // have to do channel by channel here as MaskedArrMath
245 // doesn't have partialMedians
[1069]246 Vector<uChar> flags = flagCol.getColumn(Slicer(Slice(0)));
247 Vector<Float> outspec(nchan);
248 Vector<uChar> outflag(nchan,0);
249 Vector<Float> outtsys(1);/// @fixme when tsys is channel based
250 for (uInt i=0; i<nchan; ++i) {
251 Vector<Float> specs = specCol.getColumn(Slicer(Slice(i)));
252 MaskedArray<Float> ma = maskedArray(specs,flags);
253 outspec[i] = median(ma);
254 if ( allEQ(ma.getMask(), False) )
255 outflag[i] = userflag;// flag data
256 }
257 outtsys[0] = median(tsysCol.getColumn());
258 specColOut.put(outrowCount, outspec);
259 flagColOut.put(outrowCount, outflag);
260 tsysColOut.put(outrowCount, outtsys);
[1232]261 Double intsum = sum(intCol.getColumn());
262 intColOut.put(outrowCount, intsum);
[1069]263 ++outrowCount;
264 ++iter;
265 }
266 return out;
267}
268
[805]269CountedPtr< Scantable > STMath::getScantable(const CountedPtr< Scantable >& in,
270 bool droprows)
[185]271{
[805]272 if (insitu_) return in;
273 else {
274 // clone
275 Scantable* tabp = new Scantable(*in, Bool(droprows));
276 return CountedPtr<Scantable>(tabp);
[234]277 }
[805]278}
[234]279
[805]280CountedPtr< Scantable > STMath::unaryOperate( const CountedPtr< Scantable >& in,
281 float val,
282 const std::string& mode,
283 bool tsys )
284{
285 CountedPtr< Scantable > out = getScantable(in, false);
286 Table& tab = out->table();
287 ArrayColumn<Float> specCol(tab,"SPECTRA");
288 ArrayColumn<Float> tsysCol(tab,"TSYS");
289 for (uInt i=0; i<tab.nrow(); ++i) {
290 Vector<Float> spec;
291 Vector<Float> ts;
292 specCol.get(i, spec);
293 tsysCol.get(i, ts);
[1308]294 if (mode == "MUL" || mode == "DIV") {
295 if (mode == "DIV") val = 1.0/val;
[805]296 spec *= val;
297 specCol.put(i, spec);
298 if ( tsys ) {
299 ts *= val;
300 tsysCol.put(i, ts);
301 }
[1308]302 } else if ( mode == "ADD" || mode == "SUB") {
303 if (mode == "SUB") val *= -1.0;
[805]304 spec += val;
305 specCol.put(i, spec);
306 if ( tsys ) {
307 ts += val;
308 tsysCol.put(i, ts);
309 }
310 }
[234]311 }
[805]312 return out;
313}
[234]314
[1308]315CountedPtr<Scantable> STMath::binaryOperate(const CountedPtr<Scantable>& left,
316 const CountedPtr<Scantable>& right,
317 const std::string& mode)
318{
319 bool insitu = insitu_;
320 if ( ! left->conformant(*right) ) {
321 throw(AipsError("'left' and 'right' scantables are not conformant."));
322 }
323 setInsitu(false);
324 CountedPtr< Scantable > out = getScantable(left, false);
325 setInsitu(insitu);
326 Table& tout = out->table();
327 Block<String> coln(5);
328 coln[0] = "SCANNO"; coln[1] = "CYCLENO"; coln[2] = "BEAMNO";
329 coln[3] = "IFNO"; coln[4] = "POLNO";
330 Table tmpl = tout.sort(coln);
331 Table tmpr = right->table().sort(coln);
332 ArrayColumn<Float> lspecCol(tmpl,"SPECTRA");
333 ROArrayColumn<Float> rspecCol(tmpr,"SPECTRA");
334 ArrayColumn<uChar> lflagCol(tmpl,"FLAGTRA");
335 ROArrayColumn<uChar> rflagCol(tmpr,"FLAGTRA");
336
337 for (uInt i=0; i<tout.nrow(); ++i) {
338 Vector<Float> lspecvec, rspecvec;
339 Vector<uChar> lflagvec, rflagvec;
340 lspecvec = lspecCol(i); rspecvec = rspecCol(i);
341 lflagvec = lflagCol(i); rflagvec = rflagCol(i);
342 MaskedArray<Float> mleft = maskedArray(lspecvec, lflagvec);
343 MaskedArray<Float> mright = maskedArray(rspecvec, rflagvec);
344 if (mode == "ADD") {
345 mleft += mright;
346 } else if ( mode == "SUB") {
347 mleft -= mright;
348 } else if ( mode == "MUL") {
349 mleft *= mright;
350 } else if ( mode == "DIV") {
351 mleft /= mright;
352 } else {
353 throw(AipsError("Illegal binary operator"));
354 }
355 lspecCol.put(i, mleft.getArray());
356 }
357 return out;
358}
359
360
361
[805]362MaskedArray<Float> STMath::maskedArray( const Vector<Float>& s,
363 const Vector<uChar>& f)
364{
365 Vector<Bool> mask;
366 mask.resize(f.shape());
367 convertArray(mask, f);
368 return MaskedArray<Float>(s,!mask);
369}
[248]370
[805]371Vector<uChar> STMath::flagsFromMA(const MaskedArray<Float>& ma)
372{
373 const Vector<Bool>& m = ma.getMask();
374 Vector<uChar> flags(m.shape());
375 convertArray(flags, !m);
376 return flags;
377}
[234]378
[1066]379CountedPtr< Scantable > STMath::autoQuotient( const CountedPtr< Scantable >& in,
380 const std::string & mode,
381 bool preserve )
[805]382{
383 /// @todo make other modes available
384 /// modes should be "nearest", "pair"
385 // make this operation non insitu
386 const Table& tin = in->table();
387 Table ons = tin(tin.col("SRCTYPE") == Int(0));
388 Table offs = tin(tin.col("SRCTYPE") == Int(1));
389 if ( offs.nrow() == 0 )
390 throw(AipsError("No 'off' scans present."));
391 // put all "on" scans into output table
[701]392
[805]393 bool insitu = insitu_;
394 setInsitu(false);
395 CountedPtr< Scantable > out = getScantable(in, true);
396 setInsitu(insitu);
397 Table& tout = out->table();
[248]398
[805]399 TableCopy::copyRows(tout, ons);
400 TableRow row(tout);
401 ROScalarColumn<Double> offtimeCol(offs, "TIME");
402 ArrayColumn<Float> outspecCol(tout, "SPECTRA");
403 ROArrayColumn<Float> outtsysCol(tout, "TSYS");
404 ArrayColumn<uChar> outflagCol(tout, "FLAGTRA");
405 for (uInt i=0; i < tout.nrow(); ++i) {
406 const TableRecord& rec = row.get(i);
407 Double ontime = rec.asDouble("TIME");
408 ROScalarColumn<Double> offtimeCol(offs, "TIME");
409 Double mindeltat = min(abs(offtimeCol.getColumn() - ontime));
[1259]410 // Timestamp may vary within a cycle ???!!!
411 // increase this by 0.5 sec in case of rounding errors...
412 // There might be a better way to do this.
413 mindeltat += 0.5;
414 Table sel = offs( abs(offs.col("TIME")-ontime) <= (mindeltat+0.5)
[805]415 && offs.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
416 && offs.col("IFNO") == Int(rec.asuInt("IFNO"))
417 && offs.col("POLNO") == Int(rec.asuInt("POLNO")) );
[780]418
[1259]419 if ( sel.nrow() < 1 ) {
420 throw(AipsError("No closest in time found... This could be a rounding "
421 "issue. Try quotient instead."));
422 }
[805]423 TableRow offrow(sel);
424 const TableRecord& offrec = offrow.get(0);//should only be one row
425 RORecordFieldPtr< Array<Float> > specoff(offrec, "SPECTRA");
426 RORecordFieldPtr< Array<Float> > tsysoff(offrec, "TSYS");
427 RORecordFieldPtr< Array<uChar> > flagoff(offrec, "FLAGTRA");
428 /// @fixme this assumes tsys is a scalar not vector
429 Float tsysoffscalar = (*tsysoff)(IPosition(1,0));
430 Vector<Float> specon, tsyson;
431 outtsysCol.get(i, tsyson);
432 outspecCol.get(i, specon);
433 Vector<uChar> flagon;
434 outflagCol.get(i, flagon);
435 MaskedArray<Float> mon = maskedArray(specon, flagon);
436 MaskedArray<Float> moff = maskedArray(*specoff, *flagoff);
437 MaskedArray<Float> quot = (tsysoffscalar * mon / moff);
438 if (preserve) {
439 quot -= tsysoffscalar;
440 } else {
441 quot -= tsyson[0];
[701]442 }
[805]443 outspecCol.put(i, quot.getArray());
444 outflagCol.put(i, flagsFromMA(quot));
445 }
[926]446 // renumber scanno
447 TableIterator it(tout, "SCANNO");
448 uInt i = 0;
449 while ( !it.pastEnd() ) {
450 Table t = it.table();
451 TableVector<uInt> vec(t, "SCANNO");
452 vec = i;
453 ++i;
454 ++it;
455 }
[805]456 return out;
457}
[234]458
[1066]459
460CountedPtr< Scantable > STMath::quotient( const CountedPtr< Scantable > & on,
461 const CountedPtr< Scantable > & off,
462 bool preserve )
463{
464 bool insitu = insitu_;
[1069]465 if ( ! on->conformant(*off) ) {
466 throw(AipsError("'on' and 'off' scantables are not conformant."));
467 }
[1066]468 setInsitu(false);
469 CountedPtr< Scantable > out = getScantable(on, false);
470 setInsitu(insitu);
471 Table& tout = out->table();
472 const Table& toff = off->table();
473 TableIterator sit(tout, "SCANNO");
474 TableIterator s2it(toff, "SCANNO");
475 while ( !sit.pastEnd() ) {
476 Table ton = sit.table();
477 TableRow row(ton);
478 Table t = s2it.table();
479 ArrayColumn<Float> outspecCol(ton, "SPECTRA");
480 ROArrayColumn<Float> outtsysCol(ton, "TSYS");
481 ArrayColumn<uChar> outflagCol(ton, "FLAGTRA");
482 for (uInt i=0; i < ton.nrow(); ++i) {
483 const TableRecord& rec = row.get(i);
484 Table offsel = t( t.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
485 && t.col("IFNO") == Int(rec.asuInt("IFNO"))
486 && t.col("POLNO") == Int(rec.asuInt("POLNO")) );
[1145]487 if ( offsel.nrow() == 0 )
488 throw AipsError("STMath::quotient: no matching off");
[1066]489 TableRow offrow(offsel);
490 const TableRecord& offrec = offrow.get(0);//should be ncycles - take first
491 RORecordFieldPtr< Array<Float> > specoff(offrec, "SPECTRA");
492 RORecordFieldPtr< Array<Float> > tsysoff(offrec, "TSYS");
493 RORecordFieldPtr< Array<uChar> > flagoff(offrec, "FLAGTRA");
494 Float tsysoffscalar = (*tsysoff)(IPosition(1,0));
495 Vector<Float> specon, tsyson;
496 outtsysCol.get(i, tsyson);
497 outspecCol.get(i, specon);
498 Vector<uChar> flagon;
499 outflagCol.get(i, flagon);
500 MaskedArray<Float> mon = maskedArray(specon, flagon);
501 MaskedArray<Float> moff = maskedArray(*specoff, *flagoff);
502 MaskedArray<Float> quot = (tsysoffscalar * mon / moff);
503 if (preserve) {
504 quot -= tsysoffscalar;
505 } else {
506 quot -= tsyson[0];
507 }
508 outspecCol.put(i, quot.getArray());
509 outflagCol.put(i, flagsFromMA(quot));
510 }
511 ++sit;
512 ++s2it;
513 // take the first off for each on scan which doesn't have a
514 // matching off scan
515 // non <= noff: matching pairs, non > noff matching pairs then first off
516 if ( s2it.pastEnd() ) s2it.reset();
517 }
518 return out;
519}
520
521
[805]522CountedPtr< Scantable > STMath::freqSwitch( const CountedPtr< Scantable >& in )
523{
524 // make copy or reference
525 CountedPtr< Scantable > out = getScantable(in, false);
526 Table& tout = out->table();
[1008]527 Block<String> cols(4);
[805]528 cols[0] = String("SCANNO");
[1008]529 cols[1] = String("CYCLENO");
530 cols[2] = String("BEAMNO");
531 cols[3] = String("POLNO");
[805]532 TableIterator iter(tout, cols);
533 while (!iter.pastEnd()) {
534 Table subt = iter.table();
535 // this should leave us with two rows for the two IFs....if not ignore
536 if (subt.nrow() != 2 ) {
537 continue;
[701]538 }
[1008]539 ArrayColumn<Float> specCol(subt, "SPECTRA");
540 ArrayColumn<Float> tsysCol(subt, "TSYS");
541 ArrayColumn<uChar> flagCol(subt, "FLAGTRA");
[805]542 Vector<Float> onspec,offspec, ontsys, offtsys;
543 Vector<uChar> onflag, offflag;
544 tsysCol.get(0, ontsys); tsysCol.get(1, offtsys);
545 specCol.get(0, onspec); specCol.get(1, offspec);
546 flagCol.get(0, onflag); flagCol.get(1, offflag);
547 MaskedArray<Float> on = maskedArray(onspec, onflag);
548 MaskedArray<Float> off = maskedArray(offspec, offflag);
549 MaskedArray<Float> oncopy = on.copy();
[248]550
[805]551 on /= off; on -= 1.0f;
552 on *= ontsys[0];
553 off /= oncopy; off -= 1.0f;
554 off *= offtsys[0];
555 specCol.put(0, on.getArray());
556 const Vector<Bool>& m0 = on.getMask();
557 Vector<uChar> flags0(m0.shape());
558 convertArray(flags0, !m0);
559 flagCol.put(0, flags0);
[234]560
[805]561 specCol.put(1, off.getArray());
562 const Vector<Bool>& m1 = off.getMask();
563 Vector<uChar> flags1(m1.shape());
564 convertArray(flags1, !m1);
565 flagCol.put(1, flags1);
[867]566 ++iter;
[130]567 }
[780]568
[805]569 return out;
[9]570}
[48]571
[805]572std::vector< float > STMath::statistic( const CountedPtr< Scantable > & in,
573 const std::vector< bool > & mask,
574 const std::string& which )
[130]575{
576
[805]577 Vector<Bool> m(mask);
578 const Table& tab = in->table();
579 ROArrayColumn<Float> specCol(tab, "SPECTRA");
580 ROArrayColumn<uChar> flagCol(tab, "FLAGTRA");
581 std::vector<float> out;
582 for (uInt i=0; i < tab.nrow(); ++i ) {
583 Vector<Float> spec; specCol.get(i, spec);
[867]584 Vector<uChar> flag; flagCol.get(i, flag);
585 MaskedArray<Float> ma = maskedArray(spec, flag);
586 float outstat = 0.0;
[805]587 if ( spec.nelements() == m.nelements() ) {
588 outstat = mathutil::statistics(which, ma(m));
589 } else {
590 outstat = mathutil::statistics(which, ma);
591 }
592 out.push_back(outstat);
[234]593 }
[805]594 return out;
[130]595}
596
[805]597CountedPtr< Scantable > STMath::bin( const CountedPtr< Scantable > & in,
598 int width )
[144]599{
[841]600 if ( !in->getSelection().empty() ) throw(AipsError("Can't bin subset of the data."));
[805]601 CountedPtr< Scantable > out = getScantable(in, false);
602 Table& tout = out->table();
603 out->frequencies().rescale(width, "BIN");
604 ArrayColumn<Float> specCol(tout, "SPECTRA");
605 ArrayColumn<uChar> flagCol(tout, "FLAGTRA");
606 for (uInt i=0; i < tout.nrow(); ++i ) {
607 MaskedArray<Float> main = maskedArray(specCol(i), flagCol(i));
608 MaskedArray<Float> maout;
609 LatticeUtilities::bin(maout, main, 0, Int(width));
610 /// @todo implement channel based tsys binning
611 specCol.put(i, maout.getArray());
612 flagCol.put(i, flagsFromMA(maout));
613 // take only the first binned spectrum's length for the deprecated
614 // global header item nChan
615 if (i==0) tout.rwKeywordSet().define(String("nChan"),
616 Int(maout.getArray().nelements()));
[169]617 }
[805]618 return out;
[146]619}
620
[805]621CountedPtr< Scantable > STMath::resample( const CountedPtr< Scantable >& in,
622 const std::string& method,
623 float width )
[299]624//
625// Should add the possibility of width being specified in km/s. This means
[780]626// that for each freqID (SpectralCoordinate) we will need to convert to an
627// average channel width (say at the reference pixel). Then we would need
628// to be careful to make sure each spectrum (of different freqID)
[299]629// is the same length.
630//
631{
[996]632 //InterpolateArray1D<Double,Float>::InterpolationMethod interp;
[805]633 Int interpMethod(stringToIMethod(method));
[299]634
[805]635 CountedPtr< Scantable > out = getScantable(in, false);
636 Table& tout = out->table();
[299]637
638// Resample SpectralCoordinates (one per freqID)
[805]639 out->frequencies().rescale(width, "RESAMPLE");
640 TableIterator iter(tout, "IFNO");
641 TableRow row(tout);
642 while ( !iter.pastEnd() ) {
643 Table tab = iter.table();
644 ArrayColumn<Float> specCol(tab, "SPECTRA");
645 //ArrayColumn<Float> tsysCol(tout, "TSYS");
646 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
647 Vector<Float> spec;
648 Vector<uChar> flag;
649 specCol.get(0,spec); // the number of channels should be constant per IF
650 uInt nChanIn = spec.nelements();
651 Vector<Float> xIn(nChanIn); indgen(xIn);
652 Int fac = Int(nChanIn/width);
653 Vector<Float> xOut(fac+10); // 10 to be safe - resize later
654 uInt k = 0;
655 Float x = 0.0;
656 while (x < Float(nChanIn) ) {
657 xOut(k) = x;
658 k++;
659 x += width;
660 }
661 uInt nChanOut = k;
662 xOut.resize(nChanOut, True);
663 // process all rows for this IFNO
664 Vector<Float> specOut;
665 Vector<Bool> maskOut;
666 Vector<uChar> flagOut;
667 for (uInt i=0; i < tab.nrow(); ++i) {
668 specCol.get(i, spec);
669 flagCol.get(i, flag);
670 Vector<Bool> mask(flag.nelements());
671 convertArray(mask, flag);
[299]672
[805]673 IPosition shapeIn(spec.shape());
674 //sh.nchan = nChanOut;
675 InterpolateArray1D<Float,Float>::interpolate(specOut, maskOut, xOut,
676 xIn, spec, mask,
677 interpMethod, True, True);
678 /// @todo do the same for channel based Tsys
679 flagOut.resize(maskOut.nelements());
680 convertArray(flagOut, maskOut);
681 specCol.put(i, specOut);
682 flagCol.put(i, flagOut);
683 }
684 ++iter;
[299]685 }
686
[805]687 return out;
688}
[299]689
[805]690STMath::imethod STMath::stringToIMethod(const std::string& in)
691{
692 static STMath::imap lookup;
[299]693
[805]694 // initialize the lookup table if necessary
695 if ( lookup.empty() ) {
[926]696 lookup["nearest"] = InterpolateArray1D<Double,Float>::nearestNeighbour;
697 lookup["linear"] = InterpolateArray1D<Double,Float>::linear;
698 lookup["cubic"] = InterpolateArray1D<Double,Float>::cubic;
699 lookup["spline"] = InterpolateArray1D<Double,Float>::spline;
[299]700 }
701
[805]702 STMath::imap::const_iterator iter = lookup.find(in);
[299]703
[805]704 if ( lookup.end() == iter ) {
705 std::string message = in;
706 message += " is not a valid interpolation mode";
707 throw(AipsError(message));
[299]708 }
[805]709 return iter->second;
[299]710}
711
[805]712WeightType STMath::stringToWeight(const std::string& in)
[146]713{
[805]714 static std::map<std::string, WeightType> lookup;
[434]715
[805]716 // initialize the lookup table if necessary
717 if ( lookup.empty() ) {
718 lookup["NONE"] = asap::NONE;
719 lookup["TINT"] = asap::TINT;
720 lookup["TINTSYS"] = asap::TINTSYS;
721 lookup["TSYS"] = asap::TSYS;
722 lookup["VAR"] = asap::VAR;
723 }
[434]724
[805]725 std::map<std::string, WeightType>::const_iterator iter = lookup.find(in);
[294]726
[805]727 if ( lookup.end() == iter ) {
728 std::string message = in;
729 message += " is not a valid weighting mode";
730 throw(AipsError(message));
731 }
732 return iter->second;
[146]733}
734
[805]735CountedPtr< Scantable > STMath::gainElevation( const CountedPtr< Scantable >& in,
[867]736 const vector< float > & coeff,
[805]737 const std::string & filename,
738 const std::string& method)
[165]739{
[805]740 // Get elevation data from Scantable and convert to degrees
741 CountedPtr< Scantable > out = getScantable(in, false);
[926]742 Table& tab = out->table();
[805]743 ROScalarColumn<Float> elev(tab, "ELEVATION");
744 Vector<Float> x = elev.getColumn();
745 x *= Float(180 / C::pi); // Degrees
[165]746
[867]747 Vector<Float> coeffs(coeff);
[805]748 const uInt nc = coeffs.nelements();
749 if ( filename.length() > 0 && nc > 0 ) {
750 throw(AipsError("You must choose either polynomial coefficients or an ascii file, not both"));
[315]751 }
[165]752
[805]753 // Correct
754 if ( nc > 0 || filename.length() == 0 ) {
755 // Find instrument
756 Bool throwit = True;
757 Instrument inst =
[878]758 STAttr::convertInstrument(tab.keywordSet().asString("AntennaName"),
[805]759 throwit);
[165]760
[805]761 // Set polynomial
762 Polynomial<Float>* ppoly = 0;
763 Vector<Float> coeff;
764 String msg;
765 if ( nc > 0 ) {
766 ppoly = new Polynomial<Float>(nc);
767 coeff = coeffs;
768 msg = String("user");
769 } else {
[878]770 STAttr sdAttr;
[805]771 coeff = sdAttr.gainElevationPoly(inst);
772 ppoly = new Polynomial<Float>(3);
773 msg = String("built in");
774 }
[532]775
[805]776 if ( coeff.nelements() > 0 ) {
777 ppoly->setCoefficients(coeff);
778 } else {
779 delete ppoly;
780 throw(AipsError("There is no known gain-elevation polynomial known for this instrument"));
781 }
782 ostringstream oss;
783 oss << "Making polynomial correction with " << msg << " coefficients:" << endl;
784 oss << " " << coeff;
785 pushLog(String(oss));
786 const uInt nrow = tab.nrow();
787 Vector<Float> factor(nrow);
788 for ( uInt i=0; i < nrow; ++i ) {
789 factor[i] = 1.0 / (*ppoly)(x[i]);
790 }
791 delete ppoly;
792 scaleByVector(tab, factor, true);
[532]793
[805]794 } else {
795 // Read and correct
796 pushLog("Making correction from ascii Table");
797 scaleFromAsciiTable(tab, filename, method, x, true);
[532]798 }
[805]799 return out;
800}
[165]801
[805]802void STMath::scaleFromAsciiTable(Table& in, const std::string& filename,
803 const std::string& method,
804 const Vector<Float>& xout, bool dotsys)
805{
[165]806
[805]807// Read gain-elevation ascii file data into a Table.
[165]808
[805]809 String formatString;
810 Table tbl = readAsciiTable(formatString, Table::Memory, filename, "", "", False);
811 scaleFromTable(in, tbl, method, xout, dotsys);
812}
[165]813
[805]814void STMath::scaleFromTable(Table& in,
815 const Table& table,
816 const std::string& method,
817 const Vector<Float>& xout, bool dotsys)
818{
[780]819
[805]820 ROScalarColumn<Float> geElCol(table, "ELEVATION");
821 ROScalarColumn<Float> geFacCol(table, "FACTOR");
822 Vector<Float> xin = geElCol.getColumn();
823 Vector<Float> yin = geFacCol.getColumn();
824 Vector<Bool> maskin(xin.nelements(),True);
[165]825
[805]826 // Interpolate (and extrapolate) with desired method
[532]827
[996]828 InterpolateArray1D<Double,Float>::InterpolationMethod interp = stringToIMethod(method);
[165]829
[805]830 Vector<Float> yout;
831 Vector<Bool> maskout;
832 InterpolateArray1D<Float,Float>::interpolate(yout, maskout, xout,
[996]833 xin, yin, maskin, interp,
[805]834 True, True);
[165]835
[805]836 scaleByVector(in, Float(1.0)/yout, dotsys);
[165]837}
[167]838
[805]839void STMath::scaleByVector( Table& in,
840 const Vector< Float >& factor,
841 bool dotsys )
[177]842{
[805]843 uInt nrow = in.nrow();
844 if ( factor.nelements() != nrow ) {
845 throw(AipsError("factors.nelements() != table.nelements()"));
846 }
847 ArrayColumn<Float> specCol(in, "SPECTRA");
848 ArrayColumn<uChar> flagCol(in, "FLAGTRA");
849 ArrayColumn<Float> tsysCol(in, "TSYS");
850 for (uInt i=0; i < nrow; ++i) {
851 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
852 ma *= factor[i];
853 specCol.put(i, ma.getArray());
854 flagCol.put(i, flagsFromMA(ma));
855 if ( dotsys ) {
[926]856 Vector<Float> tsys = tsysCol(i);
[805]857 tsys *= factor[i];
[926]858 tsysCol.put(i,tsys);
[805]859 }
860 }
[177]861}
862
[805]863CountedPtr< Scantable > STMath::convertFlux( const CountedPtr< Scantable >& in,
864 float d, float etaap,
865 float jyperk )
[221]866{
[805]867 CountedPtr< Scantable > out = getScantable(in, false);
868 Table& tab = in->table();
869 Unit fluxUnit(tab.keywordSet().asString("FluxUnit"));
[221]870 Unit K(String("K"));
871 Unit JY(String("Jy"));
[701]872
[805]873 bool tokelvin = true;
874 Double cfac = 1.0;
[716]875
[805]876 if ( fluxUnit == JY ) {
[716]877 pushLog("Converting to K");
[701]878 Quantum<Double> t(1.0,fluxUnit);
879 Quantum<Double> t2 = t.get(JY);
[805]880 cfac = (t2 / t).getValue(); // value to Jy
[780]881
[805]882 tokelvin = true;
883 out->setFluxUnit("K");
884 } else if ( fluxUnit == K ) {
[716]885 pushLog("Converting to Jy");
[701]886 Quantum<Double> t(1.0,fluxUnit);
887 Quantum<Double> t2 = t.get(K);
[805]888 cfac = (t2 / t).getValue(); // value to K
[780]889
[805]890 tokelvin = false;
891 out->setFluxUnit("Jy");
[221]892 } else {
[701]893 throw(AipsError("Unrecognized brightness units in Table - must be consistent with Jy or K"));
[221]894 }
[701]895 // Make sure input values are converted to either Jy or K first...
[805]896 Float factor = cfac;
[221]897
[701]898 // Select method
[805]899 if (jyperk > 0.0) {
900 factor *= jyperk;
901 if ( tokelvin ) factor = 1.0 / jyperk;
[716]902 ostringstream oss;
[805]903 oss << "Jy/K = " << jyperk;
[716]904 pushLog(String(oss));
[805]905 Vector<Float> factors(tab.nrow(), factor);
906 scaleByVector(tab,factors, false);
907 } else if ( etaap > 0.0) {
908 Instrument inst =
[878]909 STAttr::convertInstrument(tab.keywordSet().asString("AntennaName"), True);
910 STAttr sda;
[805]911 if (d < 0) d = sda.diameter(inst);
[996]912 jyperk = STAttr::findJyPerK(etaap, d);
[716]913 ostringstream oss;
[805]914 oss << "Jy/K = " << jyperk;
[716]915 pushLog(String(oss));
[805]916 factor *= jyperk;
917 if ( tokelvin ) {
[701]918 factor = 1.0 / factor;
919 }
[805]920 Vector<Float> factors(tab.nrow(), factor);
921 scaleByVector(tab, factors, False);
[354]922 } else {
[780]923
[701]924 // OK now we must deal with automatic look up of values.
925 // We must also deal with the fact that the factors need
926 // to be computed per IF and may be different and may
927 // change per integration.
[780]928
[716]929 pushLog("Looking up conversion factors");
[805]930 convertBrightnessUnits(out, tokelvin, cfac);
[701]931 }
[805]932
933 return out;
[221]934}
935
[805]936void STMath::convertBrightnessUnits( CountedPtr<Scantable>& in,
937 bool tokelvin, float cfac )
[227]938{
[805]939 Table& table = in->table();
940 Instrument inst =
[878]941 STAttr::convertInstrument(table.keywordSet().asString("AntennaName"), True);
[805]942 TableIterator iter(table, "FREQ_ID");
943 STFrequencies stfreqs = in->frequencies();
[878]944 STAttr sdAtt;
[805]945 while (!iter.pastEnd()) {
946 Table tab = iter.table();
947 ArrayColumn<Float> specCol(tab, "SPECTRA");
948 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
949 ROScalarColumn<uInt> freqidCol(tab, "FREQ_ID");
950 MEpoch::ROScalarColumn timeCol(tab, "TIME");
[234]951
[805]952 uInt freqid; freqidCol.get(0, freqid);
953 Vector<Float> tmpspec; specCol.get(0, tmpspec);
[878]954 // STAttr.JyPerK has a Vector interface... change sometime.
[805]955 Vector<Float> freqs(1,stfreqs.getRefFreq(freqid, tmpspec.nelements()));
956 for ( uInt i=0; i<tab.nrow(); ++i) {
957 Float jyperk = (sdAtt.JyPerK(inst, timeCol(i), freqs))[0];
958 Float factor = cfac * jyperk;
959 if ( tokelvin ) factor = Float(1.0) / factor;
960 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
961 ma *= factor;
962 specCol.put(i, ma.getArray());
963 flagCol.put(i, flagsFromMA(ma));
964 }
[867]965 ++iter;
[234]966 }
[230]967}
[227]968
[805]969CountedPtr< Scantable > STMath::opacity( const CountedPtr< Scantable > & in,
970 float tau )
[234]971{
[805]972 CountedPtr< Scantable > out = getScantable(in, false);
[926]973
974 Table tab = out->table();
[234]975 ROScalarColumn<Float> elev(tab, "ELEVATION");
[805]976 ArrayColumn<Float> specCol(tab, "SPECTRA");
977 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
978 for ( uInt i=0; i<tab.nrow(); ++i) {
979 Float zdist = Float(C::pi_2) - elev(i);
980 Float factor = exp(tau)/cos(zdist);
[926]981 MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
[805]982 ma *= factor;
983 specCol.put(i, ma.getArray());
984 flagCol.put(i, flagsFromMA(ma));
[234]985 }
[805]986 return out;
[234]987}
988
[805]989CountedPtr< Scantable > STMath::smooth( const CountedPtr< Scantable >& in,
990 const std::string& kernel, float width )
[457]991{
[805]992 CountedPtr< Scantable > out = getScantable(in, false);
[1033]993 Table& table = out->table();
[805]994 VectorKernel::KernelTypes type = VectorKernel::toKernelType(kernel);
995 // same IFNO should have same no of channels
996 // this saves overhead
997 TableIterator iter(table, "IFNO");
998 while (!iter.pastEnd()) {
999 Table tab = iter.table();
1000 ArrayColumn<Float> specCol(tab, "SPECTRA");
1001 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1002 Vector<Float> tmpspec; specCol.get(0, tmpspec);
1003 uInt nchan = tmpspec.nelements();
1004 Vector<Float> kvec = VectorKernel::make(type, width, nchan, True, False);
1005 Convolver<Float> conv(kvec, IPosition(1,nchan));
1006 Vector<Float> spec;
1007 Vector<uChar> flag;
1008 for ( uInt i=0; i<tab.nrow(); ++i) {
1009 specCol.get(i, spec);
1010 flagCol.get(i, flag);
1011 Vector<Bool> mask(flag.nelements());
1012 convertArray(mask, flag);
1013 Vector<Float> specout;
1014 if ( type == VectorKernel::HANNING ) {
1015 Vector<Bool> maskout;
[1033]1016 mathutil::hanning(specout, maskout, spec , !mask);
1017 convertArray(flag, !maskout);
[805]1018 flagCol.put(i, flag);
[1033]1019 specCol.put(i, specout);
1020 } else {
[805]1021 mathutil::replaceMaskByZero(specout, mask);
1022 conv.linearConv(specout, spec);
[1033]1023 specCol.put(i, specout);
[354]1024 }
[805]1025 }
[867]1026 ++iter;
[701]1027 }
[805]1028 return out;
[701]1029}
[841]1030
1031CountedPtr< Scantable >
1032 STMath::merge( const std::vector< CountedPtr < Scantable > >& in )
1033{
1034 if ( in.size() < 2 ) {
[862]1035 throw(AipsError("Need at least two scantables to perform a merge."));
[841]1036 }
1037 std::vector<CountedPtr < Scantable > >::const_iterator it = in.begin();
1038 bool insitu = insitu_;
1039 setInsitu(false);
[862]1040 CountedPtr< Scantable > out = getScantable(*it, false);
[841]1041 setInsitu(insitu);
1042 Table& tout = out->table();
1043 ScalarColumn<uInt> freqidcol(tout,"FREQ_ID"), molidcol(tout, "MOLECULE_ID");
[917]1044 ScalarColumn<uInt> scannocol(tout,"SCANNO"), focusidcol(tout,"FOCUS_ID");
1045 // Renumber SCANNO to be 0-based
[926]1046 Vector<uInt> scannos = scannocol.getColumn();
1047 uInt offset = min(scannos);
[917]1048 scannos -= offset;
[926]1049 scannocol.putColumn(scannos);
1050 uInt newscanno = max(scannos)+1;
[862]1051 ++it;
[841]1052 while ( it != in.end() ){
1053 if ( ! (*it)->conformant(*out) ) {
1054 // log message: "ignoring scantable i, as it isn't
1055 // conformant with the other(s)"
1056 cerr << "oh oh" << endl;
1057 ++it;
1058 continue;
1059 }
[862]1060 out->appendToHistoryTable((*it)->history());
[841]1061 const Table& tab = (*it)->table();
1062 TableIterator scanit(tab, "SCANNO");
1063 while (!scanit.pastEnd()) {
1064 TableIterator freqit(scanit.table(), "FREQ_ID");
1065 while ( !freqit.pastEnd() ) {
1066 Table thetab = freqit.table();
1067 uInt nrow = tout.nrow();
1068 //tout.addRow(thetab.nrow());
1069 TableCopy::copyRows(tout, thetab, nrow, 0, thetab.nrow());
1070 ROTableRow row(thetab);
1071 for ( uInt i=0; i<thetab.nrow(); ++i) {
1072 uInt k = nrow+i;
1073 scannocol.put(k, newscanno);
1074 const TableRecord& rec = row.get(i);
1075 Double rv,rp,inc;
1076 (*it)->frequencies().getEntry(rp, rv, inc, rec.asuInt("FREQ_ID"));
1077 uInt id;
1078 id = out->frequencies().addEntry(rp, rv, inc);
1079 freqidcol.put(k,id);
1080 String name,fname;Double rf;
1081 (*it)->molecules().getEntry(rf, name, fname, rec.asuInt("MOLECULE_ID"));
1082 id = out->molecules().addEntry(rf, name, fname);
1083 molidcol.put(k, id);
[961]1084 Float frot,fax,ftan,fhand,fmount,fuser, fxy, fxyp;
1085 (*it)->focus().getEntry(fax, ftan, frot, fhand,
1086 fmount,fuser, fxy, fxyp,
1087 rec.asuInt("FOCUS_ID"));
1088 id = out->focus().addEntry(fax, ftan, frot, fhand,
1089 fmount,fuser, fxy, fxyp);
[841]1090 focusidcol.put(k, id);
1091 }
1092 ++freqit;
1093 }
1094 ++newscanno;
1095 ++scanit;
1096 }
1097 ++it;
1098 }
1099 return out;
1100}
[896]1101
1102CountedPtr< Scantable >
1103 STMath::invertPhase( const CountedPtr < Scantable >& in )
1104{
[996]1105 return applyToPol(in, &STPol::invertPhase, Float(0.0));
[896]1106}
1107
1108CountedPtr< Scantable >
1109 STMath::rotateXYPhase( const CountedPtr < Scantable >& in, float phase )
1110{
1111 return applyToPol(in, &STPol::rotatePhase, Float(phase));
1112}
1113
1114CountedPtr< Scantable >
1115 STMath::rotateLinPolPhase( const CountedPtr < Scantable >& in, float phase )
1116{
1117 return applyToPol(in, &STPol::rotateLinPolPhase, Float(phase));
1118}
1119
1120CountedPtr< Scantable > STMath::applyToPol( const CountedPtr<Scantable>& in,
1121 STPol::polOperation fptr,
1122 Float phase )
1123{
1124 CountedPtr< Scantable > out = getScantable(in, false);
1125 Table& tout = out->table();
1126 Block<String> cols(4);
1127 cols[0] = String("SCANNO");
1128 cols[1] = String("BEAMNO");
1129 cols[2] = String("IFNO");
1130 cols[3] = String("CYCLENO");
1131 TableIterator iter(tout, cols);
[1015]1132 STPol* stpol = STPol::getPolClass(out->factories_, out->getPolType() );
[896]1133 while (!iter.pastEnd()) {
1134 Table t = iter.table();
1135 ArrayColumn<Float> speccol(t, "SPECTRA");
[1015]1136 ScalarColumn<uInt> focidcol(t, "FOCUS_ID");
1137 ScalarColumn<Float> parancol(t, "PARANGLE");
[896]1138 Matrix<Float> pols = speccol.getColumn();
1139 try {
1140 stpol->setSpectra(pols);
[1015]1141 Float fang,fhand,parang;
1142 fang = in->focusTable_.getTotalFeedAngle(focidcol(0));
1143 fhand = in->focusTable_.getFeedHand(focidcol(0));
1144 parang = parancol(0);
1145 /// @todo re-enable this
1146 // disable total feed angle to support paralactifying Caswell style
1147 stpol->setPhaseCorrections(parang, -parang, fhand);
[896]1148 (stpol->*fptr)(phase);
1149 speccol.putColumn(stpol->getSpectra());
[1015]1150 Matrix<Float> tmp = stpol->getSpectra();
[896]1151 } catch (AipsError& e) {
1152 delete stpol;stpol=0;
1153 throw(e);
1154 }
1155 ++iter;
1156 }
[934]1157 delete stpol;stpol=0;
[896]1158 return out;
1159}
1160
1161CountedPtr< Scantable >
1162 STMath::swapPolarisations( const CountedPtr< Scantable > & in )
1163{
1164 CountedPtr< Scantable > out = getScantable(in, false);
1165 Table& tout = out->table();
1166 Table t0 = tout(tout.col("POLNO") == 0);
1167 Table t1 = tout(tout.col("POLNO") == 1);
1168 if ( t0.nrow() != t1.nrow() )
1169 throw(AipsError("Inconsistent number of polarisations"));
1170 ArrayColumn<Float> speccol0(t0, "SPECTRA");
1171 ArrayColumn<uChar> flagcol0(t0, "FLAGTRA");
1172 ArrayColumn<Float> speccol1(t1, "SPECTRA");
1173 ArrayColumn<uChar> flagcol1(t1, "FLAGTRA");
1174 Matrix<Float> s0 = speccol0.getColumn();
1175 Matrix<uChar> f0 = flagcol0.getColumn();
1176 speccol0.putColumn(speccol1.getColumn());
1177 flagcol0.putColumn(flagcol1.getColumn());
1178 speccol1.putColumn(s0);
1179 flagcol1.putColumn(f0);
1180 return out;
1181}
[917]1182
1183CountedPtr< Scantable >
[940]1184 STMath::averagePolarisations( const CountedPtr< Scantable > & in,
1185 const std::vector<bool>& mask,
1186 const std::string& weight )
1187{
[1232]1188 if (in->npol() < 2 )
1189 throw(AipsError("averagePolarisations can only be applied to two or more"
1190 "polarisations"));
[1010]1191 bool insitu = insitu_;
1192 setInsitu(false);
[1232]1193 CountedPtr< Scantable > pols = getScantable(in, true);
[1010]1194 setInsitu(insitu);
1195 Table& tout = pols->table();
[1232]1196 std::string taql = "SELECT FROM $1 WHERE POLNO IN [0,1]";
1197 Table tab = tableCommand(taql, in->table());
1198 if (tab.nrow() == 0 )
1199 throw(AipsError("Could not find any rows with POLNO==0 and POLNO==1"));
1200 TableCopy::copyRows(tout, tab);
[1145]1201 TableVector<uInt> vec(tout, "POLNO");
[940]1202 vec = 0;
[1145]1203 pols->table_.rwKeywordSet().define("nPol", Int(1));
[1232]1204 pols->table_.rwKeywordSet().define("POLTYPE", String("stokes"));
[1010]1205 std::vector<CountedPtr<Scantable> > vpols;
1206 vpols.push_back(pols);
[1232]1207 CountedPtr< Scantable > out = average(vpols, mask, weight, "SCAN");
[940]1208 return out;
1209}
1210
[1145]1211CountedPtr< Scantable >
1212 STMath::averageBeams( const CountedPtr< Scantable > & in,
1213 const std::vector<bool>& mask,
1214 const std::string& weight )
1215{
1216 bool insitu = insitu_;
1217 setInsitu(false);
1218 CountedPtr< Scantable > beams = getScantable(in, false);
1219 setInsitu(insitu);
1220 Table& tout = beams->table();
1221 // give all rows the same BEAMNO
1222 TableVector<uInt> vec(tout, "BEAMNO");
1223 vec = 0;
1224 beams->table_.rwKeywordSet().define("nBeam", Int(1));
1225 std::vector<CountedPtr<Scantable> > vbeams;
1226 vbeams.push_back(beams);
[1232]1227 CountedPtr< Scantable > out = average(vbeams, mask, weight, "SCAN");
[1145]1228 return out;
1229}
[940]1230
[1145]1231
[940]1232CountedPtr< Scantable >
[917]1233 asap::STMath::frequencyAlign( const CountedPtr< Scantable > & in,
1234 const std::string & refTime,
[926]1235 const std::string & method)
[917]1236{
[940]1237 // clone as this is not working insitu
1238 bool insitu = insitu_;
1239 setInsitu(false);
[917]1240 CountedPtr< Scantable > out = getScantable(in, false);
[940]1241 setInsitu(insitu);
[917]1242 Table& tout = out->table();
1243 // Get reference Epoch to time of first row or given String
1244 Unit DAY(String("d"));
1245 MEpoch::Ref epochRef(in->getTimeReference());
1246 MEpoch refEpoch;
1247 if (refTime.length()>0) {
1248 Quantum<Double> qt;
1249 if (MVTime::read(qt,refTime)) {
1250 MVEpoch mv(qt);
1251 refEpoch = MEpoch(mv, epochRef);
1252 } else {
1253 throw(AipsError("Invalid format for Epoch string"));
1254 }
1255 } else {
1256 refEpoch = in->timeCol_(0);
1257 }
1258 MPosition refPos = in->getAntennaPosition();
[940]1259
[996]1260 InterpolateArray1D<Double,Float>::InterpolationMethod interp = stringToIMethod(method);
[917]1261 // test if user frame is different to base frame
1262 if ( in->frequencies().getFrameString(true)
1263 == in->frequencies().getFrameString(false) ) {
[985]1264 throw(AipsError("Can't convert as no output frame has been set"
1265 " (use set_freqframe) or it is aligned already."));
[917]1266 }
1267 MFrequency::Types system = in->frequencies().getFrame();
[940]1268 MVTime mvt(refEpoch.getValue());
1269 String epochout = mvt.string(MVTime::YMD) + String(" (") + refEpoch.getRefString() + String(")");
1270 ostringstream oss;
1271 oss << "Aligned at reference Epoch " << epochout
1272 << " in frame " << MFrequency::showType(system);
1273 pushLog(String(oss));
[917]1274 // set up the iterator
[926]1275 Block<String> cols(4);
1276 // select by constant direction
[917]1277 cols[0] = String("SRCNAME");
1278 cols[1] = String("BEAMNO");
1279 // select by IF ( no of channels varies over this )
1280 cols[2] = String("IFNO");
[926]1281 // select by restfrequency
1282 cols[3] = String("MOLECULE_ID");
[917]1283 TableIterator iter(tout, cols);
[926]1284 while ( !iter.pastEnd() ) {
[917]1285 Table t = iter.table();
1286 MDirection::ROScalarColumn dirCol(t, "DIRECTION");
[926]1287 TableIterator fiter(t, "FREQ_ID");
[917]1288 // determine nchan from the first row. This should work as
[926]1289 // we are iterating over BEAMNO and IFNO // we should have constant direction
1290
[917]1291 ROArrayColumn<Float> sCol(t, "SPECTRA");
[926]1292 MDirection direction = dirCol(0);
[917]1293 uInt nchan = sCol(0).nelements();
[926]1294 while ( !fiter.pastEnd() ) {
1295 Table ftab = fiter.table();
1296 ScalarColumn<uInt> freqidCol(ftab, "FREQ_ID");
1297 // get the SpectralCoordinate for the freqid, which we are iterating over
1298 SpectralCoordinate sC = in->frequencies().getSpectralCoordinate(freqidCol(0));
1299 FrequencyAligner<Float> fa( sC, nchan, refEpoch,
1300 direction, refPos, system );
1301 // realign the SpectralCoordinate and put into the output Scantable
1302 Vector<String> units(1);
1303 units = String("Hz");
1304 Bool linear=True;
1305 SpectralCoordinate sc2 = fa.alignedSpectralCoordinate(linear);
1306 sc2.setWorldAxisUnits(units);
[934]1307 uInt id = out->frequencies().addEntry(sc2.referencePixel()[0],
1308 sc2.referenceValue()[0],
1309 sc2.increment()[0]);
1310 TableVector<uInt> tvec(ftab, "FREQ_ID");
1311 tvec = id;
[926]1312 // create the "global" abcissa for alignment with same FREQ_ID
1313 Vector<Double> abc(nchan);
[917]1314 Double w;
1315 for (uInt i=0; i<nchan; i++) {
1316 sC.toWorld(w,Double(i));
1317 abc[i] = w;
1318 }
[926]1319 // cache abcissa for same time stamps, so iterate over those
1320 TableIterator timeiter(ftab, "TIME");
1321 while ( !timeiter.pastEnd() ) {
1322 Table tab = timeiter.table();
1323 ArrayColumn<Float> specCol(tab, "SPECTRA");
1324 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1325 MEpoch::ROScalarColumn timeCol(tab, "TIME");
1326 // use align abcissa cache after the first row
1327 bool first = true;
1328 // these rows should be just be POLNO
[996]1329 for (int i=0; i<int(tab.nrow()); ++i) {
[926]1330 // input values
1331 Vector<uChar> flag = flagCol(i);
1332 Vector<Bool> mask(flag.shape());
1333 Vector<Float> specOut, spec;
1334 spec = specCol(i);
1335 Vector<Bool> maskOut;Vector<uChar> flagOut;
1336 convertArray(mask, flag);
1337 // alignment
1338 Bool ok = fa.align(specOut, maskOut, abc, spec,
1339 mask, timeCol(i), !first,
1340 interp, False);
1341 // back into scantable
1342 flagOut.resize(maskOut.nelements());
1343 convertArray(flagOut, maskOut);
1344 flagCol.put(i, flagOut);
1345 specCol.put(i, specOut);
1346 // start abcissa caching
1347 first = false;
[917]1348 }
[926]1349 // next timestamp
1350 ++timeiter;
[917]1351 }
[940]1352 // next FREQ_ID
[926]1353 ++fiter;
[917]1354 }
1355 // next aligner
1356 ++iter;
1357 }
[940]1358 // set this afterwards to ensure we are doing insitu correctly.
1359 out->frequencies().setFrame(system, true);
[917]1360 return out;
1361}
[992]1362
1363CountedPtr<Scantable>
1364 asap::STMath::convertPolarisation( const CountedPtr<Scantable>& in,
1365 const std::string & newtype )
1366{
1367 if (in->npol() != 2 && in->npol() != 4)
1368 throw(AipsError("Can only convert two or four polarisations."));
1369 if ( in->getPolType() == newtype )
1370 throw(AipsError("No need to convert."));
[1000]1371 if ( ! in->selector_.empty() )
1372 throw(AipsError("Can only convert whole scantable. Unset the selection."));
[992]1373 bool insitu = insitu_;
1374 setInsitu(false);
1375 CountedPtr< Scantable > out = getScantable(in, true);
1376 setInsitu(insitu);
1377 Table& tout = out->table();
1378 tout.rwKeywordSet().define("POLTYPE", String(newtype));
1379
1380 Block<String> cols(4);
1381 cols[0] = "SCANNO";
1382 cols[1] = "CYCLENO";
1383 cols[2] = "BEAMNO";
1384 cols[3] = "IFNO";
1385 TableIterator it(in->originalTable_, cols);
1386 String basetype = in->getPolType();
1387 STPol* stpol = STPol::getPolClass(in->factories_, basetype);
1388 try {
1389 while ( !it.pastEnd() ) {
1390 Table tab = it.table();
1391 uInt row = tab.rowNumbers()[0];
1392 stpol->setSpectra(in->getPolMatrix(row));
1393 Float fang,fhand,parang;
1394 fang = in->focusTable_.getTotalFeedAngle(in->mfocusidCol_(row));
1395 fhand = in->focusTable_.getFeedHand(in->mfocusidCol_(row));
1396 parang = in->paraCol_(row);
1397 /// @todo re-enable this
1398 // disable total feed angle to support paralactifying Caswell style
1399 stpol->setPhaseCorrections(parang, -parang, fhand);
1400 Int npolout = 0;
1401 for (uInt i=0; i<tab.nrow(); ++i) {
1402 Vector<Float> outvec = stpol->getSpectrum(i, newtype);
1403 if ( outvec.nelements() > 0 ) {
1404 tout.addRow();
1405 TableCopy::copyRows(tout, tab, tout.nrow()-1, 0, 1);
1406 ArrayColumn<Float> sCol(tout,"SPECTRA");
1407 ScalarColumn<uInt> pCol(tout,"POLNO");
1408 sCol.put(tout.nrow()-1 ,outvec);
1409 pCol.put(tout.nrow()-1 ,uInt(npolout));
1410 npolout++;
1411 }
1412 }
1413 tout.rwKeywordSet().define("nPol", npolout);
1414 ++it;
1415 }
1416 } catch (AipsError& e) {
1417 delete stpol;
1418 throw(e);
1419 }
1420 delete stpol;
1421 return out;
1422}
[1066]1423
[1143]1424CountedPtr< Scantable >
[1140]1425 asap::STMath::mxExtract( const CountedPtr< Scantable > & in,
1426 const std::string & scantype )
1427{
1428 bool insitu = insitu_;
1429 setInsitu(false);
1430 CountedPtr< Scantable > out = getScantable(in, true);
1431 setInsitu(insitu);
1432 Table& tout = out->table();
1433 std::string taql = "SELECT FROM $1 WHERE BEAMNO != REFBEAMNO";
1434 if (scantype == "on") {
1435 taql = "SELECT FROM $1 WHERE BEAMNO == REFBEAMNO";
1436 }
1437 Table tab = tableCommand(taql, in->table());
1438 TableCopy::copyRows(tout, tab);
1439 if (scantype == "on") {
[1143]1440 // re-index SCANNO to 0
[1140]1441 TableVector<uInt> vec(tout, "SCANNO");
1442 vec = 0;
1443 }
1444 return out;
1445}
[1192]1446
1447CountedPtr< Scantable >
1448 asap::STMath::lagFlag( const CountedPtr< Scantable > & in,
[1200]1449 double frequency, double width )
[1192]1450{
1451 CountedPtr< Scantable > out = getScantable(in, false);
1452 Table& tout = out->table();
1453 TableIterator iter(tout, "FREQ_ID");
1454 FFTServer<Float,Complex> ffts;
1455 while ( !iter.pastEnd() ) {
1456 Table tab = iter.table();
1457 Double rp,rv,inc;
1458 ROTableRow row(tab);
1459 const TableRecord& rec = row.get(0);
1460 uInt freqid = rec.asuInt("FREQ_ID");
1461 out->frequencies().getEntry(rp, rv, inc, freqid);
1462 ArrayColumn<Float> specCol(tab, "SPECTRA");
1463 ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
1464 for (int i=0; i<int(tab.nrow()); ++i) {
1465 Vector<Float> spec = specCol(i);
1466 Vector<uChar> flag = flagCol(i);
[1200]1467 Int lag0 = Int(spec.nelements()*abs(inc)/(frequency+width)+0.5);
1468 Int lag1 = Int(spec.nelements()*abs(inc)/(frequency-width)+0.5);
[1192]1469 for (int k=0; k < flag.nelements(); ++k ) {
1470 if (flag[k] > 0) {
1471 spec[k] = 0.0;
1472 }
1473 }
1474 Vector<Complex> lags;
[1203]1475 ffts.fft0(lags, spec);
[1200]1476 Int start = max(0, lag0);
1477 Int end = min(Int(lags.nelements()-1), lag1);
[1192]1478 if (start == end) {
1479 lags[start] = Complex(0.0);
1480 } else {
1481 for (int j=start; j <=end ;++j) {
1482 lags[j] = Complex(0.0);
1483 }
1484 }
[1203]1485 ffts.fft0(spec, lags);
[1192]1486 specCol.put(i, spec);
1487 }
1488 ++iter;
1489 }
1490 return out;
1491}
Note: See TracBrowser for help on using the repository browser.