source: trunk/src/Scantable.cpp@ 2028

Last change on this file since 2028 was 2012, checked in by WataruKawasaki, 14 years ago

New Development: Yes

JIRA Issue: Yes (CAS-2373, CAS-2620)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: For Scantable::polyBaseline(), parameters and return value have been changed.

Test Programs:

Put in Release Notes: Yes

Module(s): sdbaseline, sd.linefinder

Description: (1) CAS-2373-related:

(1.1) Modified Scantable::polyBaseline() to have the row-based loop inside.

Now it fits and subtracts baseline for all rows and also output info
about the fitting result to logger and text file, while in the
previous version this method just did baseline fitting/subtraction
for one row only and had to be put inside a row-based loop at the
python side ("poly_baseline()" in scantable.py) and result output had
also to be controlled at the python side. Using a test data from NRO
45m telescope (348,000 rows, 512 channels), the processing time of
scantable.poly_baseline() has reduced from 130 minutes to 5-6 minutes.

(1.2) For accelerating the another polynomial fitting function, namely

scantable.auto_poly_baseline(), added a method
Scantable::autoPolyBaseline(). This basically does the same thing
with Scantable::polyBaseline(), but uses linefinfer also to
automatically flag the line regions.

(1.3) To make linefinder usable in Scantable class, added a method

linefinder.setdata(). This makes it possible to apply linefinder
for a float-list data given as a parameter, without setting scantable,
while it was indispensable to set scantable to use linefinger previously.

(2) CAS-2620-related:

Added Scantable::cubicSplineBaseline() and autoCubicSplineBaseline() for
fit baseline using the cubic spline function. Parameters include npiece
(number of polynomial pieces), clipthresh (clipping threshold), and
clipniter (maximum iteration number).



  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 76.6 KB
RevLine 
[805]1//
2// C++ Implementation: Scantable
3//
4// Description:
5//
6//
7// Author: Malte Marquarding <asap@atnf.csiro.au>, (C) 2005
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
[206]12#include <map>
[1819]13#include <fstream>
[206]14
[125]15#include <casa/aips.h>
[80]16#include <casa/iostream.h>
17#include <casa/iomanip.h>
[805]18#include <casa/OS/Path.h>
19#include <casa/OS/File.h>
[80]20#include <casa/Arrays/Array.h>
21#include <casa/Arrays/ArrayMath.h>
22#include <casa/Arrays/MaskArrMath.h>
23#include <casa/Arrays/ArrayLogical.h>
24#include <casa/Arrays/ArrayAccessor.h>
[1325]25#include <casa/Arrays/Vector.h>
[455]26#include <casa/Arrays/VectorSTLIterator.h>
[1819]27#include <casa/Arrays/Slice.h>
[418]28#include <casa/BasicMath/Math.h>
[504]29#include <casa/BasicSL/Constants.h>
[286]30#include <casa/Quanta/MVAngle.h>
[805]31#include <casa/Containers/RecordField.h>
[902]32#include <casa/Utilities/GenSort.h>
[1819]33#include <casa/Logging/LogIO.h>
[2]34
[80]35#include <tables/Tables/TableParse.h>
36#include <tables/Tables/TableDesc.h>
[488]37#include <tables/Tables/TableCopy.h>
[80]38#include <tables/Tables/SetupNewTab.h>
39#include <tables/Tables/ScaColDesc.h>
40#include <tables/Tables/ArrColDesc.h>
[805]41#include <tables/Tables/TableRow.h>
42#include <tables/Tables/TableVector.h>
43#include <tables/Tables/TableIter.h>
[2]44
[80]45#include <tables/Tables/ExprNode.h>
46#include <tables/Tables/TableRecord.h>
[1325]47#include <casa/Quanta/MVTime.h>
48#include <casa/Quanta/MVAngle.h>
49#include <measures/Measures/MeasRef.h>
50#include <measures/Measures/MeasTable.h>
51// needed to avoid error in .tcc
52#include <measures/Measures/MCDirection.h>
53//
54#include <measures/Measures/MDirection.h>
[80]55#include <measures/Measures/MFrequency.h>
[805]56#include <measures/Measures/MEpoch.h>
57#include <measures/TableMeasures/TableMeasRefDesc.h>
58#include <measures/TableMeasures/TableMeasValueDesc.h>
59#include <measures/TableMeasures/TableMeasDesc.h>
60#include <measures/TableMeasures/ScalarMeasColumn.h>
[105]61#include <coordinates/Coordinates/CoordinateUtil.h>
[2]62
[2005]63#include <atnf/PKSIO/SrcType.h>
[805]64#include "Scantable.h"
[896]65#include "STPolLinear.h"
[1189]66#include "STPolCircular.h"
[913]67#include "STPolStokes.h"
[878]68#include "STAttr.h"
[2012]69#include "STLineFinder.h"
[902]70#include "MathUtils.h"
[2]71
[125]72using namespace casa;
[2]73
[805]74namespace asap {
75
[896]76std::map<std::string, STPol::STPolFactory *> Scantable::factories_;
77
78void Scantable::initFactories() {
79 if ( factories_.empty() ) {
80 Scantable::factories_["linear"] = &STPolLinear::myFactory;
[1323]81 Scantable::factories_["circular"] = &STPolCircular::myFactory;
[913]82 Scantable::factories_["stokes"] = &STPolStokes::myFactory;
[896]83 }
84}
85
[805]86Scantable::Scantable(Table::TableType ttype) :
[852]87 type_(ttype)
[206]88{
[896]89 initFactories();
[805]90 setupMainTable();
[852]91 freqTable_ = STFrequencies(*this);
[805]92 table_.rwKeywordSet().defineTable("FREQUENCIES", freqTable_.table());
[852]93 weatherTable_ = STWeather(*this);
[805]94 table_.rwKeywordSet().defineTable("WEATHER", weatherTable_.table());
[852]95 focusTable_ = STFocus(*this);
[805]96 table_.rwKeywordSet().defineTable("FOCUS", focusTable_.table());
[852]97 tcalTable_ = STTcal(*this);
[805]98 table_.rwKeywordSet().defineTable("TCAL", tcalTable_.table());
[852]99 moleculeTable_ = STMolecules(*this);
[805]100 table_.rwKeywordSet().defineTable("MOLECULES", moleculeTable_.table());
[860]101 historyTable_ = STHistory(*this);
102 table_.rwKeywordSet().defineTable("HISTORY", historyTable_.table());
[959]103 fitTable_ = STFit(*this);
104 table_.rwKeywordSet().defineTable("FIT", fitTable_.table());
[1881]105 table_.tableInfo().setType( "Scantable" ) ;
[805]106 originalTable_ = table_;
[322]107 attach();
[18]108}
[206]109
[805]110Scantable::Scantable(const std::string& name, Table::TableType ttype) :
[852]111 type_(ttype)
[206]112{
[896]113 initFactories();
[1819]114
[865]115 Table tab(name, Table::Update);
[1009]116 uInt version = tab.keywordSet().asuInt("VERSION");
[483]117 if (version != version_) {
118 throw(AipsError("Unsupported version of ASAP file."));
119 }
[1009]120 if ( type_ == Table::Memory ) {
[852]121 table_ = tab.copyToMemoryTable(generateName());
[1009]122 } else {
[805]123 table_ = tab;
[1009]124 }
[1881]125 table_.tableInfo().setType( "Scantable" ) ;
[1009]126
[859]127 attachSubtables();
[805]128 originalTable_ = table_;
[329]129 attach();
[2]130}
[1819]131/*
132Scantable::Scantable(const std::string& name, Table::TableType ttype) :
133 type_(ttype)
134{
135 initFactories();
136 Table tab(name, Table::Update);
137 uInt version = tab.keywordSet().asuInt("VERSION");
138 if (version != version_) {
139 throw(AipsError("Unsupported version of ASAP file."));
140 }
141 if ( type_ == Table::Memory ) {
142 table_ = tab.copyToMemoryTable(generateName());
143 } else {
144 table_ = tab;
145 }
[2]146
[1819]147 attachSubtables();
148 originalTable_ = table_;
149 attach();
150}
151*/
152
[805]153Scantable::Scantable( const Scantable& other, bool clear )
[206]154{
[805]155 // with or without data
[859]156 String newname = String(generateName());
[865]157 type_ = other.table_.tableType();
[859]158 if ( other.table_.tableType() == Table::Memory ) {
159 if ( clear ) {
160 table_ = TableCopy::makeEmptyMemoryTable(newname,
161 other.table_, True);
162 } else
163 table_ = other.table_.copyToMemoryTable(newname);
[16]164 } else {
[915]165 other.table_.deepCopy(newname, Table::New, False,
166 other.table_.endianFormat(),
[865]167 Bool(clear));
168 table_ = Table(newname, Table::Update);
169 table_.markForDelete();
170 }
[1881]171 table_.tableInfo().setType( "Scantable" ) ;
[1111]172 /// @todo reindex SCANNO, recompute nbeam, nif, npol
[915]173 if ( clear ) copySubtables(other);
[859]174 attachSubtables();
[805]175 originalTable_ = table_;
[322]176 attach();
[2]177}
178
[865]179void Scantable::copySubtables(const Scantable& other) {
180 Table t = table_.rwKeywordSet().asTable("FREQUENCIES");
181 TableCopy::copyRows(t, other.freqTable_.table());
182 t = table_.rwKeywordSet().asTable("FOCUS");
183 TableCopy::copyRows(t, other.focusTable_.table());
184 t = table_.rwKeywordSet().asTable("WEATHER");
185 TableCopy::copyRows(t, other.weatherTable_.table());
186 t = table_.rwKeywordSet().asTable("TCAL");
187 TableCopy::copyRows(t, other.tcalTable_.table());
188 t = table_.rwKeywordSet().asTable("MOLECULES");
189 TableCopy::copyRows(t, other.moleculeTable_.table());
190 t = table_.rwKeywordSet().asTable("HISTORY");
191 TableCopy::copyRows(t, other.historyTable_.table());
[972]192 t = table_.rwKeywordSet().asTable("FIT");
193 TableCopy::copyRows(t, other.fitTable_.table());
[865]194}
195
[859]196void Scantable::attachSubtables()
197{
198 freqTable_ = STFrequencies(table_);
199 focusTable_ = STFocus(table_);
200 weatherTable_ = STWeather(table_);
201 tcalTable_ = STTcal(table_);
202 moleculeTable_ = STMolecules(table_);
[860]203 historyTable_ = STHistory(table_);
[972]204 fitTable_ = STFit(table_);
[859]205}
206
[805]207Scantable::~Scantable()
[206]208{
[941]209 //cout << "~Scantable() " << this << endl;
[2]210}
211
[805]212void Scantable::setupMainTable()
[206]213{
[805]214 TableDesc td("", "1", TableDesc::Scratch);
215 td.comment() = "An ASAP Scantable";
[1009]216 td.rwKeywordSet().define("VERSION", uInt(version_));
[2]217
[805]218 // n Cycles
219 td.addColumn(ScalarColumnDesc<uInt>("SCANNO"));
220 // new index every nBeam x nIF x nPol
221 td.addColumn(ScalarColumnDesc<uInt>("CYCLENO"));
[2]222
[805]223 td.addColumn(ScalarColumnDesc<uInt>("BEAMNO"));
224 td.addColumn(ScalarColumnDesc<uInt>("IFNO"));
[972]225 // linear, circular, stokes
[805]226 td.rwKeywordSet().define("POLTYPE", String("linear"));
227 td.addColumn(ScalarColumnDesc<uInt>("POLNO"));
[138]228
[805]229 td.addColumn(ScalarColumnDesc<uInt>("FREQ_ID"));
230 td.addColumn(ScalarColumnDesc<uInt>("MOLECULE_ID"));
[80]231
[1819]232 ScalarColumnDesc<Int> refbeamnoColumn("REFBEAMNO");
233 refbeamnoColumn.setDefault(Int(-1));
234 td.addColumn(refbeamnoColumn);
235
236 ScalarColumnDesc<uInt> flagrowColumn("FLAGROW");
237 flagrowColumn.setDefault(uInt(0));
238 td.addColumn(flagrowColumn);
239
[805]240 td.addColumn(ScalarColumnDesc<Double>("TIME"));
241 TableMeasRefDesc measRef(MEpoch::UTC); // UTC as default
242 TableMeasValueDesc measVal(td, "TIME");
243 TableMeasDesc<MEpoch> mepochCol(measVal, measRef);
244 mepochCol.write(td);
[483]245
[805]246 td.addColumn(ScalarColumnDesc<Double>("INTERVAL"));
247
[2]248 td.addColumn(ScalarColumnDesc<String>("SRCNAME"));
[805]249 // Type of source (on=0, off=1, other=-1)
[1503]250 ScalarColumnDesc<Int> stypeColumn("SRCTYPE");
251 stypeColumn.setDefault(Int(-1));
252 td.addColumn(stypeColumn);
[805]253 td.addColumn(ScalarColumnDesc<String>("FIELDNAME"));
254
255 //The actual Data Vectors
[2]256 td.addColumn(ArrayColumnDesc<Float>("SPECTRA"));
257 td.addColumn(ArrayColumnDesc<uChar>("FLAGTRA"));
[89]258 td.addColumn(ArrayColumnDesc<Float>("TSYS"));
[805]259
260 td.addColumn(ArrayColumnDesc<Double>("DIRECTION",
261 IPosition(1,2),
262 ColumnDesc::Direct));
263 TableMeasRefDesc mdirRef(MDirection::J2000); // default
264 TableMeasValueDesc tmvdMDir(td, "DIRECTION");
265 // the TableMeasDesc gives the column a type
266 TableMeasDesc<MDirection> mdirCol(tmvdMDir, mdirRef);
[987]267 // a uder set table type e.g. GALCTIC, B1950 ...
268 td.rwKeywordSet().define("DIRECTIONREF", String("J2000"));
[805]269 // writing create the measure column
270 mdirCol.write(td);
[923]271 td.addColumn(ScalarColumnDesc<Float>("AZIMUTH"));
272 td.addColumn(ScalarColumnDesc<Float>("ELEVATION"));
[1047]273 td.addColumn(ScalarColumnDesc<Float>("OPACITY"));
[105]274
[805]275 td.addColumn(ScalarColumnDesc<uInt>("TCAL_ID"));
[972]276 ScalarColumnDesc<Int> fitColumn("FIT_ID");
[973]277 fitColumn.setDefault(Int(-1));
[972]278 td.addColumn(fitColumn);
[805]279
280 td.addColumn(ScalarColumnDesc<uInt>("FOCUS_ID"));
281 td.addColumn(ScalarColumnDesc<uInt>("WEATHER_ID"));
282
[999]283 // columns which just get dragged along, as they aren't used in asap
284 td.addColumn(ScalarColumnDesc<Double>("SRCVELOCITY"));
285 td.addColumn(ArrayColumnDesc<Double>("SRCPROPERMOTION"));
286 td.addColumn(ArrayColumnDesc<Double>("SRCDIRECTION"));
287 td.addColumn(ArrayColumnDesc<Double>("SCANRATE"));
288
[805]289 td.rwKeywordSet().define("OBSMODE", String(""));
290
[418]291 // Now create Table SetUp from the description.
[859]292 SetupNewTable aNewTab(generateName(), td, Table::Scratch);
[852]293 table_ = Table(aNewTab, type_, 0);
[805]294 originalTable_ = table_;
295}
[418]296
[805]297void Scantable::attach()
[455]298{
[805]299 timeCol_.attach(table_, "TIME");
300 srcnCol_.attach(table_, "SRCNAME");
[1068]301 srctCol_.attach(table_, "SRCTYPE");
[805]302 specCol_.attach(table_, "SPECTRA");
303 flagsCol_.attach(table_, "FLAGTRA");
[865]304 tsysCol_.attach(table_, "TSYS");
[805]305 cycleCol_.attach(table_,"CYCLENO");
306 scanCol_.attach(table_, "SCANNO");
307 beamCol_.attach(table_, "BEAMNO");
[847]308 ifCol_.attach(table_, "IFNO");
309 polCol_.attach(table_, "POLNO");
[805]310 integrCol_.attach(table_, "INTERVAL");
311 azCol_.attach(table_, "AZIMUTH");
312 elCol_.attach(table_, "ELEVATION");
313 dirCol_.attach(table_, "DIRECTION");
314 fldnCol_.attach(table_, "FIELDNAME");
315 rbeamCol_.attach(table_, "REFBEAMNO");
[455]316
[1730]317 mweatheridCol_.attach(table_,"WEATHER_ID");
[805]318 mfitidCol_.attach(table_,"FIT_ID");
319 mfreqidCol_.attach(table_, "FREQ_ID");
320 mtcalidCol_.attach(table_, "TCAL_ID");
321 mfocusidCol_.attach(table_, "FOCUS_ID");
322 mmolidCol_.attach(table_, "MOLECULE_ID");
[1819]323
324 //Add auxiliary column for row-based flagging (CAS-1433 Wataru Kawasaki)
325 attachAuxColumnDef(flagrowCol_, "FLAGROW", 0);
326
[455]327}
328
[1819]329template<class T, class T2>
330void Scantable::attachAuxColumnDef(ScalarColumn<T>& col,
331 const String& colName,
332 const T2& defValue)
333{
334 try {
335 col.attach(table_, colName);
336 } catch (TableError& err) {
337 String errMesg = err.getMesg();
338 if (errMesg == "Table column " + colName + " is unknown") {
339 table_.addColumn(ScalarColumnDesc<T>(colName));
340 col.attach(table_, colName);
341 col.fillColumn(static_cast<T>(defValue));
342 } else {
343 throw;
344 }
345 } catch (...) {
346 throw;
347 }
348}
349
350template<class T, class T2>
351void Scantable::attachAuxColumnDef(ArrayColumn<T>& col,
352 const String& colName,
353 const Array<T2>& defValue)
354{
355 try {
356 col.attach(table_, colName);
357 } catch (TableError& err) {
358 String errMesg = err.getMesg();
359 if (errMesg == "Table column " + colName + " is unknown") {
360 table_.addColumn(ArrayColumnDesc<T>(colName));
361 col.attach(table_, colName);
362
363 int size = 0;
364 ArrayIterator<T2>& it = defValue.begin();
365 while (it != defValue.end()) {
366 ++size;
367 ++it;
368 }
369 IPosition ip(1, size);
370 Array<T>& arr(ip);
371 for (int i = 0; i < size; ++i)
372 arr[i] = static_cast<T>(defValue[i]);
373
374 col.fillColumn(arr);
375 } else {
376 throw;
377 }
378 } catch (...) {
379 throw;
380 }
381}
382
[901]383void Scantable::setHeader(const STHeader& sdh)
[206]384{
[18]385 table_.rwKeywordSet().define("nIF", sdh.nif);
386 table_.rwKeywordSet().define("nBeam", sdh.nbeam);
387 table_.rwKeywordSet().define("nPol", sdh.npol);
388 table_.rwKeywordSet().define("nChan", sdh.nchan);
389 table_.rwKeywordSet().define("Observer", sdh.observer);
390 table_.rwKeywordSet().define("Project", sdh.project);
391 table_.rwKeywordSet().define("Obstype", sdh.obstype);
392 table_.rwKeywordSet().define("AntennaName", sdh.antennaname);
393 table_.rwKeywordSet().define("AntennaPosition", sdh.antennaposition);
394 table_.rwKeywordSet().define("Equinox", sdh.equinox);
395 table_.rwKeywordSet().define("FreqRefFrame", sdh.freqref);
396 table_.rwKeywordSet().define("FreqRefVal", sdh.reffreq);
397 table_.rwKeywordSet().define("Bandwidth", sdh.bandwidth);
398 table_.rwKeywordSet().define("UTC", sdh.utc);
[206]399 table_.rwKeywordSet().define("FluxUnit", sdh.fluxunit);
400 table_.rwKeywordSet().define("Epoch", sdh.epoch);
[905]401 table_.rwKeywordSet().define("POLTYPE", sdh.poltype);
[50]402}
[21]403
[901]404STHeader Scantable::getHeader() const
[206]405{
[901]406 STHeader sdh;
[21]407 table_.keywordSet().get("nBeam",sdh.nbeam);
408 table_.keywordSet().get("nIF",sdh.nif);
409 table_.keywordSet().get("nPol",sdh.npol);
410 table_.keywordSet().get("nChan",sdh.nchan);
411 table_.keywordSet().get("Observer", sdh.observer);
412 table_.keywordSet().get("Project", sdh.project);
413 table_.keywordSet().get("Obstype", sdh.obstype);
414 table_.keywordSet().get("AntennaName", sdh.antennaname);
415 table_.keywordSet().get("AntennaPosition", sdh.antennaposition);
416 table_.keywordSet().get("Equinox", sdh.equinox);
417 table_.keywordSet().get("FreqRefFrame", sdh.freqref);
418 table_.keywordSet().get("FreqRefVal", sdh.reffreq);
419 table_.keywordSet().get("Bandwidth", sdh.bandwidth);
420 table_.keywordSet().get("UTC", sdh.utc);
[206]421 table_.keywordSet().get("FluxUnit", sdh.fluxunit);
422 table_.keywordSet().get("Epoch", sdh.epoch);
[905]423 table_.keywordSet().get("POLTYPE", sdh.poltype);
[21]424 return sdh;
[18]425}
[805]426
[1360]427void Scantable::setSourceType( int stype )
[1068]428{
429 if ( stype < 0 || stype > 1 )
430 throw(AipsError("Illegal sourcetype."));
431 TableVector<Int> tabvec(table_, "SRCTYPE");
432 tabvec = Int(stype);
433}
434
[845]435bool Scantable::conformant( const Scantable& other )
436{
437 return this->getHeader().conformant(other.getHeader());
438}
439
440
[50]441
[805]442std::string Scantable::formatSec(Double x) const
[206]443{
[105]444 Double xcop = x;
445 MVTime mvt(xcop/24./3600.); // make days
[365]446
[105]447 if (x < 59.95)
[281]448 return String(" ") + mvt.string(MVTime::TIME_CLEAN_NO_HM, 7)+"s";
[745]449 else if (x < 3599.95)
[281]450 return String(" ") + mvt.string(MVTime::TIME_CLEAN_NO_H,7)+" ";
451 else {
452 ostringstream oss;
453 oss << setw(2) << std::right << setprecision(1) << mvt.hour();
454 oss << ":" << mvt.string(MVTime::TIME_CLEAN_NO_H,7) << " ";
455 return String(oss);
[745]456 }
[105]457};
458
[805]459std::string Scantable::formatDirection(const MDirection& md) const
[281]460{
461 Vector<Double> t = md.getAngle(Unit(String("rad"))).getValue();
462 Int prec = 7;
463
464 MVAngle mvLon(t[0]);
465 String sLon = mvLon.string(MVAngle::TIME,prec);
[987]466 uInt tp = md.getRef().getType();
467 if (tp == MDirection::GALACTIC ||
468 tp == MDirection::SUPERGAL ) {
469 sLon = mvLon(0.0).string(MVAngle::ANGLE_CLEAN,prec);
470 }
[281]471 MVAngle mvLat(t[1]);
472 String sLat = mvLat.string(MVAngle::ANGLE+MVAngle::DIG2,prec);
[380]473 return sLon + String(" ") + sLat;
[281]474}
475
476
[805]477std::string Scantable::getFluxUnit() const
[206]478{
[847]479 return table_.keywordSet().asString("FluxUnit");
[206]480}
481
[805]482void Scantable::setFluxUnit(const std::string& unit)
[218]483{
484 String tmp(unit);
485 Unit tU(tmp);
486 if (tU==Unit("K") || tU==Unit("Jy")) {
487 table_.rwKeywordSet().define(String("FluxUnit"), tmp);
488 } else {
489 throw AipsError("Illegal unit - must be compatible with Jy or K");
490 }
491}
492
[805]493void Scantable::setInstrument(const std::string& name)
[236]494{
[805]495 bool throwIt = true;
[996]496 // create an Instrument to see if this is valid
497 STAttr::convertInstrument(name, throwIt);
[236]498 String nameU(name);
499 nameU.upcase();
500 table_.rwKeywordSet().define(String("AntennaName"), nameU);
501}
502
[1189]503void Scantable::setFeedType(const std::string& feedtype)
504{
505 if ( Scantable::factories_.find(feedtype) == Scantable::factories_.end() ) {
506 std::string msg = "Illegal feed type "+ feedtype;
507 throw(casa::AipsError(msg));
508 }
509 table_.rwKeywordSet().define(String("POLTYPE"), feedtype);
510}
511
[1743]512MPosition Scantable::getAntennaPosition() const
[805]513{
514 Vector<Double> antpos;
515 table_.keywordSet().get("AntennaPosition", antpos);
516 MVPosition mvpos(antpos(0),antpos(1),antpos(2));
517 return MPosition(mvpos);
518}
[281]519
[805]520void Scantable::makePersistent(const std::string& filename)
521{
522 String inname(filename);
523 Path path(inname);
[1111]524 /// @todo reindex SCANNO, recompute nbeam, nif, npol
[805]525 inname = path.expandedName();
[1727]526 // WORKAROUND !!! for Table bug
527 // Remove when fixed in casacore
[1728]528 if ( table_.tableType() == Table::Memory && !selector_.empty() ) {
[1727]529 Table tab = table_.copyToMemoryTable(generateName());
530 tab.deepCopy(inname, Table::New);
[1730]531 tab.markForDelete();
532
[1727]533 } else {
534 table_.deepCopy(inname, Table::New);
535 }
[805]536}
537
[837]538int Scantable::nbeam( int scanno ) const
[805]539{
540 if ( scanno < 0 ) {
541 Int n;
542 table_.keywordSet().get("nBeam",n);
543 return int(n);
[105]544 } else {
[805]545 // take the first POLNO,IFNO,CYCLENO as nbeam shouldn't vary with these
[888]546 Table t = table_(table_.col("SCANNO") == scanno);
547 ROTableRow row(t);
548 const TableRecord& rec = row.get(0);
549 Table subt = t( t.col("IFNO") == Int(rec.asuInt("IFNO"))
550 && t.col("POLNO") == Int(rec.asuInt("POLNO"))
551 && t.col("CYCLENO") == Int(rec.asuInt("CYCLENO")) );
552 ROTableVector<uInt> v(subt, "BEAMNO");
[805]553 return int(v.nelements());
[105]554 }
[805]555 return 0;
556}
[455]557
[837]558int Scantable::nif( int scanno ) const
[805]559{
560 if ( scanno < 0 ) {
561 Int n;
562 table_.keywordSet().get("nIF",n);
563 return int(n);
564 } else {
565 // take the first POLNO,BEAMNO,CYCLENO as nbeam shouldn't vary with these
[888]566 Table t = table_(table_.col("SCANNO") == scanno);
567 ROTableRow row(t);
568 const TableRecord& rec = row.get(0);
569 Table subt = t( t.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
570 && t.col("POLNO") == Int(rec.asuInt("POLNO"))
571 && t.col("CYCLENO") == Int(rec.asuInt("CYCLENO")) );
572 if ( subt.nrow() == 0 ) return 0;
573 ROTableVector<uInt> v(subt, "IFNO");
[805]574 return int(v.nelements());
[2]575 }
[805]576 return 0;
577}
[321]578
[837]579int Scantable::npol( int scanno ) const
[805]580{
581 if ( scanno < 0 ) {
582 Int n;
583 table_.keywordSet().get("nPol",n);
584 return n;
585 } else {
586 // take the first POLNO,IFNO,CYCLENO as nbeam shouldn't vary with these
[888]587 Table t = table_(table_.col("SCANNO") == scanno);
588 ROTableRow row(t);
589 const TableRecord& rec = row.get(0);
590 Table subt = t( t.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
591 && t.col("IFNO") == Int(rec.asuInt("IFNO"))
592 && t.col("CYCLENO") == Int(rec.asuInt("CYCLENO")) );
593 if ( subt.nrow() == 0 ) return 0;
594 ROTableVector<uInt> v(subt, "POLNO");
[805]595 return int(v.nelements());
[321]596 }
[805]597 return 0;
[2]598}
[805]599
[845]600int Scantable::ncycle( int scanno ) const
[206]601{
[805]602 if ( scanno < 0 ) {
[837]603 Block<String> cols(2);
604 cols[0] = "SCANNO";
605 cols[1] = "CYCLENO";
606 TableIterator it(table_, cols);
607 int n = 0;
608 while ( !it.pastEnd() ) {
609 ++n;
[902]610 ++it;
[837]611 }
612 return n;
[805]613 } else {
[888]614 Table t = table_(table_.col("SCANNO") == scanno);
615 ROTableRow row(t);
616 const TableRecord& rec = row.get(0);
617 Table subt = t( t.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
618 && t.col("POLNO") == Int(rec.asuInt("POLNO"))
619 && t.col("IFNO") == Int(rec.asuInt("IFNO")) );
620 if ( subt.nrow() == 0 ) return 0;
621 return int(subt.nrow());
[805]622 }
623 return 0;
[18]624}
[455]625
626
[845]627int Scantable::nrow( int scanno ) const
[805]628{
[845]629 return int(table_.nrow());
630}
631
632int Scantable::nchan( int ifno ) const
633{
634 if ( ifno < 0 ) {
[805]635 Int n;
636 table_.keywordSet().get("nChan",n);
637 return int(n);
638 } else {
[1360]639 // take the first SCANNO,POLNO,BEAMNO,CYCLENO as nbeam shouldn't
640 // vary with these
[888]641 Table t = table_(table_.col("IFNO") == ifno);
642 if ( t.nrow() == 0 ) return 0;
643 ROArrayColumn<Float> v(t, "SPECTRA");
[923]644 return v.shape(0)(0);
[805]645 }
646 return 0;
[18]647}
[455]648
[1111]649int Scantable::nscan() const {
650 Vector<uInt> scannos(scanCol_.getColumn());
[1148]651 uInt nout = genSort( scannos, Sort::Ascending,
[1111]652 Sort::QuickSort|Sort::NoDuplicates );
653 return int(nout);
654}
655
[923]656int Scantable::getChannels(int whichrow) const
657{
658 return specCol_.shape(whichrow)(0);
659}
[847]660
661int Scantable::getBeam(int whichrow) const
662{
663 return beamCol_(whichrow);
664}
665
[1694]666std::vector<uint> Scantable::getNumbers(const ScalarColumn<uInt>& col) const
[1111]667{
668 Vector<uInt> nos(col.getColumn());
[1148]669 uInt n = genSort( nos, Sort::Ascending, Sort::QuickSort|Sort::NoDuplicates );
670 nos.resize(n, True);
[1111]671 std::vector<uint> stlout;
672 nos.tovector(stlout);
673 return stlout;
674}
675
[847]676int Scantable::getIF(int whichrow) const
677{
678 return ifCol_(whichrow);
679}
680
681int Scantable::getPol(int whichrow) const
682{
683 return polCol_(whichrow);
684}
685
[805]686std::string Scantable::formatTime(const MEpoch& me, bool showdate) const
687{
[1947]688 return formatTime(me, showdate, 0);
689}
690
691std::string Scantable::formatTime(const MEpoch& me, bool showdate, uInt prec) const
692{
[805]693 MVTime mvt(me.getValue());
694 if (showdate)
[1947]695 //mvt.setFormat(MVTime::YMD);
696 mvt.setFormat(MVTime::YMD, prec);
[805]697 else
[1947]698 //mvt.setFormat(MVTime::TIME);
699 mvt.setFormat(MVTime::TIME, prec);
[805]700 ostringstream oss;
701 oss << mvt;
702 return String(oss);
703}
[488]704
[805]705void Scantable::calculateAZEL()
706{
707 MPosition mp = getAntennaPosition();
708 MEpoch::ROScalarColumn timeCol(table_, "TIME");
709 ostringstream oss;
710 oss << "Computed azimuth/elevation using " << endl
711 << mp << endl;
[996]712 for (Int i=0; i<nrow(); ++i) {
[805]713 MEpoch me = timeCol(i);
[987]714 MDirection md = getDirection(i);
[805]715 oss << " Time: " << formatTime(me,False) << " Direction: " << formatDirection(md)
716 << endl << " => ";
717 MeasFrame frame(mp, me);
718 Vector<Double> azel =
719 MDirection::Convert(md, MDirection::Ref(MDirection::AZEL,
720 frame)
721 )().getAngle("rad").getValue();
[923]722 azCol_.put(i,Float(azel[0]));
723 elCol_.put(i,Float(azel[1]));
[805]724 oss << "azel: " << azel[0]/C::pi*180.0 << " "
725 << azel[1]/C::pi*180.0 << " (deg)" << endl;
[16]726 }
[805]727 pushLog(String(oss));
728}
[89]729
[1819]730void Scantable::clip(const Float uthres, const Float dthres, bool clipoutside, bool unflag)
731{
732 for (uInt i=0; i<table_.nrow(); ++i) {
733 Vector<uChar> flgs = flagsCol_(i);
734 srchChannelsToClip(i, uthres, dthres, clipoutside, unflag, flgs);
735 flagsCol_.put(i, flgs);
736 }
737}
738
739std::vector<bool> Scantable::getClipMask(int whichrow, const Float uthres, const Float dthres, bool clipoutside, bool unflag)
740{
741 Vector<uChar> flags;
742 flagsCol_.get(uInt(whichrow), flags);
743 srchChannelsToClip(uInt(whichrow), uthres, dthres, clipoutside, unflag, flags);
744 Vector<Bool> bflag(flags.shape());
745 convertArray(bflag, flags);
746 //bflag = !bflag;
747
748 std::vector<bool> mask;
749 bflag.tovector(mask);
750 return mask;
751}
752
753void Scantable::srchChannelsToClip(uInt whichrow, const Float uthres, const Float dthres, bool clipoutside, bool unflag,
754 Vector<uChar> flgs)
755{
756 Vector<Float> spcs = specCol_(whichrow);
757 uInt nchannel = nchan();
758 if (spcs.nelements() != nchannel) {
759 throw(AipsError("Data has incorrect number of channels"));
760 }
761 uChar userflag = 1 << 7;
762 if (unflag) {
763 userflag = 0 << 7;
764 }
765 if (clipoutside) {
766 for (uInt j = 0; j < nchannel; ++j) {
767 Float spc = spcs(j);
768 if ((spc >= uthres) || (spc <= dthres)) {
769 flgs(j) = userflag;
770 }
771 }
772 } else {
773 for (uInt j = 0; j < nchannel; ++j) {
774 Float spc = spcs(j);
775 if ((spc < uthres) && (spc > dthres)) {
776 flgs(j) = userflag;
777 }
778 }
779 }
780}
781
[1994]782
783void Scantable::flag( int whichrow, const std::vector<bool>& msk, bool unflag ) {
[1333]784 std::vector<bool>::const_iterator it;
785 uInt ntrue = 0;
[1994]786 if (whichrow >= int(table_.nrow()) ) {
787 throw(AipsError("Invalid row number"));
788 }
[1333]789 for (it = msk.begin(); it != msk.end(); ++it) {
790 if ( *it ) {
791 ntrue++;
792 }
793 }
[1994]794 //if ( selector_.empty() && (msk.size() == 0 || msk.size() == ntrue) )
795 if ( whichrow == -1 && !unflag && selector_.empty() && (msk.size() == 0 || msk.size() == ntrue) )
[1000]796 throw(AipsError("Trying to flag whole scantable."));
[1994]797 uChar userflag = 1 << 7;
798 if ( unflag ) {
799 userflag = 0 << 7;
800 }
801 if (whichrow > -1 ) {
802 applyChanFlag(uInt(whichrow), msk, userflag);
803 } else {
[1000]804 for ( uInt i=0; i<table_.nrow(); ++i) {
[1994]805 applyChanFlag(i, msk, userflag);
[1000]806 }
[1994]807 }
808}
809
810void Scantable::applyChanFlag( uInt whichrow, const std::vector<bool>& msk, uChar flagval )
811{
812 if (whichrow >= table_.nrow() ) {
813 throw( casa::indexError<int>( whichrow, "asap::Scantable::applyChanFlag: Invalid row number" ) );
814 }
815 Vector<uChar> flgs = flagsCol_(whichrow);
816 if ( msk.size() == 0 ) {
817 flgs = flagval;
818 flagsCol_.put(whichrow, flgs);
[1000]819 return;
820 }
821 if ( int(msk.size()) != nchan() ) {
822 throw(AipsError("Mask has incorrect number of channels."));
823 }
[1994]824 if ( flgs.nelements() != msk.size() ) {
825 throw(AipsError("Mask has incorrect number of channels."
826 " Probably varying with IF. Please flag per IF"));
827 }
828 std::vector<bool>::const_iterator it;
829 uInt j = 0;
830 for (it = msk.begin(); it != msk.end(); ++it) {
831 if ( *it ) {
832 flgs(j) = flagval;
[1000]833 }
[1994]834 ++j;
[1000]835 }
[1994]836 flagsCol_.put(whichrow, flgs);
[865]837}
838
[1819]839void Scantable::flagRow(const std::vector<uInt>& rows, bool unflag)
840{
841 if ( selector_.empty() && (rows.size() == table_.nrow()) )
842 throw(AipsError("Trying to flag whole scantable."));
843
844 uInt rowflag = (unflag ? 0 : 1);
845 std::vector<uInt>::const_iterator it;
846 for (it = rows.begin(); it != rows.end(); ++it)
847 flagrowCol_.put(*it, rowflag);
848}
849
[805]850std::vector<bool> Scantable::getMask(int whichrow) const
851{
852 Vector<uChar> flags;
853 flagsCol_.get(uInt(whichrow), flags);
854 Vector<Bool> bflag(flags.shape());
855 convertArray(bflag, flags);
856 bflag = !bflag;
857 std::vector<bool> mask;
858 bflag.tovector(mask);
859 return mask;
860}
[89]861
[896]862std::vector<float> Scantable::getSpectrum( int whichrow,
[902]863 const std::string& poltype ) const
[805]864{
[905]865 String ptype = poltype;
866 if (poltype == "" ) ptype = getPolType();
[902]867 if ( whichrow < 0 || whichrow >= nrow() )
868 throw(AipsError("Illegal row number."));
[896]869 std::vector<float> out;
[805]870 Vector<Float> arr;
[896]871 uInt requestedpol = polCol_(whichrow);
872 String basetype = getPolType();
[905]873 if ( ptype == basetype ) {
[896]874 specCol_.get(whichrow, arr);
875 } else {
[1598]876 CountedPtr<STPol> stpol(STPol::getPolClass(Scantable::factories_,
[1586]877 basetype));
[1334]878 uInt row = uInt(whichrow);
879 stpol->setSpectra(getPolMatrix(row));
880 Float fang,fhand,parang;
[1586]881 fang = focusTable_.getTotalAngle(mfocusidCol_(row));
[1334]882 fhand = focusTable_.getFeedHand(mfocusidCol_(row));
[1586]883 stpol->setPhaseCorrections(fang, fhand);
[1334]884 arr = stpol->getSpectrum(requestedpol, ptype);
[896]885 }
[902]886 if ( arr.nelements() == 0 )
887 pushLog("Not enough polarisations present to do the conversion.");
[805]888 arr.tovector(out);
889 return out;
[89]890}
[212]891
[1360]892void Scantable::setSpectrum( const std::vector<float>& spec,
[884]893 int whichrow )
894{
895 Vector<Float> spectrum(spec);
896 Vector<Float> arr;
897 specCol_.get(whichrow, arr);
898 if ( spectrum.nelements() != arr.nelements() )
[896]899 throw AipsError("The spectrum has incorrect number of channels.");
[884]900 specCol_.put(whichrow, spectrum);
901}
902
903
[805]904String Scantable::generateName()
[745]905{
[805]906 return (File::newUniqueName("./","temp")).baseName();
[212]907}
908
[805]909const casa::Table& Scantable::table( ) const
[212]910{
[805]911 return table_;
[212]912}
913
[805]914casa::Table& Scantable::table( )
[386]915{
[805]916 return table_;
[386]917}
918
[896]919std::string Scantable::getPolType() const
920{
921 return table_.keywordSet().asString("POLTYPE");
922}
923
[805]924void Scantable::unsetSelection()
[380]925{
[805]926 table_ = originalTable_;
[847]927 attach();
[805]928 selector_.reset();
[380]929}
[386]930
[805]931void Scantable::setSelection( const STSelector& selection )
[430]932{
[805]933 Table tab = const_cast<STSelector&>(selection).apply(originalTable_);
934 if ( tab.nrow() == 0 ) {
935 throw(AipsError("Selection contains no data. Not applying it."));
936 }
937 table_ = tab;
[847]938 attach();
[805]939 selector_ = selection;
[430]940}
941
[837]942std::string Scantable::summary( bool verbose )
[447]943{
[805]944 // Format header info
945 ostringstream oss;
946 oss << endl;
947 oss << asap::SEPERATOR << endl;
948 oss << " Scan Table Summary" << endl;
949 oss << asap::SEPERATOR << endl;
950 oss.flags(std::ios_base::left);
951 oss << setw(15) << "Beams:" << setw(4) << nbeam() << endl
952 << setw(15) << "IFs:" << setw(4) << nif() << endl
[896]953 << setw(15) << "Polarisations:" << setw(4) << npol()
954 << "(" << getPolType() << ")" << endl
[1694]955 << setw(15) << "Channels:" << nchan() << endl;
[805]956 String tmp;
[860]957 oss << setw(15) << "Observer:"
958 << table_.keywordSet().asString("Observer") << endl;
[805]959 oss << setw(15) << "Obs Date:" << getTime(-1,true) << endl;
960 table_.keywordSet().get("Project", tmp);
961 oss << setw(15) << "Project:" << tmp << endl;
962 table_.keywordSet().get("Obstype", tmp);
963 oss << setw(15) << "Obs. Type:" << tmp << endl;
964 table_.keywordSet().get("AntennaName", tmp);
965 oss << setw(15) << "Antenna Name:" << tmp << endl;
966 table_.keywordSet().get("FluxUnit", tmp);
967 oss << setw(15) << "Flux Unit:" << tmp << endl;
[1819]968 //Vector<Double> vec(moleculeTable_.getRestFrequencies());
969 int nid = moleculeTable_.nrow();
970 Bool firstline = True;
[805]971 oss << setw(15) << "Rest Freqs:";
[1819]972 for (int i=0; i<nid; i++) {
973 Table t = table_(table_.col("MOLECULE_ID") == i);
974 if (t.nrow() > 0) {
975 Vector<Double> vec(moleculeTable_.getRestFrequency(i));
976 if (vec.nelements() > 0) {
977 if (firstline) {
978 oss << setprecision(10) << vec << " [Hz]" << endl;
979 firstline=False;
980 }
981 else{
982 oss << setw(15)<<" " << setprecision(10) << vec << " [Hz]" << endl;
983 }
984 } else {
985 oss << "none" << endl;
986 }
987 }
[805]988 }
[941]989
990 oss << setw(15) << "Abcissa:" << getAbcissaLabel(0) << endl;
[805]991 oss << selector_.print() << endl;
992 oss << endl;
993 // main table
994 String dirtype = "Position ("
[987]995 + getDirectionRefString()
[805]996 + ")";
[941]997 oss << setw(5) << "Scan" << setw(15) << "Source"
[2005]998 << setw(10) << "Time" << setw(18) << "Integration"
999 << setw(15) << "Source Type" << endl;
[941]1000 oss << setw(5) << "" << setw(5) << "Beam" << setw(3) << "" << dirtype << endl;
[1694]1001 oss << setw(10) << "" << setw(3) << "IF" << setw(3) << ""
[805]1002 << setw(8) << "Frame" << setw(16)
[1694]1003 << "RefVal" << setw(10) << "RefPix" << setw(12) << "Increment"
1004 << setw(7) << "Channels"
1005 << endl;
[805]1006 oss << asap::SEPERATOR << endl;
1007 TableIterator iter(table_, "SCANNO");
1008 while (!iter.pastEnd()) {
1009 Table subt = iter.table();
1010 ROTableRow row(subt);
1011 MEpoch::ROScalarColumn timeCol(subt,"TIME");
1012 const TableRecord& rec = row.get(0);
1013 oss << setw(4) << std::right << rec.asuInt("SCANNO")
1014 << std::left << setw(1) << ""
1015 << setw(15) << rec.asString("SRCNAME")
1016 << setw(10) << formatTime(timeCol(0), false);
1017 // count the cycles in the scan
1018 TableIterator cyciter(subt, "CYCLENO");
1019 int nint = 0;
1020 while (!cyciter.pastEnd()) {
1021 ++nint;
1022 ++cyciter;
1023 }
1024 oss << setw(3) << std::right << nint << setw(3) << " x " << std::left
[2005]1025 << setw(11) << formatSec(rec.asFloat("INTERVAL")) << setw(1) << ""
1026 << setw(15) << SrcType::getName(rec.asInt("SRCTYPE")) << endl;
[447]1027
[805]1028 TableIterator biter(subt, "BEAMNO");
1029 while (!biter.pastEnd()) {
1030 Table bsubt = biter.table();
1031 ROTableRow brow(bsubt);
1032 const TableRecord& brec = brow.get(0);
[1000]1033 uInt row0 = bsubt.rowNumbers(table_)[0];
[941]1034 oss << setw(5) << "" << setw(4) << std::right << brec.asuInt("BEAMNO")<< std::left;
[987]1035 oss << setw(4) << "" << formatDirection(getDirection(row0)) << endl;
[805]1036 TableIterator iiter(bsubt, "IFNO");
1037 while (!iiter.pastEnd()) {
1038 Table isubt = iiter.table();
1039 ROTableRow irow(isubt);
1040 const TableRecord& irec = irow.get(0);
[1694]1041 oss << setw(9) << "";
[941]1042 oss << setw(3) << std::right << irec.asuInt("IFNO") << std::left
[1694]1043 << setw(1) << "" << frequencies().print(irec.asuInt("FREQ_ID"))
1044 << setw(3) << "" << nchan(irec.asuInt("IFNO"))
[1375]1045 << endl;
[447]1046
[805]1047 ++iiter;
1048 }
1049 ++biter;
1050 }
1051 ++iter;
[447]1052 }
[805]1053 /// @todo implement verbose mode
1054 return String(oss);
[447]1055}
1056
[1947]1057// std::string Scantable::getTime(int whichrow, bool showdate) const
1058// {
1059// MEpoch::ROScalarColumn timeCol(table_, "TIME");
1060// MEpoch me;
1061// if (whichrow > -1) {
1062// me = timeCol(uInt(whichrow));
1063// } else {
1064// Double tm;
1065// table_.keywordSet().get("UTC",tm);
1066// me = MEpoch(MVEpoch(tm));
1067// }
1068// return formatTime(me, showdate);
1069// }
1070
1071std::string Scantable::getTime(int whichrow, bool showdate, uInt prec) const
[777]1072{
[805]1073 MEpoch me;
[1947]1074 me = getEpoch(whichrow);
1075 return formatTime(me, showdate, prec);
[777]1076}
[805]1077
[1411]1078MEpoch Scantable::getEpoch(int whichrow) const
1079{
1080 if (whichrow > -1) {
1081 return timeCol_(uInt(whichrow));
1082 } else {
1083 Double tm;
1084 table_.keywordSet().get("UTC",tm);
[1598]1085 return MEpoch(MVEpoch(tm));
[1411]1086 }
1087}
1088
[1068]1089std::string Scantable::getDirectionString(int whichrow) const
1090{
1091 return formatDirection(getDirection(uInt(whichrow)));
1092}
1093
[1598]1094
1095SpectralCoordinate Scantable::getSpectralCoordinate(int whichrow) const {
1096 const MPosition& mp = getAntennaPosition();
1097 const MDirection& md = getDirection(whichrow);
1098 const MEpoch& me = timeCol_(whichrow);
[1819]1099 //Double rf = moleculeTable_.getRestFrequency(mmolidCol_(whichrow));
1100 Vector<Double> rf = moleculeTable_.getRestFrequency(mmolidCol_(whichrow));
[1598]1101 return freqTable_.getSpectralCoordinate(md, mp, me, rf,
1102 mfreqidCol_(whichrow));
1103}
1104
[1360]1105std::vector< double > Scantable::getAbcissa( int whichrow ) const
[865]1106{
[1507]1107 if ( whichrow > int(table_.nrow()) ) throw(AipsError("Illegal row number"));
[865]1108 std::vector<double> stlout;
1109 int nchan = specCol_(whichrow).nelements();
1110 String us = freqTable_.getUnitString();
1111 if ( us == "" || us == "pixel" || us == "channel" ) {
1112 for (int i=0; i<nchan; ++i) {
1113 stlout.push_back(double(i));
1114 }
1115 return stlout;
1116 }
[1598]1117 SpectralCoordinate spc = getSpectralCoordinate(whichrow);
[865]1118 Vector<Double> pixel(nchan);
1119 Vector<Double> world;
1120 indgen(pixel);
1121 if ( Unit(us) == Unit("Hz") ) {
1122 for ( int i=0; i < nchan; ++i) {
1123 Double world;
1124 spc.toWorld(world, pixel[i]);
1125 stlout.push_back(double(world));
1126 }
1127 } else if ( Unit(us) == Unit("km/s") ) {
1128 Vector<Double> world;
1129 spc.pixelToVelocity(world, pixel);
1130 world.tovector(stlout);
1131 }
1132 return stlout;
1133}
[1360]1134void Scantable::setDirectionRefString( const std::string & refstr )
[987]1135{
1136 MDirection::Types mdt;
1137 if (refstr != "" && !MDirection::getType(mdt, refstr)) {
1138 throw(AipsError("Illegal Direction frame."));
1139 }
1140 if ( refstr == "" ) {
1141 String defaultstr = MDirection::showType(dirCol_.getMeasRef().getType());
1142 table_.rwKeywordSet().define("DIRECTIONREF", defaultstr);
1143 } else {
1144 table_.rwKeywordSet().define("DIRECTIONREF", String(refstr));
1145 }
1146}
[865]1147
[1360]1148std::string Scantable::getDirectionRefString( ) const
[987]1149{
1150 return table_.keywordSet().asString("DIRECTIONREF");
1151}
1152
1153MDirection Scantable::getDirection(int whichrow ) const
1154{
1155 String usertype = table_.keywordSet().asString("DIRECTIONREF");
1156 String type = MDirection::showType(dirCol_.getMeasRef().getType());
1157 if ( usertype != type ) {
1158 MDirection::Types mdt;
1159 if (!MDirection::getType(mdt, usertype)) {
1160 throw(AipsError("Illegal Direction frame."));
1161 }
1162 return dirCol_.convert(uInt(whichrow), mdt);
1163 } else {
1164 return dirCol_(uInt(whichrow));
1165 }
1166}
1167
[847]1168std::string Scantable::getAbcissaLabel( int whichrow ) const
1169{
[996]1170 if ( whichrow > int(table_.nrow()) ) throw(AipsError("Illegal ro number"));
[847]1171 const MPosition& mp = getAntennaPosition();
[987]1172 const MDirection& md = getDirection(whichrow);
[847]1173 const MEpoch& me = timeCol_(whichrow);
[1819]1174 //const Double& rf = mmolidCol_(whichrow);
1175 const Vector<Double> rf = moleculeTable_.getRestFrequency(mmolidCol_(whichrow));
[847]1176 SpectralCoordinate spc =
1177 freqTable_.getSpectralCoordinate(md, mp, me, rf, mfreqidCol_(whichrow));
1178
1179 String s = "Channel";
1180 Unit u = Unit(freqTable_.getUnitString());
1181 if (u == Unit("km/s")) {
[1170]1182 s = CoordinateUtil::axisLabel(spc, 0, True,True, True);
[847]1183 } else if (u == Unit("Hz")) {
1184 Vector<String> wau(1);wau = u.getName();
1185 spc.setWorldAxisUnits(wau);
[1170]1186 s = CoordinateUtil::axisLabel(spc, 0, True, True, False);
[847]1187 }
1188 return s;
1189
1190}
1191
[1819]1192/**
1193void asap::Scantable::setRestFrequencies( double rf, const std::string& name,
[1170]1194 const std::string& unit )
[1819]1195**/
1196void Scantable::setRestFrequencies( vector<double> rf, const vector<std::string>& name,
1197 const std::string& unit )
1198
[847]1199{
[923]1200 ///@todo lookup in line table to fill in name and formattedname
[847]1201 Unit u(unit);
[1819]1202 //Quantum<Double> urf(rf, u);
1203 Quantum<Vector<Double> >urf(rf, u);
1204 Vector<String> formattedname(0);
1205 //cerr<<"Scantable::setRestFrequnecies="<<urf<<endl;
1206
1207 //uInt id = moleculeTable_.addEntry(urf.getValue("Hz"), name, "");
1208 uInt id = moleculeTable_.addEntry(urf.getValue("Hz"), mathutil::toVectorString(name), formattedname);
[847]1209 TableVector<uInt> tabvec(table_, "MOLECULE_ID");
1210 tabvec = id;
1211}
1212
[1819]1213/**
1214void asap::Scantable::setRestFrequencies( const std::string& name )
[847]1215{
1216 throw(AipsError("setRestFrequencies( const std::string& name ) NYI"));
1217 ///@todo implement
1218}
[1819]1219**/
[2012]1220
[1819]1221void Scantable::setRestFrequencies( const vector<std::string>& name )
1222{
1223 throw(AipsError("setRestFrequencies( const vector<std::string>& name ) NYI"));
1224 ///@todo implement
1225}
[847]1226
[1360]1227std::vector< unsigned int > Scantable::rownumbers( ) const
[852]1228{
1229 std::vector<unsigned int> stlout;
1230 Vector<uInt> vec = table_.rowNumbers();
1231 vec.tovector(stlout);
1232 return stlout;
1233}
1234
[865]1235
[1360]1236Matrix<Float> Scantable::getPolMatrix( uInt whichrow ) const
[896]1237{
1238 ROTableRow row(table_);
1239 const TableRecord& rec = row.get(whichrow);
1240 Table t =
1241 originalTable_( originalTable_.col("SCANNO") == Int(rec.asuInt("SCANNO"))
1242 && originalTable_.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
1243 && originalTable_.col("IFNO") == Int(rec.asuInt("IFNO"))
1244 && originalTable_.col("CYCLENO") == Int(rec.asuInt("CYCLENO")) );
1245 ROArrayColumn<Float> speccol(t, "SPECTRA");
1246 return speccol.getColumn();
1247}
[865]1248
[1360]1249std::vector< std::string > Scantable::columnNames( ) const
[902]1250{
1251 Vector<String> vec = table_.tableDesc().columnNames();
1252 return mathutil::tovectorstring(vec);
1253}
[896]1254
[1360]1255MEpoch::Types Scantable::getTimeReference( ) const
[915]1256{
1257 return MEpoch::castType(timeCol_.getMeasRef().getType());
[972]1258}
[915]1259
[1360]1260void Scantable::addFit( const STFitEntry& fit, int row )
[972]1261{
[1819]1262 //cout << mfitidCol_(uInt(row)) << endl;
1263 LogIO os( LogOrigin( "Scantable", "addFit()", WHERE ) ) ;
1264 os << mfitidCol_(uInt(row)) << LogIO::POST ;
[972]1265 uInt id = fitTable_.addEntry(fit, mfitidCol_(uInt(row)));
1266 mfitidCol_.put(uInt(row), id);
1267}
[915]1268
[1360]1269void Scantable::shift(int npix)
1270{
1271 Vector<uInt> fids(mfreqidCol_.getColumn());
1272 genSort( fids, Sort::Ascending,
1273 Sort::QuickSort|Sort::NoDuplicates );
1274 for (uInt i=0; i<fids.nelements(); ++i) {
[1567]1275 frequencies().shiftRefPix(npix, fids[i]);
[1360]1276 }
1277}
[987]1278
[1819]1279String Scantable::getAntennaName() const
[1391]1280{
1281 String out;
1282 table_.keywordSet().get("AntennaName", out);
[1987]1283 String::size_type pos1 = out.find("@") ;
1284 String::size_type pos2 = out.find("//") ;
1285 if ( pos2 != String::npos )
1286 out = out.substr(pos2+2,pos1) ;
1287 else if ( pos1 != String::npos )
1288 out = out.substr(0,pos1) ;
[1391]1289 return out;
[987]1290}
[1391]1291
[1730]1292int Scantable::checkScanInfo(const std::vector<int>& scanlist) const
[1391]1293{
1294 String tbpath;
1295 int ret = 0;
1296 if ( table_.keywordSet().isDefined("GBT_GO") ) {
1297 table_.keywordSet().get("GBT_GO", tbpath);
1298 Table t(tbpath,Table::Old);
1299 // check each scan if other scan of the pair exist
1300 int nscan = scanlist.size();
1301 for (int i = 0; i < nscan; i++) {
1302 Table subt = t( t.col("SCAN") == scanlist[i]+1 );
1303 if (subt.nrow()==0) {
[1819]1304 //cerr <<"Scan "<<scanlist[i]<<" cannot be found in the scantable."<<endl;
1305 LogIO os( LogOrigin( "Scantable", "checkScanInfo()", WHERE ) ) ;
1306 os <<LogIO::WARN<<"Scan "<<scanlist[i]<<" cannot be found in the scantable."<<LogIO::POST;
[1391]1307 ret = 1;
1308 break;
1309 }
1310 ROTableRow row(subt);
1311 const TableRecord& rec = row.get(0);
1312 int scan1seqn = rec.asuInt("PROCSEQN");
1313 int laston1 = rec.asuInt("LASTON");
1314 if ( rec.asuInt("PROCSIZE")==2 ) {
1315 if ( i < nscan-1 ) {
1316 Table subt2 = t( t.col("SCAN") == scanlist[i+1]+1 );
1317 if ( subt2.nrow() == 0) {
[1819]1318 LogIO os( LogOrigin( "Scantable", "checkScanInfo()", WHERE ) ) ;
1319
1320 //cerr<<"Scan "<<scanlist[i+1]<<" cannot be found in the scantable."<<endl;
1321 os<<LogIO::WARN<<"Scan "<<scanlist[i+1]<<" cannot be found in the scantable."<<LogIO::POST;
[1391]1322 ret = 1;
1323 break;
1324 }
1325 ROTableRow row2(subt2);
1326 const TableRecord& rec2 = row2.get(0);
1327 int scan2seqn = rec2.asuInt("PROCSEQN");
1328 int laston2 = rec2.asuInt("LASTON");
1329 if (scan1seqn == 1 && scan2seqn == 2) {
1330 if (laston1 == laston2) {
[1819]1331 LogIO os( LogOrigin( "Scantable", "checkScanInfo()", WHERE ) ) ;
1332 //cerr<<"A valid scan pair ["<<scanlist[i]<<","<<scanlist[i+1]<<"]"<<endl;
1333 os<<"A valid scan pair ["<<scanlist[i]<<","<<scanlist[i+1]<<"]"<<LogIO::POST;
[1391]1334 i +=1;
1335 }
1336 else {
[1819]1337 LogIO os( LogOrigin( "Scantable", "checkScanInfo()", WHERE ) ) ;
1338 //cerr<<"Incorrect scan pair ["<<scanlist[i]<<","<<scanlist[i+1]<<"]"<<endl;
1339 os<<LogIO::WARN<<"Incorrect scan pair ["<<scanlist[i]<<","<<scanlist[i+1]<<"]"<<LogIO::POST;
[1391]1340 }
1341 }
1342 else if (scan1seqn==2 && scan2seqn == 1) {
1343 if (laston1 == laston2) {
[1819]1344 LogIO os( LogOrigin( "Scantable", "checkScanInfo()", WHERE ) ) ;
1345 //cerr<<"["<<scanlist[i]<<","<<scanlist[i+1]<<"] is a valid scan pair but in incorrect order."<<endl;
1346 os<<LogIO::WARN<<"["<<scanlist[i]<<","<<scanlist[i+1]<<"] is a valid scan pair but in incorrect order."<<LogIO::POST;
[1391]1347 ret = 1;
1348 break;
1349 }
1350 }
1351 else {
[1819]1352 LogIO os( LogOrigin( "Scantable", "checkScanInfo()", WHERE ) ) ;
1353 //cerr<<"The other scan for "<<scanlist[i]<<" appears to be missing. Check the input scan numbers."<<endl;
1354 os<<LogIO::WARN<<"The other scan for "<<scanlist[i]<<" appears to be missing. Check the input scan numbers."<<LogIO::POST;
[1391]1355 ret = 1;
1356 break;
1357 }
1358 }
1359 }
1360 else {
[1819]1361 LogIO os( LogOrigin( "Scantable", "checkScanInfo()", WHERE ) ) ;
1362 //cerr<<"The scan does not appear to be standard obsevation."<<endl;
1363 os<<LogIO::WARN<<"The scan does not appear to be standard obsevation."<<LogIO::POST;
[1391]1364 }
1365 //if ( i >= nscan ) break;
1366 }
1367 }
1368 else {
[1819]1369 LogIO os( LogOrigin( "Scantable", "checkScanInfo()", WHERE ) ) ;
1370 //cerr<<"No reference to GBT_GO table."<<endl;
1371 os<<LogIO::WARN<<"No reference to GBT_GO table."<<LogIO::POST;
[1391]1372 ret = 1;
1373 }
1374 return ret;
1375}
1376
[1730]1377std::vector<double> Scantable::getDirectionVector(int whichrow) const
[1391]1378{
1379 Vector<Double> Dir = dirCol_(whichrow).getAngle("rad").getValue();
1380 std::vector<double> dir;
1381 Dir.tovector(dir);
1382 return dir;
1383}
1384
[1819]1385void asap::Scantable::reshapeSpectrum( int nmin, int nmax )
1386 throw( casa::AipsError )
1387{
1388 // assumed that all rows have same nChan
1389 Vector<Float> arr = specCol_( 0 ) ;
1390 int nChan = arr.nelements() ;
1391
1392 // if nmin < 0 or nmax < 0, nothing to do
1393 if ( nmin < 0 ) {
1394 throw( casa::indexError<int>( nmin, "asap::Scantable::reshapeSpectrum: Invalid range. Negative index is specified." ) ) ;
1395 }
1396 if ( nmax < 0 ) {
1397 throw( casa::indexError<int>( nmax, "asap::Scantable::reshapeSpectrum: Invalid range. Negative index is specified." ) ) ;
1398 }
1399
1400 // if nmin > nmax, exchange values
1401 if ( nmin > nmax ) {
1402 int tmp = nmax ;
1403 nmax = nmin ;
1404 nmin = tmp ;
1405 LogIO os( LogOrigin( "Scantable", "reshapeSpectrum()", WHERE ) ) ;
1406 os << "Swap values. Applied range is ["
1407 << nmin << ", " << nmax << "]" << LogIO::POST ;
1408 }
1409
1410 // if nmin exceeds nChan, nothing to do
1411 if ( nmin >= nChan ) {
1412 throw( casa::indexError<int>( nmin, "asap::Scantable::reshapeSpectrum: Invalid range. Specified minimum exceeds nChan." ) ) ;
1413 }
1414
1415 // if nmax exceeds nChan, reset nmax to nChan
1416 if ( nmax >= nChan ) {
1417 if ( nmin == 0 ) {
1418 // nothing to do
1419 LogIO os( LogOrigin( "Scantable", "reshapeSpectrum()", WHERE ) ) ;
1420 os << "Whole range is selected. Nothing to do." << LogIO::POST ;
1421 return ;
1422 }
1423 else {
1424 LogIO os( LogOrigin( "Scantable", "reshapeSpectrum()", WHERE ) ) ;
1425 os << "Specified maximum exceeds nChan. Applied range is ["
1426 << nmin << ", " << nChan-1 << "]." << LogIO::POST ;
1427 nmax = nChan - 1 ;
1428 }
1429 }
1430
1431 // reshape specCol_ and flagCol_
1432 for ( int irow = 0 ; irow < nrow() ; irow++ ) {
1433 reshapeSpectrum( nmin, nmax, irow ) ;
1434 }
1435
1436 // update FREQUENCIES subtable
1437 Double refpix ;
1438 Double refval ;
1439 Double increment ;
1440 int freqnrow = freqTable_.table().nrow() ;
1441 Vector<uInt> oldId( freqnrow ) ;
1442 Vector<uInt> newId( freqnrow ) ;
1443 for ( int irow = 0 ; irow < freqnrow ; irow++ ) {
1444 freqTable_.getEntry( refpix, refval, increment, irow ) ;
1445 /***
1446 * need to shift refpix to nmin
1447 * note that channel nmin in old index will be channel 0 in new one
1448 ***/
1449 refval = refval - ( refpix - nmin ) * increment ;
1450 refpix = 0 ;
1451 freqTable_.setEntry( refpix, refval, increment, irow ) ;
1452 }
1453
1454 // update nchan
1455 int newsize = nmax - nmin + 1 ;
1456 table_.rwKeywordSet().define( "nChan", newsize ) ;
1457
1458 // update bandwidth
1459 // assumed all spectra in the scantable have same bandwidth
1460 table_.rwKeywordSet().define( "Bandwidth", increment * newsize ) ;
1461
1462 return ;
1463}
1464
1465void asap::Scantable::reshapeSpectrum( int nmin, int nmax, int irow )
1466{
1467 // reshape specCol_ and flagCol_
1468 Vector<Float> oldspec = specCol_( irow ) ;
1469 Vector<uChar> oldflag = flagsCol_( irow ) ;
1470 uInt newsize = nmax - nmin + 1 ;
1471 specCol_.put( irow, oldspec( Slice( nmin, newsize, 1 ) ) ) ;
1472 flagsCol_.put( irow, oldflag( Slice( nmin, newsize, 1 ) ) ) ;
1473
1474 return ;
1475}
1476
1477void asap::Scantable::regridChannel( int nChan, double dnu )
1478{
1479 LogIO os( LogOrigin( "Scantable", "regridChannel()", WHERE ) ) ;
1480 os << "Regrid abcissa with channel number " << nChan << " and spectral resoultion " << dnu << "Hz." << LogIO::POST ;
1481 // assumed that all rows have same nChan
1482 Vector<Float> arr = specCol_( 0 ) ;
1483 int oldsize = arr.nelements() ;
1484
1485 // if oldsize == nChan, nothing to do
1486 if ( oldsize == nChan ) {
1487 os << "Specified channel number is same as current one. Nothing to do." << LogIO::POST ;
1488 return ;
1489 }
1490
1491 // if oldChan < nChan, unphysical operation
1492 if ( oldsize < nChan ) {
1493 os << "Unphysical operation. Nothing to do." << LogIO::POST ;
1494 return ;
1495 }
1496
1497 // change channel number for specCol_ and flagCol_
1498 Vector<Float> newspec( nChan, 0 ) ;
1499 Vector<uChar> newflag( nChan, false ) ;
1500 vector<string> coordinfo = getCoordInfo() ;
1501 string oldinfo = coordinfo[0] ;
1502 coordinfo[0] = "Hz" ;
1503 setCoordInfo( coordinfo ) ;
1504 for ( int irow = 0 ; irow < nrow() ; irow++ ) {
1505 regridChannel( nChan, dnu, irow ) ;
1506 }
1507 coordinfo[0] = oldinfo ;
1508 setCoordInfo( coordinfo ) ;
1509
1510
1511 // NOTE: this method does not update metadata such as
1512 // FREQUENCIES subtable, nChan, Bandwidth, etc.
1513
1514 return ;
1515}
1516
1517void asap::Scantable::regridChannel( int nChan, double dnu, int irow )
1518{
1519 // logging
1520 //ofstream ofs( "average.log", std::ios::out | std::ios::app ) ;
1521 //ofs << "IFNO = " << getIF( irow ) << " irow = " << irow << endl ;
1522
1523 Vector<Float> oldspec = specCol_( irow ) ;
1524 Vector<uChar> oldflag = flagsCol_( irow ) ;
1525 Vector<Float> newspec( nChan, 0 ) ;
1526 Vector<uChar> newflag( nChan, false ) ;
1527
1528 // regrid
1529 vector<double> abcissa = getAbcissa( irow ) ;
1530 int oldsize = abcissa.size() ;
1531 double olddnu = abcissa[1] - abcissa[0] ;
1532 //int refChan = 0 ;
1533 //double frac = 0.0 ;
1534 //double wedge = 0.0 ;
1535 //double pile = 0.0 ;
1536 int ichan = 0 ;
1537 double wsum = 0.0 ;
1538 Vector<Float> z( nChan ) ;
1539 z[0] = abcissa[0] - 0.5 * olddnu + 0.5 * dnu ;
1540 for ( int ii = 1 ; ii < nChan ; ii++ )
1541 z[ii] = z[ii-1] + dnu ;
1542 Vector<Float> zi( nChan+1 ) ;
1543 Vector<Float> yi( oldsize + 1 ) ;
1544 zi[0] = z[0] - 0.5 * dnu ;
1545 zi[1] = z[0] + 0.5 * dnu ;
1546 for ( int ii = 2 ; ii < nChan ; ii++ )
1547 zi[ii] = zi[ii-1] + dnu ;
1548 zi[nChan] = z[nChan-1] + 0.5 * dnu ;
1549 yi[0] = abcissa[0] - 0.5 * olddnu ;
1550 yi[1] = abcissa[1] + 0.5 * olddnu ;
1551 for ( int ii = 2 ; ii < oldsize ; ii++ )
1552 yi[ii] = abcissa[ii-1] + olddnu ;
1553 yi[oldsize] = abcissa[oldsize-1] + 0.5 * olddnu ;
1554 if ( dnu > 0.0 ) {
1555 for ( int ii = 0 ; ii < nChan ; ii++ ) {
1556 double zl = zi[ii] ;
1557 double zr = zi[ii+1] ;
1558 for ( int j = ichan ; j < oldsize ; j++ ) {
1559 double yl = yi[j] ;
1560 double yr = yi[j+1] ;
1561 if ( yl <= zl ) {
1562 if ( yr <= zl ) {
1563 continue ;
1564 }
1565 else if ( yr <= zr ) {
1566 newspec[ii] += oldspec[j] * ( yr - zl ) ;
1567 newflag[ii] = newflag[ii] || oldflag[j] ;
1568 wsum += ( yr - zl ) ;
1569 }
1570 else {
1571 newspec[ii] += oldspec[j] * dnu ;
1572 newflag[ii] = newflag[ii] || oldflag[j] ;
1573 wsum += dnu ;
1574 ichan = j ;
1575 break ;
1576 }
1577 }
1578 else if ( yl < zr ) {
1579 if ( yr <= zr ) {
1580 newspec[ii] += oldspec[j] * ( yr - yl ) ;
1581 newflag[ii] = newflag[ii] || oldflag[j] ;
1582 wsum += ( yr - yl ) ;
1583 }
1584 else {
1585 newspec[ii] += oldspec[j] * ( zr - yl ) ;
1586 newflag[ii] = newflag[ii] || oldflag[j] ;
1587 wsum += ( zr - yl ) ;
1588 ichan = j ;
1589 break ;
1590 }
1591 }
1592 else {
1593 ichan = j - 1 ;
1594 break ;
1595 }
1596 }
1597 newspec[ii] /= wsum ;
1598 wsum = 0.0 ;
1599 }
1600 }
1601 else if ( dnu < 0.0 ) {
1602 for ( int ii = 0 ; ii < nChan ; ii++ ) {
1603 double zl = zi[ii] ;
1604 double zr = zi[ii+1] ;
1605 for ( int j = ichan ; j < oldsize ; j++ ) {
1606 double yl = yi[j] ;
1607 double yr = yi[j+1] ;
1608 if ( yl >= zl ) {
1609 if ( yr >= zl ) {
1610 continue ;
1611 }
1612 else if ( yr >= zr ) {
1613 newspec[ii] += oldspec[j] * abs( yr - zl ) ;
1614 newflag[ii] = newflag[ii] || oldflag[j] ;
1615 wsum += abs( yr - zl ) ;
1616 }
1617 else {
1618 newspec[ii] += oldspec[j] * abs( dnu ) ;
1619 newflag[ii] = newflag[ii] || oldflag[j] ;
1620 wsum += abs( dnu ) ;
1621 ichan = j ;
1622 break ;
1623 }
1624 }
1625 else if ( yl > zr ) {
1626 if ( yr >= zr ) {
1627 newspec[ii] += oldspec[j] * abs( yr - yl ) ;
1628 newflag[ii] = newflag[ii] || oldflag[j] ;
1629 wsum += abs( yr - yl ) ;
1630 }
1631 else {
1632 newspec[ii] += oldspec[j] * abs( zr - yl ) ;
1633 newflag[ii] = newflag[ii] || oldflag[j] ;
1634 wsum += abs( zr - yl ) ;
1635 ichan = j ;
1636 break ;
1637 }
1638 }
1639 else {
1640 ichan = j - 1 ;
1641 break ;
1642 }
1643 }
1644 newspec[ii] /= wsum ;
1645 wsum = 0.0 ;
1646 }
1647 }
1648// * ichan = 0
1649// ***/
1650// //ofs << "olddnu = " << olddnu << ", dnu = " << dnu << endl ;
1651// pile += dnu ;
1652// wedge = olddnu * ( refChan + 1 ) ;
1653// while ( wedge < pile ) {
1654// newspec[0] += olddnu * oldspec[refChan] ;
1655// newflag[0] = newflag[0] || oldflag[refChan] ;
1656// //ofs << "channel " << refChan << " is included in new channel 0" << endl ;
1657// refChan++ ;
1658// wedge += olddnu ;
1659// wsum += olddnu ;
1660// //ofs << "newspec[0] = " << newspec[0] << " wsum = " << wsum << endl ;
1661// }
1662// frac = ( wedge - pile ) / olddnu ;
1663// wsum += ( 1.0 - frac ) * olddnu ;
1664// newspec[0] += ( 1.0 - frac ) * olddnu * oldspec[refChan] ;
1665// newflag[0] = newflag[0] || oldflag[refChan] ;
1666// //ofs << "channel " << refChan << " is partly included in new channel 0" << " with fraction of " << ( 1.0 - frac ) << endl ;
1667// //ofs << "newspec[0] = " << newspec[0] << " wsum = " << wsum << endl ;
1668// newspec[0] /= wsum ;
1669// //ofs << "newspec[0] = " << newspec[0] << endl ;
1670// //ofs << "wedge = " << wedge << ", pile = " << pile << endl ;
1671
1672// /***
1673// * ichan = 1 - nChan-2
1674// ***/
1675// for ( int ichan = 1 ; ichan < nChan - 1 ; ichan++ ) {
1676// pile += dnu ;
1677// newspec[ichan] += frac * olddnu * oldspec[refChan] ;
1678// newflag[ichan] = newflag[ichan] || oldflag[refChan] ;
1679// //ofs << "channel " << refChan << " is partly included in new channel " << ichan << " with fraction of " << frac << endl ;
1680// refChan++ ;
1681// wedge += olddnu ;
1682// wsum = frac * olddnu ;
1683// //ofs << "newspec[" << ichan << "] = " << newspec[ichan] << " wsum = " << wsum << endl ;
1684// while ( wedge < pile ) {
1685// newspec[ichan] += olddnu * oldspec[refChan] ;
1686// newflag[ichan] = newflag[ichan] || oldflag[refChan] ;
1687// //ofs << "channel " << refChan << " is included in new channel " << ichan << endl ;
1688// refChan++ ;
1689// wedge += olddnu ;
1690// wsum += olddnu ;
1691// //ofs << "newspec[" << ichan << "] = " << newspec[ichan] << " wsum = " << wsum << endl ;
1692// }
1693// frac = ( wedge - pile ) / olddnu ;
1694// wsum += ( 1.0 - frac ) * olddnu ;
1695// newspec[ichan] += ( 1.0 - frac ) * olddnu * oldspec[refChan] ;
1696// newflag[ichan] = newflag[ichan] || oldflag[refChan] ;
1697// //ofs << "channel " << refChan << " is partly included in new channel " << ichan << " with fraction of " << ( 1.0 - frac ) << endl ;
1698// //ofs << "wedge = " << wedge << ", pile = " << pile << endl ;
1699// //ofs << "newspec[" << ichan << "] = " << newspec[ichan] << " wsum = " << wsum << endl ;
1700// newspec[ichan] /= wsum ;
1701// //ofs << "newspec[" << ichan << "] = " << newspec[ichan] << endl ;
1702// }
1703
1704// /***
1705// * ichan = nChan-1
1706// ***/
1707// // NOTE: Assumed that all spectra have the same bandwidth
1708// pile += dnu ;
1709// newspec[nChan-1] += frac * olddnu * oldspec[refChan] ;
1710// newflag[nChan-1] = newflag[nChan-1] || oldflag[refChan] ;
1711// //ofs << "channel " << refChan << " is partly included in new channel " << nChan-1 << " with fraction of " << frac << endl ;
1712// refChan++ ;
1713// wedge += olddnu ;
1714// wsum = frac * olddnu ;
1715// //ofs << "newspec[" << nChan - 1 << "] = " << newspec[nChan-1] << " wsum = " << wsum << endl ;
1716// for ( int jchan = refChan ; jchan < oldsize ; jchan++ ) {
1717// newspec[nChan-1] += olddnu * oldspec[jchan] ;
1718// newflag[nChan-1] = newflag[nChan-1] || oldflag[jchan] ;
1719// wsum += olddnu ;
1720// //ofs << "channel " << jchan << " is included in new channel " << nChan-1 << " with fraction of " << frac << endl ;
1721// //ofs << "newspec[" << nChan - 1 << "] = " << newspec[nChan-1] << " wsum = " << wsum << endl ;
1722// }
1723// //ofs << "wedge = " << wedge << ", pile = " << pile << endl ;
1724// //ofs << "newspec[" << nChan - 1 << "] = " << newspec[nChan-1] << " wsum = " << wsum << endl ;
1725// newspec[nChan-1] /= wsum ;
1726// //ofs << "newspec[" << nChan - 1 << "] = " << newspec[nChan-1] << endl ;
1727
1728// specCol_.put( irow, newspec ) ;
1729// flagsCol_.put( irow, newflag ) ;
1730
1731// // ofs.close() ;
1732
1733
1734 return ;
1735}
1736
[1730]1737std::vector<float> Scantable::getWeather(int whichrow) const
1738{
1739 std::vector<float> out(5);
1740 //Float temperature, pressure, humidity, windspeed, windaz;
1741 weatherTable_.getEntry(out[0], out[1], out[2], out[3], out[4],
1742 mweatheridCol_(uInt(whichrow)));
1743
1744
1745 return out;
[1391]1746}
[1730]1747
[1907]1748bool Scantable::getFlagtraFast(int whichrow)
1749{
1750 uChar flag;
1751 Vector<uChar> flags;
1752 flagsCol_.get(uInt(whichrow), flags);
[2012]1753 flag = flags[0];
1754 for (int i = 1; i < flags.size(); ++i) {
1755 flag &= flags[i];
1756 }
1757 return ((flag >> 7) == 1);
1758}
1759
1760void Scantable::cubicSplineBaseline(const std::vector<bool>& mask, int nPiece, float thresClip, int nIterClip, bool outLogger, const std::string& blfile) {
1761 ofstream ofs;
1762 String coordInfo;
1763 bool hasSameNchan;
1764 int firstIF;
1765 bool outTextFile = false;
1766
1767 if (blfile != "") {
1768 ofs.open(blfile.c_str(), ios::out | ios::app);
1769 if (ofs) outTextFile = true;
1770 }
1771
1772 if (outLogger || outTextFile) {
1773 coordInfo = getCoordInfo()[0];
1774 if (coordInfo == "") coordInfo = "channel";
1775 hasSameNchan = hasSameNchanOverIFs();
1776 firstIF = getIF(0);
1777 }
1778
1779 //Fitter fitter = Fitter();
1780 //fitter.setExpression("cspline", nPiece, thresClip, nIterClip);
1781
1782 int nRow = nrow();
1783 std::vector<bool> chanMask;
1784
1785 for (int whichrow = 0; whichrow < nRow; ++whichrow) {
1786
1787 chanMask = getCompositeChanMask(whichrow, mask);
1788 //fitBaseline(chanMask, whichrow, fitter);
1789 //setSpectrum(fitter.getResidual(), whichrow);
1790 std::vector<int> pieceRanges;
1791 std::vector<float> params;
1792 std::vector<float> res = doCubicSplineFitting(getSpectrum(whichrow), chanMask, pieceRanges, params, nPiece, thresClip, nIterClip);
1793 setSpectrum(res, whichrow);
1794
1795 if (outLogger || outTextFile) {
1796 std::vector<bool> fixed;
1797 fixed.clear();
1798 float rms = getRms(chanMask, whichrow);
1799 String masklist = getMaskRangeList(chanMask, whichrow, coordInfo, hasSameNchan, firstIF, true);
1800
1801 if (outLogger) {
1802 LogIO ols(LogOrigin("Scantable", "cubicSplineBaseline()", WHERE));
1803 ols << formatPiecewiseBaselineParams(pieceRanges, params, fixed, rms, masklist, whichrow, false) << LogIO::POST ;
1804 }
1805 if (outTextFile) {
1806 ofs << formatPiecewiseBaselineParams(pieceRanges, params, fixed, rms, masklist, whichrow, true) << flush;
1807 }
[1907]1808 }
[2012]1809
1810 }
1811
1812 if (outTextFile) ofs.close();
1813}
1814
1815
1816void Scantable::autoCubicSplineBaseline(const std::vector<bool>& mask, int nPiece, float thresClip, int nIterClip, const std::vector<int>& edge, float threshold, int chanAvgLimit, bool outLogger, const std::string& blfile)
1817{
1818 ofstream ofs;
1819 String coordInfo;
1820 bool hasSameNchan;
1821 int firstIF;
1822 bool outTextFile = false;
1823
1824 if (blfile != "") {
1825 ofs.open(blfile.c_str(), ios::out | ios::app);
1826 if (ofs) outTextFile = true;
1827 }
1828
1829 if (outLogger || outTextFile) {
1830 coordInfo = getCoordInfo()[0];
1831 if (coordInfo == "") coordInfo = "channel";
1832 hasSameNchan = hasSameNchanOverIFs();
1833 firstIF = getIF(0);
1834 }
1835
1836 //Fitter fitter = Fitter();
1837 //fitter.setExpression("cspline", nPiece, thresClip, nIterClip);
1838
1839 int nRow = nrow();
1840 std::vector<bool> chanMask;
1841 int minEdgeSize = getIFNos().size()*2;
1842 STLineFinder lineFinder = STLineFinder();
1843 lineFinder.setOptions(threshold, 3, chanAvgLimit);
1844
1845 for (int whichrow = 0; whichrow < nRow; ++whichrow) {
1846
1847 //-------------------------------------------------------
1848 //chanMask = getCompositeChanMask(whichrow, mask, edge, minEdgeSize, lineFinder);
1849 //-------------------------------------------------------
1850 int edgeSize = edge.size();
1851 std::vector<int> currentEdge;
1852 if (edgeSize >= 2) {
1853 int idx = 0;
1854 if (edgeSize > 2) {
1855 if (edgeSize < minEdgeSize) {
1856 throw(AipsError("Length of edge element info is less than that of IFs"));
1857 }
1858 idx = 2 * getIF(whichrow);
1859 }
1860 currentEdge.push_back(edge[idx]);
1861 currentEdge.push_back(edge[idx+1]);
1862 } else {
1863 throw(AipsError("Wrong length of edge element"));
[1907]1864 }
[2012]1865 lineFinder.setData(getSpectrum(whichrow));
1866 lineFinder.findLines(getCompositeChanMask(whichrow, mask), currentEdge, whichrow);
1867 chanMask = lineFinder.getMask();
1868 //-------------------------------------------------------
1869
1870
1871 //fitBaseline(chanMask, whichrow, fitter);
1872 //setSpectrum(fitter.getResidual(), whichrow);
1873 std::vector<int> pieceRanges;
1874 std::vector<float> params;
1875 std::vector<float> res = doCubicSplineFitting(getSpectrum(whichrow), chanMask, pieceRanges, params, nPiece, thresClip, nIterClip);
1876 setSpectrum(res, whichrow);
1877
1878 if (outLogger || outTextFile) {
1879 std::vector<bool> fixed;
1880 fixed.clear();
1881 float rms = getRms(chanMask, whichrow);
1882 String masklist = getMaskRangeList(chanMask, whichrow, coordInfo, hasSameNchan, firstIF, true);
1883
1884 if (outLogger) {
1885 LogIO ols(LogOrigin("Scantable", "autoCubicSplineBaseline()", WHERE));
1886 ols << formatPiecewiseBaselineParams(pieceRanges, params, fixed, rms, masklist, whichrow, false) << LogIO::POST ;
1887 }
1888 if (outTextFile) {
1889 ofs << formatPiecewiseBaselineParams(pieceRanges, params, fixed, rms, masklist, whichrow, true) << flush;
1890 }
1891 }
1892
1893 }
1894
1895 if (outTextFile) ofs.close();
[1730]1896}
[1907]1897
[2012]1898
1899std::vector<float> Scantable::doCubicSplineFitting(const std::vector<float>& data, const std::vector<bool>& mask, std::vector<int>& sectionRanges, std::vector<float>& params, int nPiece, float thresClip, int nIterClip) {
1900 if (nPiece < 1) {
1901 throw(AipsError("wrong number of the sections for fitting"));
1902 }
1903 if (data.size() != mask.size()) {
1904 throw(AipsError("data and mask have different size"));
1905 }
1906
1907 int nChan = data.size();
1908 std::vector<int> maskArray;
1909 std::vector<int> x;
1910 for (int i = 0; i < nChan; ++i) {
1911 maskArray.push_back(mask[i] ? 1 : 0);
1912 if (mask[i]) {
1913 x.push_back(i);
1914 }
1915 }
1916
1917 int nData = x.size();
1918 int nElement = (int)(floor(floor((double)(nData/nPiece))+0.5));
1919
1920 std::vector<double> sectionList0, sectionList1, sectionListR;
1921 sectionList0.push_back((double)x[0]);
1922 sectionRanges.clear();
1923 sectionRanges.push_back(x[0]);
1924 for (int i = 1; i < nPiece; ++i) {
1925 double valX = (double)x[nElement*i];
1926 sectionList0.push_back(valX);
1927 sectionList1.push_back(valX);
1928 sectionListR.push_back(1.0/valX);
1929
1930 sectionRanges.push_back(x[nElement*i]-1);
1931 sectionRanges.push_back(x[nElement*i]);
1932 }
1933 sectionList1.push_back((double)(x[x.size()-1]+1));
1934 sectionRanges.push_back(x[x.size()-1]);
1935
1936 std::vector<double> x1, x2, x3, z1, x1z1, x2z1, x3z1, r1;
1937 for (int i = 0; i < nChan; ++i) {
1938 x1.push_back((double)i);
1939 x2.push_back((double)(i*i));
1940 x3.push_back((double)(i*i*i));
1941 z1.push_back((double)data[i]);
1942 x1z1.push_back(((double)i)*(double)data[i]);
1943 x2z1.push_back(((double)(i*i))*(double)data[i]);
1944 x3z1.push_back(((double)(i*i*i))*(double)data[i]);
1945 r1.push_back(0.0);
1946 }
1947
1948 int currentNData = nData;
1949 int nDOF = nPiece + 3; //number of parameters to solve, namely, 4+(nPiece-1).
1950
1951 for (int nClip = 0; nClip < nIterClip+1; ++nClip) {
1952 //xMatrix : horizontal concatenation of the least-sq. matrix (left) and an
1953 //identity matrix (right).
1954 //the right part is used to calculate the inverse matrix of the left part.
1955 double xMatrix[nDOF][2*nDOF];
1956 double zMatrix[nDOF];
1957 for (int i = 0; i < nDOF; ++i) {
1958 for (int j = 0; j < 2*nDOF; ++j) {
1959 xMatrix[i][j] = 0.0;
1960 }
1961 xMatrix[i][nDOF+i] = 1.0;
1962 zMatrix[i] = 0.0;
1963 }
1964
1965 for (int n = 0; n < nPiece; ++n) {
1966 for (int i = sectionList0[n]; i < sectionList1[n]; ++i) {
1967 if (maskArray[i] == 0) continue;
1968 xMatrix[0][0] += 1.0;
1969 xMatrix[0][1] += x1[i];
1970 xMatrix[0][2] += x2[i];
1971 xMatrix[0][3] += x3[i];
1972 xMatrix[1][1] += x2[i];
1973 xMatrix[1][2] += x3[i];
1974 xMatrix[1][3] += x2[i]*x2[i];
1975 xMatrix[2][2] += x2[i]*x2[i];
1976 xMatrix[2][3] += x3[i]*x2[i];
1977 xMatrix[3][3] += x3[i]*x3[i];
1978 zMatrix[0] += z1[i];
1979 zMatrix[1] += x1z1[i];
1980 zMatrix[2] += x2z1[i];
1981 zMatrix[3] += x3z1[i];
1982 for (int j = 0; j < n; ++j) {
1983 double q = 1.0 - x1[i]*sectionListR[j];
1984 q = q*q*q;
1985 xMatrix[0][j+4] += q;
1986 xMatrix[1][j+4] += q*x1[i];
1987 xMatrix[2][j+4] += q*x2[i];
1988 xMatrix[3][j+4] += q*x3[i];
1989 for (int k = 0; k < j; ++k) {
1990 double r = 1.0 - x1[i]*sectionListR[k];
1991 r = r*r*r;
1992 xMatrix[k+4][j+4] += r*q;
1993 }
1994 xMatrix[j+4][j+4] += q*q;
1995 zMatrix[j+4] += q*z1[i];
1996 }
1997 }
1998 }
1999
2000 for (int i = 0; i < nDOF; ++i) {
2001 for (int j = 0; j < i; ++j) {
2002 xMatrix[i][j] = xMatrix[j][i];
2003 }
2004 }
2005
2006 std::vector<double> invDiag;
2007 for (int i = 0; i < nDOF; ++i) {
2008 invDiag.push_back(1.0/xMatrix[i][i]);
2009 for (int j = 0; j < nDOF; ++j) {
2010 xMatrix[i][j] *= invDiag[i];
2011 }
2012 }
2013
2014 for (int k = 0; k < nDOF; ++k) {
2015 for (int i = 0; i < nDOF; ++i) {
2016 if (i != k) {
2017 double factor1 = xMatrix[k][k];
2018 double factor2 = xMatrix[i][k];
2019 for (int j = k; j < 2*nDOF; ++j) {
2020 xMatrix[i][j] *= factor1;
2021 xMatrix[i][j] -= xMatrix[k][j]*factor2;
2022 xMatrix[i][j] /= factor1;
2023 }
2024 }
2025 }
2026 double xDiag = xMatrix[k][k];
2027 for (int j = k; j < 2*nDOF; ++j) {
2028 xMatrix[k][j] /= xDiag;
2029 }
2030 }
2031
2032 for (int i = 0; i < nDOF; ++i) {
2033 for (int j = 0; j < nDOF; ++j) {
2034 xMatrix[i][nDOF+j] *= invDiag[j];
2035 }
2036 }
2037 //compute a vector y which consists of the coefficients of the best-fit spline curves
2038 //(a0,a1,a2,a3(,b3,c3,...)), namely, the ones for the leftmost piece and the ones of
2039 //cubic terms for the other pieces (in case nPiece>1).
2040 std::vector<double> y;
2041 for (int i = 0; i < nDOF; ++i) {
2042 y.push_back(0.0);
2043 for (int j = 0; j < nDOF; ++j) {
2044 y[i] += xMatrix[i][nDOF+j]*zMatrix[j];
2045 }
2046 }
2047
2048 double a0 = y[0];
2049 double a1 = y[1];
2050 double a2 = y[2];
2051 double a3 = y[3];
2052 params.clear();
2053
2054 for (int n = 0; n < nPiece; ++n) {
2055 for (int i = sectionList0[n]; i < sectionList1[n]; ++i) {
2056 r1[i] = a0 + a1*x1[i] + a2*x2[i] + a3*x3[i];
2057 }
2058 params.push_back(a0);
2059 params.push_back(a1);
2060 params.push_back(a2);
2061 params.push_back(a3);
2062
2063 if (n == nPiece-1) break;
2064
2065 double d = y[4+n];
2066 a0 += d;
2067 a1 -= 3.0*d*sectionListR[n];
2068 a2 += 3.0*d*sectionListR[n]*sectionListR[n];
2069 a3 -= d*sectionListR[n]*sectionListR[n]*sectionListR[n];
2070 }
2071
2072 if ((nClip == nIterClip) || (thresClip <= 0.0)) {
2073 break;
2074 } else {
2075 std::vector<double> rz;
2076 double stdDev = 0.0;
2077 for (int i = 0; i < nChan; ++i) {
2078 double val = abs(r1[i] - z1[i]);
2079 rz.push_back(val);
2080 stdDev += val*val*(double)maskArray[i];
2081 }
2082 stdDev = sqrt(stdDev/(double)nData);
2083
2084 double thres = stdDev * thresClip;
2085 int newNData = 0;
2086 for (int i = 0; i < nChan; ++i) {
2087 if (rz[i] >= thres) {
2088 maskArray[i] = 0;
2089 }
2090 if (maskArray[i] > 0) {
2091 newNData++;
2092 }
2093 }
2094 if (newNData == currentNData) {
2095 break; //no additional flag. finish iteration.
2096 } else {
2097 currentNData = newNData;
2098 }
2099 }
2100 }
2101
2102 std::vector<float> residual;
2103 for (int i = 0; i < nChan; ++i) {
2104 residual.push_back((float)(z1[i] - r1[i]));
2105 }
2106 return residual;
2107
2108}
2109
2110void Scantable::fitBaseline(const std::vector<bool>& mask, int whichrow, Fitter& fitter)
[1907]2111{
[2012]2112 std::vector<double> abcsd = getAbcissa(whichrow);
[1907]2113 std::vector<float> abcs;
[2012]2114 for (int i = 0; i < abcsd.size(); ++i) {
[1907]2115 abcs.push_back((float)abcsd[i]);
2116 }
[2012]2117 std::vector<float> spec = getSpectrum(whichrow);
2118
2119 fitter.setData(abcs, spec, mask);
2120 fitter.lfit();
2121}
2122
2123std::vector<bool> Scantable::getCompositeChanMask(int whichrow, const std::vector<bool>& inMask)
2124{
2125 std::vector<bool> chanMask = getMask(whichrow);
2126 int chanMaskSize = chanMask.size();
2127 if (chanMaskSize != inMask.size()) {
[1908]2128 throw(AipsError("different mask sizes"));
2129 }
[2012]2130 for (int i = 0; i < chanMaskSize; ++i) {
2131 chanMask[i] = chanMask[i] && inMask[i];
[1907]2132 }
2133
[2012]2134 return chanMask;
[1907]2135}
2136
[2012]2137/*
2138std::vector<bool> Scantable::getCompositeChanMask(int whichrow, const std::vector<bool>& inMask, const std::vector<int>& edge, const int minEdgeSize, STLineFinder& lineFinder)
[1907]2139{
[2012]2140 int edgeSize = edge.size();
2141 std::vector<int> currentEdge;
2142 if (edgeSize >= 2) {
2143 int idx = 0;
2144 if (edgeSize > 2) {
2145 if (edgeSize < minEdgeSize) {
2146 throw(AipsError("Length of edge element info is less than that of IFs"));
2147 }
2148 idx = 2 * getIF(whichrow);
2149 }
2150 currentEdge.push_back(edge[idx]);
2151 currentEdge.push_back(edge[idx+1]);
2152 } else {
2153 throw(AipsError("Wrong length of edge element"));
2154 }
2155
2156 lineFinder.setData(getSpectrum(whichrow));
2157 lineFinder.findLines(getCompositeChanMask(whichrow, inMask), currentEdge, whichrow);
2158
2159 return lineFinder.getMask();
2160}
2161*/
2162
2163void Scantable::polyBaseline(const std::vector<bool>& mask, int order, bool outLogger, const std::string& blfile)
2164{
2165 ofstream ofs;
2166 String coordInfo;
2167 bool hasSameNchan;
2168 int firstIF;
2169 bool outTextFile = false;
2170
2171 if (blfile != "") {
2172 ofs.open(blfile.c_str(), ios::out | ios::app);
2173 if (ofs) outTextFile = true;
2174 }
2175
2176 if (outLogger || outTextFile) {
2177 coordInfo = getCoordInfo()[0];
2178 if (coordInfo == "") coordInfo = "channel";
2179 hasSameNchan = hasSameNchanOverIFs();
2180 firstIF = getIF(0);
2181 }
2182
[1907]2183 Fitter fitter = Fitter();
[2012]2184 fitter.setExpression("poly", order);
2185
2186 int nRow = nrow();
2187 std::vector<bool> chanMask;
2188
2189 for (int whichrow = 0; whichrow < nRow; ++whichrow) {
2190
2191 chanMask = getCompositeChanMask(whichrow, mask);
2192 fitBaseline(chanMask, whichrow, fitter);
2193 setSpectrum(fitter.getResidual(), whichrow);
2194
2195 if (outLogger || outTextFile) {
2196 std::vector<float> params = fitter.getParameters();
2197 std::vector<bool> fixed = fitter.getFixedParameters();
2198 float rms = getRms(chanMask, whichrow);
2199 String masklist = getMaskRangeList(chanMask, whichrow, coordInfo, hasSameNchan, firstIF, true);
2200
2201 if (outLogger) {
2202 LogIO ols(LogOrigin("Scantable", "polyBaseline()", WHERE));
2203 ols << formatBaselineParams(params, fixed, rms, masklist, whichrow, false) << LogIO::POST ;
2204 }
2205 if (outTextFile) {
2206 ofs << formatBaselineParams(params, fixed, rms, masklist, whichrow, true) << flush;
2207 }
2208 }
2209
[1931]2210 }
[2012]2211
2212 if (outTextFile) ofs.close();
[1907]2213}
2214
[2012]2215void Scantable::autoPolyBaseline(const std::vector<bool>& mask, int order, const std::vector<int>& edge, float threshold, int chanAvgLimit, bool outLogger, const std::string& blfile)
2216{
2217 ofstream ofs;
2218 String coordInfo;
2219 bool hasSameNchan;
2220 int firstIF;
2221 bool outTextFile = false;
2222
2223 if (blfile != "") {
2224 ofs.open(blfile.c_str(), ios::out | ios::app);
2225 if (ofs) outTextFile = true;
2226 }
2227
2228 if (outLogger || outTextFile) {
2229 coordInfo = getCoordInfo()[0];
2230 if (coordInfo == "") coordInfo = "channel";
2231 hasSameNchan = hasSameNchanOverIFs();
2232 firstIF = getIF(0);
2233 }
2234
2235 Fitter fitter = Fitter();
2236 fitter.setExpression("poly", order);
2237
2238 int nRow = nrow();
2239 std::vector<bool> chanMask;
2240 int minEdgeSize = getIFNos().size()*2;
2241 STLineFinder lineFinder = STLineFinder();
2242 lineFinder.setOptions(threshold, 3, chanAvgLimit);
2243
2244 for (int whichrow = 0; whichrow < nRow; ++whichrow) {
2245
2246 //-------------------------------------------------------
2247 //chanMask = getCompositeChanMask(whichrow, mask, edge, minEdgeSize, lineFinder);
2248 //-------------------------------------------------------
2249 int edgeSize = edge.size();
2250 std::vector<int> currentEdge;
2251 if (edgeSize >= 2) {
2252 int idx = 0;
2253 if (edgeSize > 2) {
2254 if (edgeSize < minEdgeSize) {
2255 throw(AipsError("Length of edge element info is less than that of IFs"));
2256 }
2257 idx = 2 * getIF(whichrow);
2258 }
2259 currentEdge.push_back(edge[idx]);
2260 currentEdge.push_back(edge[idx+1]);
2261 } else {
2262 throw(AipsError("Wrong length of edge element"));
2263 }
2264 lineFinder.setData(getSpectrum(whichrow));
2265 lineFinder.findLines(getCompositeChanMask(whichrow, mask), currentEdge, whichrow);
2266 chanMask = lineFinder.getMask();
2267 //-------------------------------------------------------
2268
2269
2270 fitBaseline(chanMask, whichrow, fitter);
2271 setSpectrum(fitter.getResidual(), whichrow);
2272
2273 if (outLogger || outTextFile) {
2274 std::vector<float> params = fitter.getParameters();
2275 std::vector<bool> fixed = fitter.getFixedParameters();
2276 float rms = getRms(chanMask, whichrow);
2277 String masklist = getMaskRangeList(chanMask, whichrow, coordInfo, hasSameNchan, firstIF, true);
2278
2279 if (outLogger) {
2280 LogIO ols(LogOrigin("Scantable", "autoPolyBaseline()", WHERE));
2281 ols << formatBaselineParams(params, fixed, rms, masklist, whichrow, false) << LogIO::POST ;
2282 }
2283 if (outTextFile) {
2284 ofs << formatBaselineParams(params, fixed, rms, masklist, whichrow, true) << flush;
2285 }
2286 }
2287
2288 }
2289
2290 if (outTextFile) ofs.close();
2291}
2292
2293
2294float Scantable::getRms(const std::vector<bool>& mask, int whichrow) {
2295 Vector<Float> spec;
2296 specCol_.get(whichrow, spec);
2297
2298 float mean = 0.0;
2299 float smean = 0.0;
2300 int n = 0;
2301 for (int i = 0; i < spec.nelements(); ++i) {
2302 if (mask[i]) {
2303 mean += spec[i];
2304 smean += spec[i]*spec[i];
2305 n++;
2306 }
2307 }
2308
2309 mean /= (float)n;
2310 smean /= (float)n;
2311
2312 return sqrt(smean - mean*mean);
2313}
2314
2315
2316std::string Scantable::formatBaselineParamsHeader(int whichrow, const std::string& masklist, bool verbose) const
2317{
2318 ostringstream oss;
2319
2320 if (verbose) {
2321 for (int i = 0; i < 60; ++i) {
2322 oss << "-";
2323 }
2324 oss << endl;
2325 oss << " Scan[" << getScan(whichrow) << "]";
2326 oss << " Beam[" << getBeam(whichrow) << "]";
2327 oss << " IF[" << getIF(whichrow) << "]";
2328 oss << " Pol[" << getPol(whichrow) << "]";
2329 oss << " Cycle[" << getCycle(whichrow) << "]: " << endl;
2330 oss << "Fitter range = " << masklist << endl;
2331 oss << "Baseline parameters" << endl;
2332 oss << flush;
2333 }
2334
2335 return String(oss);
2336}
2337
2338std::string Scantable::formatBaselineParamsFooter(float rms, bool verbose) const
2339{
2340 ostringstream oss;
2341
2342 if (verbose) {
2343 oss << endl;
2344 oss << "Results of baseline fit" << endl;
2345 oss << " rms = " << setprecision(6) << rms << endl;
2346 }
2347
2348 return String(oss);
2349}
2350
2351std::string Scantable::formatPiecewiseBaselineParams(const std::vector<int>& ranges, const std::vector<float>& params, const std::vector<bool>& fixed, float rms, const std::string& masklist, int whichrow, bool verbose) const
2352{
2353 ostringstream oss;
2354 oss << formatBaselineParamsHeader(whichrow, masklist, verbose);
2355
2356 if ((params.size() > 0) && (ranges.size() > 0)) {
2357 if (((ranges.size() % 2) == 0) && ((params.size() % (ranges.size() / 2)) == 0)) {
2358 int nParam = params.size() / (ranges.size() / 2);
2359 for (uInt j = 0; j < ranges.size(); j+=2) {
2360 oss << "[" << ranges[j] << "," << ranges[j+1] << "]";
2361 for (uInt i = 0; i < nParam; ++i) {
2362 if (i > 0) {
2363 oss << ",";
2364 }
2365 String fix = ((fixed.size() > 0) && (fixed[i]) && verbose) ? "(fixed)" : "";
2366 oss << " p" << i << fix << "= " << setprecision(6) << params[j/2*nParam+i];
2367 }
2368 }
2369 } else {
2370 oss << " ";
2371 }
2372 } else {
2373 oss << " Not fitted";
2374 }
2375
2376 oss << formatBaselineParamsFooter(rms, verbose);
2377 oss << flush;
2378
2379 return String(oss);
2380}
2381
2382std::string Scantable::formatBaselineParams(const std::vector<float>& params, const std::vector<bool>& fixed, float rms, const std::string& masklist, int whichrow, bool verbose) const
2383{
2384 ostringstream oss;
2385 oss << formatBaselineParamsHeader(whichrow, masklist, verbose);
2386
2387 if (params.size() > 0) {
2388 for (uInt i = 0; i < params.size(); ++i) {
2389 if (i > 0) {
2390 oss << ",";
2391 }
2392 String fix = ((fixed.size() > 0) && (fixed[i]) && verbose) ? "(fixed)" : "";
2393 oss << " p" << i << fix << "= " << setprecision(6) << params[i];
2394 }
2395 } else {
2396 oss << " Not fitted";
2397 }
2398
2399 oss << formatBaselineParamsFooter(rms, verbose);
2400 oss << flush;
2401
2402 return String(oss);
2403}
2404
2405std::string Scantable::getMaskRangeList(const std::vector<bool>& mask, int whichrow, const casa::String& coordInfo, bool hasSameNchan, int firstIF, bool silent)
2406{
2407 if (mask.size() < 2) {
2408 throw(AipsError("The mask elements should be > 1"));
2409 }
2410 if (mask.size() != nchan()) {
2411 throw(AipsError("Number of channels in scantable != number of mask elements"));
2412 }
2413
2414 std::vector<int> startIdx = getMaskEdgeIndices(mask, true);
2415 std::vector<int> endIdx = getMaskEdgeIndices(mask, false);
2416
2417 if (startIdx.size() != endIdx.size()) {
2418 throw(AipsError("Numbers of mask start and mask end are not identical"));
2419 }
2420 for (int i = 0; i < startIdx.size(); ++i) {
2421 if (startIdx[i] > endIdx[i]) {
2422 throw(AipsError("Mask start index > mask end index"));
2423 }
2424 }
2425
2426 if (!silent) {
2427 LogIO logOs(LogOrigin("Scantable", "getMaskRangeList()", WHERE));
2428 logOs << LogIO::WARN << "The current mask window unit is " << coordInfo;
2429 if (!hasSameNchan) {
2430 logOs << endl << "This mask is only valid for IF=" << firstIF;
2431 }
2432 logOs << LogIO::POST;
2433 }
2434
2435 std::vector<double> abcissa = getAbcissa(whichrow);
2436 ostringstream oss;
2437 oss.setf(ios::fixed);
2438 oss << setprecision(1) << "[";
2439 for (int i = 0; i < startIdx.size(); ++i) {
2440 std::vector<float> aMaskRange;
2441 aMaskRange.push_back((float)abcissa[startIdx[i]]);
2442 aMaskRange.push_back((float)abcissa[endIdx[i]]);
2443 sort(aMaskRange.begin(), aMaskRange.end());
2444 if (i > 0) oss << ",";
2445 oss << "[" << aMaskRange[0] << "," << aMaskRange[1] << "]";
2446 }
2447 oss << "]" << flush;
2448
2449 return String(oss);
2450}
2451
2452bool Scantable::hasSameNchanOverIFs()
2453{
2454 int nIF = nif(-1);
2455 int nCh;
2456 int totalPositiveNChan = 0;
2457 int nPositiveNChan = 0;
2458
2459 for (int i = 0; i < nIF; ++i) {
2460 nCh = nchan(i);
2461 if (nCh > 0) {
2462 totalPositiveNChan += nCh;
2463 nPositiveNChan++;
2464 }
2465 }
2466
2467 return (totalPositiveNChan == (nPositiveNChan * nchan(0)));
2468}
2469
2470std::vector<int> Scantable::getMaskEdgeIndices(const std::vector<bool>& mask, bool getStartIndices)
2471{
2472 if (mask.size() < 2) {
2473 throw(AipsError("The mask elements should be > 1"));
2474 }
2475 if (mask.size() != nchan()) {
2476 throw(AipsError("Number of channels in scantable != number of mask elements"));
2477 }
2478
2479 std::vector<int> out;
2480 int endIdx = mask.size() - 1;
2481
2482 if (getStartIndices) {
2483 if (mask[0]) {
2484 out.push_back(0);
2485 }
2486 for (int i = 0; i < endIdx; ++i) {
2487 if ((!mask[i]) && mask[i+1]) {
2488 out.push_back(i+1);
2489 }
2490 }
2491 } else {
2492 for (int i = 0; i < endIdx; ++i) {
2493 if (mask[i] && (!mask[i+1])) {
2494 out.push_back(i);
2495 }
2496 }
2497 if (mask[endIdx]) {
2498 out.push_back(endIdx);
2499 }
2500 }
2501
2502 return out;
2503}
2504
2505
2506/*
[1931]2507STFitEntry Scantable::polyBaseline(const std::vector<bool>& mask, int order, int rowno)
[1907]2508{
2509 Fitter fitter = Fitter();
[2012]2510 fitter.setExpression("poly", order);
2511
2512 std::vector<bool> fmask = getMask(rowno);
2513 if (fmask.size() != mask.size()) {
2514 throw(AipsError("different mask sizes"));
2515 }
2516 for (int i = 0; i < fmask.size(); ++i) {
2517 fmask[i] = fmask[i] && mask[i];
2518 }
2519
2520 fitBaseline(fmask, rowno, fitter);
[1907]2521 setSpectrum(fitter.getResidual(), rowno);
[1931]2522 return fitter.getFitEntry();
[1907]2523}
[2012]2524*/
[1907]2525
2526}
[1819]2527//namespace asap
Note: See TracBrowser for help on using the repository browser.