source: trunk/src/Scantable.cpp@ 999

Last change on this file since 999 was 999, checked in by mar637, 19 years ago

added "redundant" fields from reader. The aren't used in asap but should be passed on for consistency.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.8 KB
Line 
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//
12#include <map>
13
14#include <casa/aips.h>
15#include <casa/iostream.h>
16#include <casa/iomanip.h>
17#include <casa/OS/Path.h>
18#include <casa/OS/File.h>
19#include <casa/Arrays/Array.h>
20#include <casa/Arrays/ArrayMath.h>
21#include <casa/Arrays/MaskArrMath.h>
22#include <casa/Arrays/ArrayLogical.h>
23#include <casa/Arrays/ArrayAccessor.h>
24#include <casa/Arrays/VectorSTLIterator.h>
25#include <casa/Arrays/Vector.h>
26#include <casa/BasicMath/Math.h>
27#include <casa/BasicSL/Constants.h>
28#include <casa/Quanta/MVAngle.h>
29#include <casa/Containers/RecordField.h>
30#include <casa/Utilities/GenSort.h>
31
32#include <tables/Tables/TableParse.h>
33#include <tables/Tables/TableDesc.h>
34#include <tables/Tables/TableCopy.h>
35#include <tables/Tables/SetupNewTab.h>
36#include <tables/Tables/ScaColDesc.h>
37#include <tables/Tables/ArrColDesc.h>
38#include <tables/Tables/TableRow.h>
39#include <tables/Tables/TableVector.h>
40#include <tables/Tables/TableIter.h>
41
42#include <tables/Tables/ExprNode.h>
43#include <tables/Tables/TableRecord.h>
44#include <measures/Measures/MFrequency.h>
45#include <measures/Measures/MEpoch.h>
46#include <measures/Measures/MeasTable.h>
47#include <measures/Measures/MeasRef.h>
48#include <measures/TableMeasures/TableMeasRefDesc.h>
49#include <measures/TableMeasures/TableMeasValueDesc.h>
50#include <measures/TableMeasures/TableMeasDesc.h>
51#include <measures/TableMeasures/ScalarMeasColumn.h>
52#include <coordinates/Coordinates/CoordinateUtil.h>
53#include <casa/Quanta/MVTime.h>
54#include <casa/Quanta/MVAngle.h>
55
56#include "Scantable.h"
57#include "STPolLinear.h"
58#include "STPolStokes.h"
59#include "STAttr.h"
60#include "MathUtils.h"
61
62using namespace casa;
63
64namespace asap {
65
66std::map<std::string, STPol::STPolFactory *> Scantable::factories_;
67
68void Scantable::initFactories() {
69 if ( factories_.empty() ) {
70 Scantable::factories_["linear"] = &STPolLinear::myFactory;
71 Scantable::factories_["stokes"] = &STPolStokes::myFactory;
72 }
73}
74
75Scantable::Scantable(Table::TableType ttype) :
76 type_(ttype)
77{
78 initFactories();
79 setupMainTable();
80 freqTable_ = STFrequencies(*this);
81 table_.rwKeywordSet().defineTable("FREQUENCIES", freqTable_.table());
82 weatherTable_ = STWeather(*this);
83 table_.rwKeywordSet().defineTable("WEATHER", weatherTable_.table());
84 focusTable_ = STFocus(*this);
85 table_.rwKeywordSet().defineTable("FOCUS", focusTable_.table());
86 tcalTable_ = STTcal(*this);
87 table_.rwKeywordSet().defineTable("TCAL", tcalTable_.table());
88 moleculeTable_ = STMolecules(*this);
89 table_.rwKeywordSet().defineTable("MOLECULES", moleculeTable_.table());
90 historyTable_ = STHistory(*this);
91 table_.rwKeywordSet().defineTable("HISTORY", historyTable_.table());
92 fitTable_ = STFit(*this);
93 table_.rwKeywordSet().defineTable("FIT", fitTable_.table());
94 originalTable_ = table_;
95 attach();
96}
97
98Scantable::Scantable(const std::string& name, Table::TableType ttype) :
99 type_(ttype)
100{
101 initFactories();
102 Table tab(name, Table::Update);
103 uInt version;
104 tab.keywordSet().get("VERSION", version);
105 if (version != version_) {
106 throw(AipsError("Unsupported version of ASAP file."));
107 }
108 if ( type_ == Table::Memory )
109 table_ = tab.copyToMemoryTable(generateName());
110 else
111 table_ = tab;
112 attachSubtables();
113 originalTable_ = table_;
114 attach();
115}
116
117Scantable::Scantable( const Scantable& other, bool clear )
118{
119 // with or without data
120 String newname = String(generateName());
121 type_ = other.table_.tableType();
122 if ( other.table_.tableType() == Table::Memory ) {
123 if ( clear ) {
124 table_ = TableCopy::makeEmptyMemoryTable(newname,
125 other.table_, True);
126 } else
127 table_ = other.table_.copyToMemoryTable(newname);
128 } else {
129 other.table_.deepCopy(newname, Table::New, False,
130 other.table_.endianFormat(),
131 Bool(clear));
132 table_ = Table(newname, Table::Update);
133 table_.markForDelete();
134 }
135
136 if ( clear ) copySubtables(other);
137 attachSubtables();
138 originalTable_ = table_;
139 attach();
140}
141
142void Scantable::copySubtables(const Scantable& other) {
143 Table t = table_.rwKeywordSet().asTable("FREQUENCIES");
144 TableCopy::copyRows(t, other.freqTable_.table());
145 t = table_.rwKeywordSet().asTable("FOCUS");
146 TableCopy::copyRows(t, other.focusTable_.table());
147 t = table_.rwKeywordSet().asTable("WEATHER");
148 TableCopy::copyRows(t, other.weatherTable_.table());
149 t = table_.rwKeywordSet().asTable("TCAL");
150 TableCopy::copyRows(t, other.tcalTable_.table());
151 t = table_.rwKeywordSet().asTable("MOLECULES");
152 TableCopy::copyRows(t, other.moleculeTable_.table());
153 t = table_.rwKeywordSet().asTable("HISTORY");
154 TableCopy::copyRows(t, other.historyTable_.table());
155 t = table_.rwKeywordSet().asTable("FIT");
156 TableCopy::copyRows(t, other.fitTable_.table());
157}
158
159void Scantable::attachSubtables()
160{
161 freqTable_ = STFrequencies(table_);
162 focusTable_ = STFocus(table_);
163 weatherTable_ = STWeather(table_);
164 tcalTable_ = STTcal(table_);
165 moleculeTable_ = STMolecules(table_);
166 historyTable_ = STHistory(table_);
167 fitTable_ = STFit(table_);
168}
169
170Scantable::~Scantable()
171{
172 //cout << "~Scantable() " << this << endl;
173}
174
175void Scantable::setupMainTable()
176{
177 TableDesc td("", "1", TableDesc::Scratch);
178 td.comment() = "An ASAP Scantable";
179 td.rwKeywordSet().define("VERSION", Int(version_));
180
181 // n Cycles
182 td.addColumn(ScalarColumnDesc<uInt>("SCANNO"));
183 // new index every nBeam x nIF x nPol
184 td.addColumn(ScalarColumnDesc<uInt>("CYCLENO"));
185
186 td.addColumn(ScalarColumnDesc<uInt>("BEAMNO"));
187 td.addColumn(ScalarColumnDesc<uInt>("IFNO"));
188 // linear, circular, stokes
189 td.rwKeywordSet().define("POLTYPE", String("linear"));
190 td.addColumn(ScalarColumnDesc<uInt>("POLNO"));
191
192 td.addColumn(ScalarColumnDesc<uInt>("FREQ_ID"));
193 td.addColumn(ScalarColumnDesc<uInt>("MOLECULE_ID"));
194 td.addColumn(ScalarColumnDesc<Int>("REFBEAMNO"));
195
196 td.addColumn(ScalarColumnDesc<Double>("TIME"));
197 TableMeasRefDesc measRef(MEpoch::UTC); // UTC as default
198 TableMeasValueDesc measVal(td, "TIME");
199 TableMeasDesc<MEpoch> mepochCol(measVal, measRef);
200 mepochCol.write(td);
201
202 td.addColumn(ScalarColumnDesc<Double>("INTERVAL"));
203
204 td.addColumn(ScalarColumnDesc<String>("SRCNAME"));
205 // Type of source (on=0, off=1, other=-1)
206 td.addColumn(ScalarColumnDesc<Int>("SRCTYPE", Int(-1)));
207 td.addColumn(ScalarColumnDesc<String>("FIELDNAME"));
208
209 //The actual Data Vectors
210 td.addColumn(ArrayColumnDesc<Float>("SPECTRA"));
211 td.addColumn(ArrayColumnDesc<uChar>("FLAGTRA"));
212 td.addColumn(ArrayColumnDesc<Float>("TSYS"));
213
214 td.addColumn(ArrayColumnDesc<Double>("DIRECTION",
215 IPosition(1,2),
216 ColumnDesc::Direct));
217 TableMeasRefDesc mdirRef(MDirection::J2000); // default
218 TableMeasValueDesc tmvdMDir(td, "DIRECTION");
219 // the TableMeasDesc gives the column a type
220 TableMeasDesc<MDirection> mdirCol(tmvdMDir, mdirRef);
221 // a uder set table type e.g. GALCTIC, B1950 ...
222 td.rwKeywordSet().define("DIRECTIONREF", String("J2000"));
223 // writing create the measure column
224 mdirCol.write(td);
225 td.addColumn(ScalarColumnDesc<Float>("AZIMUTH"));
226 td.addColumn(ScalarColumnDesc<Float>("ELEVATION"));
227 td.addColumn(ScalarColumnDesc<Float>("PARANGLE"));
228
229 td.addColumn(ScalarColumnDesc<uInt>("TCAL_ID"));
230 ScalarColumnDesc<Int> fitColumn("FIT_ID");
231 fitColumn.setDefault(Int(-1));
232 td.addColumn(fitColumn);
233
234 td.addColumn(ScalarColumnDesc<uInt>("FOCUS_ID"));
235 td.addColumn(ScalarColumnDesc<uInt>("WEATHER_ID"));
236
237 // columns which just get dragged along, as they aren't used in asap
238 td.addColumn(ScalarColumnDesc<Double>("SRCVELOCITY"));
239 td.addColumn(ArrayColumnDesc<Double>("SRCPROPERMOTION"));
240 td.addColumn(ArrayColumnDesc<Double>("SRCDIRECTION"));
241 td.addColumn(ArrayColumnDesc<Double>("SCANRATE"));
242
243 td.rwKeywordSet().define("OBSMODE", String(""));
244
245 // Now create Table SetUp from the description.
246 SetupNewTable aNewTab(generateName(), td, Table::Scratch);
247 table_ = Table(aNewTab, type_, 0);
248 originalTable_ = table_;
249}
250
251
252void Scantable::attach()
253{
254 timeCol_.attach(table_, "TIME");
255 srcnCol_.attach(table_, "SRCNAME");
256 specCol_.attach(table_, "SPECTRA");
257 flagsCol_.attach(table_, "FLAGTRA");
258 tsysCol_.attach(table_, "TSYS");
259 cycleCol_.attach(table_,"CYCLENO");
260 scanCol_.attach(table_, "SCANNO");
261 beamCol_.attach(table_, "BEAMNO");
262 ifCol_.attach(table_, "IFNO");
263 polCol_.attach(table_, "POLNO");
264 integrCol_.attach(table_, "INTERVAL");
265 azCol_.attach(table_, "AZIMUTH");
266 elCol_.attach(table_, "ELEVATION");
267 dirCol_.attach(table_, "DIRECTION");
268 paraCol_.attach(table_, "PARANGLE");
269 fldnCol_.attach(table_, "FIELDNAME");
270 rbeamCol_.attach(table_, "REFBEAMNO");
271
272 mfitidCol_.attach(table_,"FIT_ID");
273 mfreqidCol_.attach(table_, "FREQ_ID");
274 mtcalidCol_.attach(table_, "TCAL_ID");
275 mfocusidCol_.attach(table_, "FOCUS_ID");
276 mmolidCol_.attach(table_, "MOLECULE_ID");
277}
278
279void Scantable::setHeader(const STHeader& sdh)
280{
281 table_.rwKeywordSet().define("nIF", sdh.nif);
282 table_.rwKeywordSet().define("nBeam", sdh.nbeam);
283 table_.rwKeywordSet().define("nPol", sdh.npol);
284 table_.rwKeywordSet().define("nChan", sdh.nchan);
285 table_.rwKeywordSet().define("Observer", sdh.observer);
286 table_.rwKeywordSet().define("Project", sdh.project);
287 table_.rwKeywordSet().define("Obstype", sdh.obstype);
288 table_.rwKeywordSet().define("AntennaName", sdh.antennaname);
289 table_.rwKeywordSet().define("AntennaPosition", sdh.antennaposition);
290 table_.rwKeywordSet().define("Equinox", sdh.equinox);
291 table_.rwKeywordSet().define("FreqRefFrame", sdh.freqref);
292 table_.rwKeywordSet().define("FreqRefVal", sdh.reffreq);
293 table_.rwKeywordSet().define("Bandwidth", sdh.bandwidth);
294 table_.rwKeywordSet().define("UTC", sdh.utc);
295 table_.rwKeywordSet().define("FluxUnit", sdh.fluxunit);
296 table_.rwKeywordSet().define("Epoch", sdh.epoch);
297 table_.rwKeywordSet().define("POLTYPE", sdh.poltype);
298}
299
300STHeader Scantable::getHeader() const
301{
302 STHeader sdh;
303 table_.keywordSet().get("nBeam",sdh.nbeam);
304 table_.keywordSet().get("nIF",sdh.nif);
305 table_.keywordSet().get("nPol",sdh.npol);
306 table_.keywordSet().get("nChan",sdh.nchan);
307 table_.keywordSet().get("Observer", sdh.observer);
308 table_.keywordSet().get("Project", sdh.project);
309 table_.keywordSet().get("Obstype", sdh.obstype);
310 table_.keywordSet().get("AntennaName", sdh.antennaname);
311 table_.keywordSet().get("AntennaPosition", sdh.antennaposition);
312 table_.keywordSet().get("Equinox", sdh.equinox);
313 table_.keywordSet().get("FreqRefFrame", sdh.freqref);
314 table_.keywordSet().get("FreqRefVal", sdh.reffreq);
315 table_.keywordSet().get("Bandwidth", sdh.bandwidth);
316 table_.keywordSet().get("UTC", sdh.utc);
317 table_.keywordSet().get("FluxUnit", sdh.fluxunit);
318 table_.keywordSet().get("Epoch", sdh.epoch);
319 table_.keywordSet().get("POLTYPE", sdh.poltype);
320 return sdh;
321}
322
323bool Scantable::conformant( const Scantable& other )
324{
325 return this->getHeader().conformant(other.getHeader());
326}
327
328
329int Scantable::nscan() const {
330 Vector<uInt> scannos(scanCol_.getColumn());
331 uInt nout = GenSort<uInt>::sort( scannos, Sort::Ascending,
332 Sort::QuickSort|Sort::NoDuplicates );
333 return int(nout);
334}
335
336std::string Scantable::formatSec(Double x) const
337{
338 Double xcop = x;
339 MVTime mvt(xcop/24./3600.); // make days
340
341 if (x < 59.95)
342 return String(" ") + mvt.string(MVTime::TIME_CLEAN_NO_HM, 7)+"s";
343 else if (x < 3599.95)
344 return String(" ") + mvt.string(MVTime::TIME_CLEAN_NO_H,7)+" ";
345 else {
346 ostringstream oss;
347 oss << setw(2) << std::right << setprecision(1) << mvt.hour();
348 oss << ":" << mvt.string(MVTime::TIME_CLEAN_NO_H,7) << " ";
349 return String(oss);
350 }
351};
352
353std::string Scantable::formatDirection(const MDirection& md) const
354{
355 Vector<Double> t = md.getAngle(Unit(String("rad"))).getValue();
356 Int prec = 7;
357
358 MVAngle mvLon(t[0]);
359 String sLon = mvLon.string(MVAngle::TIME,prec);
360 uInt tp = md.getRef().getType();
361 if (tp == MDirection::GALACTIC ||
362 tp == MDirection::SUPERGAL ) {
363 sLon = mvLon(0.0).string(MVAngle::ANGLE_CLEAN,prec);
364 }
365 MVAngle mvLat(t[1]);
366 String sLat = mvLat.string(MVAngle::ANGLE+MVAngle::DIG2,prec);
367 return sLon + String(" ") + sLat;
368}
369
370
371std::string Scantable::getFluxUnit() const
372{
373 return table_.keywordSet().asString("FluxUnit");
374}
375
376void Scantable::setFluxUnit(const std::string& unit)
377{
378 String tmp(unit);
379 Unit tU(tmp);
380 if (tU==Unit("K") || tU==Unit("Jy")) {
381 table_.rwKeywordSet().define(String("FluxUnit"), tmp);
382 } else {
383 throw AipsError("Illegal unit - must be compatible with Jy or K");
384 }
385}
386
387void Scantable::setInstrument(const std::string& name)
388{
389 bool throwIt = true;
390 // create an Instrument to see if this is valid
391 STAttr::convertInstrument(name, throwIt);
392 String nameU(name);
393 nameU.upcase();
394 table_.rwKeywordSet().define(String("AntennaName"), nameU);
395}
396
397MPosition Scantable::getAntennaPosition () const
398{
399 Vector<Double> antpos;
400 table_.keywordSet().get("AntennaPosition", antpos);
401 MVPosition mvpos(antpos(0),antpos(1),antpos(2));
402 return MPosition(mvpos);
403}
404
405void Scantable::makePersistent(const std::string& filename)
406{
407 String inname(filename);
408 Path path(inname);
409 inname = path.expandedName();
410 table_.deepCopy(inname, Table::New);
411}
412
413int Scantable::nbeam( int scanno ) const
414{
415 if ( scanno < 0 ) {
416 Int n;
417 table_.keywordSet().get("nBeam",n);
418 return int(n);
419 } else {
420 // take the first POLNO,IFNO,CYCLENO as nbeam shouldn't vary with these
421 Table t = table_(table_.col("SCANNO") == scanno);
422 ROTableRow row(t);
423 const TableRecord& rec = row.get(0);
424 Table subt = t( t.col("IFNO") == Int(rec.asuInt("IFNO"))
425 && t.col("POLNO") == Int(rec.asuInt("POLNO"))
426 && t.col("CYCLENO") == Int(rec.asuInt("CYCLENO")) );
427 ROTableVector<uInt> v(subt, "BEAMNO");
428 return int(v.nelements());
429 }
430 return 0;
431}
432
433int Scantable::nif( int scanno ) const
434{
435 if ( scanno < 0 ) {
436 Int n;
437 table_.keywordSet().get("nIF",n);
438 return int(n);
439 } else {
440 // take the first POLNO,BEAMNO,CYCLENO as nbeam shouldn't vary with these
441 Table t = table_(table_.col("SCANNO") == scanno);
442 ROTableRow row(t);
443 const TableRecord& rec = row.get(0);
444 Table subt = t( t.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
445 && t.col("POLNO") == Int(rec.asuInt("POLNO"))
446 && t.col("CYCLENO") == Int(rec.asuInt("CYCLENO")) );
447 if ( subt.nrow() == 0 ) return 0;
448 ROTableVector<uInt> v(subt, "IFNO");
449 return int(v.nelements());
450 }
451 return 0;
452}
453
454int Scantable::npol( int scanno ) const
455{
456 if ( scanno < 0 ) {
457 Int n;
458 table_.keywordSet().get("nPol",n);
459 return n;
460 } else {
461 // take the first POLNO,IFNO,CYCLENO as nbeam shouldn't vary with these
462 Table t = table_(table_.col("SCANNO") == scanno);
463 ROTableRow row(t);
464 const TableRecord& rec = row.get(0);
465 Table subt = t( t.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
466 && t.col("IFNO") == Int(rec.asuInt("IFNO"))
467 && t.col("CYCLENO") == Int(rec.asuInt("CYCLENO")) );
468 if ( subt.nrow() == 0 ) return 0;
469 ROTableVector<uInt> v(subt, "POLNO");
470 return int(v.nelements());
471 }
472 return 0;
473}
474
475int Scantable::ncycle( int scanno ) const
476{
477 if ( scanno < 0 ) {
478 Block<String> cols(2);
479 cols[0] = "SCANNO";
480 cols[1] = "CYCLENO";
481 TableIterator it(table_, cols);
482 int n = 0;
483 while ( !it.pastEnd() ) {
484 ++n;
485 ++it;
486 }
487 return n;
488 } else {
489 Table t = table_(table_.col("SCANNO") == scanno);
490 ROTableRow row(t);
491 const TableRecord& rec = row.get(0);
492 Table subt = t( t.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
493 && t.col("POLNO") == Int(rec.asuInt("POLNO"))
494 && t.col("IFNO") == Int(rec.asuInt("IFNO")) );
495 if ( subt.nrow() == 0 ) return 0;
496 return int(subt.nrow());
497 }
498 return 0;
499}
500
501
502int Scantable::nrow( int scanno ) const
503{
504 return int(table_.nrow());
505}
506
507int Scantable::nchan( int ifno ) const
508{
509 if ( ifno < 0 ) {
510 Int n;
511 table_.keywordSet().get("nChan",n);
512 return int(n);
513 } else {
514 // take the first SCANNO,POLNO,BEAMNO,CYCLENO as nbeam shouldn't vary with these
515 Table t = table_(table_.col("IFNO") == ifno);
516 if ( t.nrow() == 0 ) return 0;
517 ROArrayColumn<Float> v(t, "SPECTRA");
518 return v.shape(0)(0);
519 }
520 return 0;
521}
522
523int Scantable::getChannels(int whichrow) const
524{
525 return specCol_.shape(whichrow)(0);
526}
527
528int Scantable::getBeam(int whichrow) const
529{
530 return beamCol_(whichrow);
531}
532
533int Scantable::getIF(int whichrow) const
534{
535 return ifCol_(whichrow);
536}
537
538int Scantable::getPol(int whichrow) const
539{
540 return polCol_(whichrow);
541}
542
543std::string Scantable::formatTime(const MEpoch& me, bool showdate) const
544{
545 MVTime mvt(me.getValue());
546 if (showdate)
547 mvt.setFormat(MVTime::YMD);
548 else
549 mvt.setFormat(MVTime::TIME);
550 ostringstream oss;
551 oss << mvt;
552 return String(oss);
553}
554
555void Scantable::calculateAZEL()
556{
557 MPosition mp = getAntennaPosition();
558 MEpoch::ROScalarColumn timeCol(table_, "TIME");
559 ostringstream oss;
560 oss << "Computed azimuth/elevation using " << endl
561 << mp << endl;
562 for (Int i=0; i<nrow(); ++i) {
563 MEpoch me = timeCol(i);
564 MDirection md = getDirection(i);
565 oss << " Time: " << formatTime(me,False) << " Direction: " << formatDirection(md)
566 << endl << " => ";
567 MeasFrame frame(mp, me);
568 Vector<Double> azel =
569 MDirection::Convert(md, MDirection::Ref(MDirection::AZEL,
570 frame)
571 )().getAngle("rad").getValue();
572 azCol_.put(i,Float(azel[0]));
573 elCol_.put(i,Float(azel[1]));
574 oss << "azel: " << azel[0]/C::pi*180.0 << " "
575 << azel[1]/C::pi*180.0 << " (deg)" << endl;
576 }
577 pushLog(String(oss));
578}
579
580void Scantable::flag()
581{
582 if ( selector_.empty() )
583 throw(AipsError("Trying to flag whole scantable. Aborted."));
584 TableVector<uChar> tvec(table_, "FLAGTRA");
585 uChar userflag = 1 << 7;
586 tvec = userflag;
587}
588
589std::vector<bool> Scantable::getMask(int whichrow) const
590{
591 Vector<uChar> flags;
592 flagsCol_.get(uInt(whichrow), flags);
593 Vector<Bool> bflag(flags.shape());
594 convertArray(bflag, flags);
595 bflag = !bflag;
596 std::vector<bool> mask;
597 bflag.tovector(mask);
598 return mask;
599}
600
601std::vector<float> Scantable::getSpectrum( int whichrow,
602 const std::string& poltype ) const
603{
604 String ptype = poltype;
605 if (poltype == "" ) ptype = getPolType();
606 if ( whichrow < 0 || whichrow >= nrow() )
607 throw(AipsError("Illegal row number."));
608 std::vector<float> out;
609 Vector<Float> arr;
610 uInt requestedpol = polCol_(whichrow);
611 String basetype = getPolType();
612 if ( ptype == basetype ) {
613 specCol_.get(whichrow, arr);
614 } else {
615 STPol* stpol = 0;
616 stpol =STPol::getPolClass(Scantable::factories_, basetype);
617 try {
618 uInt row = uInt(whichrow);
619 stpol->setSpectra(getPolMatrix(row));
620 Float fang,fhand,parang;
621 fang = focusTable_.getTotalFeedAngle(mfocusidCol_(row));
622 fhand = focusTable_.getFeedHand(mfocusidCol_(row));
623 parang = paraCol_(row);
624 /// @todo re-enable this
625 // disable total feed angle to support paralactifying Caswell style
626 stpol->setPhaseCorrections(parang, -parang, fhand);
627 arr = stpol->getSpectrum(requestedpol, ptype);
628 delete stpol;
629 } catch (AipsError& e) {
630 delete stpol;
631 throw(e);
632 }
633 }
634 if ( arr.nelements() == 0 )
635 pushLog("Not enough polarisations present to do the conversion.");
636 arr.tovector(out);
637 return out;
638}
639
640void asap::Scantable::setSpectrum( const std::vector<float>& spec,
641 int whichrow )
642{
643 Vector<Float> spectrum(spec);
644 Vector<Float> arr;
645 specCol_.get(whichrow, arr);
646 if ( spectrum.nelements() != arr.nelements() )
647 throw AipsError("The spectrum has incorrect number of channels.");
648 specCol_.put(whichrow, spectrum);
649}
650
651
652String Scantable::generateName()
653{
654 return (File::newUniqueName("./","temp")).baseName();
655}
656
657const casa::Table& Scantable::table( ) const
658{
659 return table_;
660}
661
662casa::Table& Scantable::table( )
663{
664 return table_;
665}
666
667std::string Scantable::getPolType() const
668{
669 return table_.keywordSet().asString("POLTYPE");
670}
671
672void Scantable::unsetSelection()
673{
674 table_ = originalTable_;
675 attach();
676 selector_.reset();
677}
678
679void Scantable::setSelection( const STSelector& selection )
680{
681 Table tab = const_cast<STSelector&>(selection).apply(originalTable_);
682 if ( tab.nrow() == 0 ) {
683 throw(AipsError("Selection contains no data. Not applying it."));
684 }
685 table_ = tab;
686 attach();
687 selector_ = selection;
688}
689
690std::string Scantable::summary( bool verbose )
691{
692 // Format header info
693 ostringstream oss;
694 oss << endl;
695 oss << asap::SEPERATOR << endl;
696 oss << " Scan Table Summary" << endl;
697 oss << asap::SEPERATOR << endl;
698 oss.flags(std::ios_base::left);
699 oss << setw(15) << "Beams:" << setw(4) << nbeam() << endl
700 << setw(15) << "IFs:" << setw(4) << nif() << endl
701 << setw(15) << "Polarisations:" << setw(4) << npol()
702 << "(" << getPolType() << ")" << endl
703 << setw(15) << "Channels:" << setw(4) << nchan() << endl;
704 oss << endl;
705 String tmp;
706 oss << setw(15) << "Observer:"
707 << table_.keywordSet().asString("Observer") << endl;
708 oss << setw(15) << "Obs Date:" << getTime(-1,true) << endl;
709 table_.keywordSet().get("Project", tmp);
710 oss << setw(15) << "Project:" << tmp << endl;
711 table_.keywordSet().get("Obstype", tmp);
712 oss << setw(15) << "Obs. Type:" << tmp << endl;
713 table_.keywordSet().get("AntennaName", tmp);
714 oss << setw(15) << "Antenna Name:" << tmp << endl;
715 table_.keywordSet().get("FluxUnit", tmp);
716 oss << setw(15) << "Flux Unit:" << tmp << endl;
717 Vector<Double> vec(moleculeTable_.getRestFrequencies());
718 oss << setw(15) << "Rest Freqs:";
719 if (vec.nelements() > 0) {
720 oss << setprecision(10) << vec << " [Hz]" << endl;
721 } else {
722 oss << "none" << endl;
723 }
724
725 oss << setw(15) << "Abcissa:" << getAbcissaLabel(0) << endl;
726 oss << selector_.print() << endl;
727 oss << endl;
728 // main table
729 String dirtype = "Position ("
730 + getDirectionRefString()
731 + ")";
732 oss << setw(5) << "Scan" << setw(15) << "Source"
733 << setw(10) << "Time" << setw(18) << "Integration" << endl;
734 oss << setw(5) << "" << setw(5) << "Beam" << setw(3) << "" << dirtype << endl;
735 oss << setw(10) << "" << setw(3) << "IF" << setw(6) << ""
736 << setw(8) << "Frame" << setw(16)
737 << "RefVal" << setw(10) << "RefPix" << setw(12) << "Increment" <<endl;
738 oss << asap::SEPERATOR << endl;
739 TableIterator iter(table_, "SCANNO");
740 while (!iter.pastEnd()) {
741 Table subt = iter.table();
742 ROTableRow row(subt);
743 MEpoch::ROScalarColumn timeCol(subt,"TIME");
744 const TableRecord& rec = row.get(0);
745 oss << setw(4) << std::right << rec.asuInt("SCANNO")
746 << std::left << setw(1) << ""
747 << setw(15) << rec.asString("SRCNAME")
748 << setw(10) << formatTime(timeCol(0), false);
749 // count the cycles in the scan
750 TableIterator cyciter(subt, "CYCLENO");
751 int nint = 0;
752 while (!cyciter.pastEnd()) {
753 ++nint;
754 ++cyciter;
755 }
756 oss << setw(3) << std::right << nint << setw(3) << " x " << std::left
757 << setw(6) << formatSec(rec.asFloat("INTERVAL")) << endl;
758
759 TableIterator biter(subt, "BEAMNO");
760 while (!biter.pastEnd()) {
761 Table bsubt = biter.table();
762 ROTableRow brow(bsubt);
763 const TableRecord& brec = brow.get(0);
764 uInt row0 = bsubt.rowNumbers()[0];
765 oss << setw(5) << "" << setw(4) << std::right << brec.asuInt("BEAMNO")<< std::left;
766 oss << setw(4) << "" << formatDirection(getDirection(row0)) << endl;
767 TableIterator iiter(bsubt, "IFNO");
768 while (!iiter.pastEnd()) {
769 Table isubt = iiter.table();
770 ROTableRow irow(isubt);
771 const TableRecord& irec = irow.get(0);
772 oss << setw(10) << "";
773 oss << setw(3) << std::right << irec.asuInt("IFNO") << std::left
774 << setw(2) << "" << frequencies().print(irec.asuInt("FREQ_ID"));
775
776 ++iiter;
777 }
778 ++biter;
779 }
780 ++iter;
781 }
782 /// @todo implement verbose mode
783 return String(oss);
784}
785
786std::string Scantable::getTime(int whichrow, bool showdate) const
787{
788 MEpoch::ROScalarColumn timeCol(table_, "TIME");
789 MEpoch me;
790 if (whichrow > -1) {
791 me = timeCol(uInt(whichrow));
792 } else {
793 Double tm;
794 table_.keywordSet().get("UTC",tm);
795 me = MEpoch(MVEpoch(tm));
796 }
797 return formatTime(me, showdate);
798}
799
800std::vector< double > asap::Scantable::getAbcissa( int whichrow ) const
801{
802 if ( whichrow > int(table_.nrow()) ) throw(AipsError("Illegal ro number"));
803 std::vector<double> stlout;
804 int nchan = specCol_(whichrow).nelements();
805 String us = freqTable_.getUnitString();
806 if ( us == "" || us == "pixel" || us == "channel" ) {
807 for (int i=0; i<nchan; ++i) {
808 stlout.push_back(double(i));
809 }
810 return stlout;
811 }
812
813 const MPosition& mp = getAntennaPosition();
814 const MDirection& md = getDirection(whichrow);
815 const MEpoch& me = timeCol_(whichrow);
816 Double rf = moleculeTable_.getRestFrequency(mmolidCol_(whichrow));
817 SpectralCoordinate spc =
818 freqTable_.getSpectralCoordinate(md, mp, me, rf, mfreqidCol_(whichrow));
819 Vector<Double> pixel(nchan);
820 Vector<Double> world;
821 indgen(pixel);
822 if ( Unit(us) == Unit("Hz") ) {
823 for ( int i=0; i < nchan; ++i) {
824 Double world;
825 spc.toWorld(world, pixel[i]);
826 stlout.push_back(double(world));
827 }
828 } else if ( Unit(us) == Unit("km/s") ) {
829 Vector<Double> world;
830 spc.pixelToVelocity(world, pixel);
831 world.tovector(stlout);
832 }
833 return stlout;
834}
835void asap::Scantable::setDirectionRefString( const std::string & refstr )
836{
837 MDirection::Types mdt;
838 if (refstr != "" && !MDirection::getType(mdt, refstr)) {
839 throw(AipsError("Illegal Direction frame."));
840 }
841 if ( refstr == "" ) {
842 String defaultstr = MDirection::showType(dirCol_.getMeasRef().getType());
843 table_.rwKeywordSet().define("DIRECTIONREF", defaultstr);
844 } else {
845 table_.rwKeywordSet().define("DIRECTIONREF", String(refstr));
846 }
847}
848
849std::string asap::Scantable::getDirectionRefString( ) const
850{
851 return table_.keywordSet().asString("DIRECTIONREF");
852}
853
854MDirection Scantable::getDirection(int whichrow ) const
855{
856 String usertype = table_.keywordSet().asString("DIRECTIONREF");
857 String type = MDirection::showType(dirCol_.getMeasRef().getType());
858 if ( usertype != type ) {
859 MDirection::Types mdt;
860 if (!MDirection::getType(mdt, usertype)) {
861 throw(AipsError("Illegal Direction frame."));
862 }
863 return dirCol_.convert(uInt(whichrow), mdt);
864 } else {
865 return dirCol_(uInt(whichrow));
866 }
867}
868
869std::string Scantable::getAbcissaLabel( int whichrow ) const
870{
871 if ( whichrow > int(table_.nrow()) ) throw(AipsError("Illegal ro number"));
872 const MPosition& mp = getAntennaPosition();
873 const MDirection& md = getDirection(whichrow);
874 const MEpoch& me = timeCol_(whichrow);
875 const Double& rf = mmolidCol_(whichrow);
876 SpectralCoordinate spc =
877 freqTable_.getSpectralCoordinate(md, mp, me, rf, mfreqidCol_(whichrow));
878
879 String s = "Channel";
880 Unit u = Unit(freqTable_.getUnitString());
881 if (u == Unit("km/s")) {
882 s = CoordinateUtil::axisLabel(spc,0,True,True,True);
883 } else if (u == Unit("Hz")) {
884 Vector<String> wau(1);wau = u.getName();
885 spc.setWorldAxisUnits(wau);
886 s = CoordinateUtil::axisLabel(spc,0,True,True,False);
887 }
888 return s;
889
890}
891
892void asap::Scantable::setRestFrequencies( double rf, const std::string& unit )
893{
894 ///@todo lookup in line table to fill in name and formattedname
895 Unit u(unit);
896 Quantum<Double> urf(rf, u);
897 uInt id = moleculeTable_.addEntry(urf.getValue("Hz"), "", "");
898 TableVector<uInt> tabvec(table_, "MOLECULE_ID");
899 tabvec = id;
900}
901
902void asap::Scantable::setRestFrequencies( const std::string& name )
903{
904 throw(AipsError("setRestFrequencies( const std::string& name ) NYI"));
905 ///@todo implement
906}
907
908std::vector< unsigned int > asap::Scantable::rownumbers( ) const
909{
910 std::vector<unsigned int> stlout;
911 Vector<uInt> vec = table_.rowNumbers();
912 vec.tovector(stlout);
913 return stlout;
914}
915
916
917Matrix<Float> asap::Scantable::getPolMatrix( uInt whichrow ) const
918{
919 ROTableRow row(table_);
920 const TableRecord& rec = row.get(whichrow);
921 Table t =
922 originalTable_( originalTable_.col("SCANNO") == Int(rec.asuInt("SCANNO"))
923 && originalTable_.col("BEAMNO") == Int(rec.asuInt("BEAMNO"))
924 && originalTable_.col("IFNO") == Int(rec.asuInt("IFNO"))
925 && originalTable_.col("CYCLENO") == Int(rec.asuInt("CYCLENO")) );
926 ROArrayColumn<Float> speccol(t, "SPECTRA");
927 return speccol.getColumn();
928}
929
930std::vector< std::string > asap::Scantable::columnNames( ) const
931{
932 Vector<String> vec = table_.tableDesc().columnNames();
933 return mathutil::tovectorstring(vec);
934}
935
936casa::MEpoch::Types asap::Scantable::getTimeReference( ) const
937{
938 return MEpoch::castType(timeCol_.getMeasRef().getType());
939}
940
941void asap::Scantable::addFit( const STFitEntry & fit, int row )
942{
943 cout << mfitidCol_(uInt(row)) << endl;
944 uInt id = fitTable_.addEntry(fit, mfitidCol_(uInt(row)));
945 mfitidCol_.put(uInt(row), id);
946}
947
948
949}
950 //namespace asap
Note: See TracBrowser for help on using the repository browser.