Line data Source code
1 : //# MSContinuumSubtractor.cc: Subtract continuum from spectral line data
2 : //# Copyright (C) 2004
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //#
5 : //# This library is free software; you can redistribute it and/or modify it
6 : //# under the terms of the GNU Library General Public License as published by
7 : //# the Free Software Foundation; either version 2 of the License, or (at your
8 : //# option) any later version.
9 : //#
10 : //# This library is distributed in the hope that it will be useful, but WITHOUT
11 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 : //# License for more details.
14 : //#
15 : //# You should have received a copy of the GNU Library General Public License
16 : //# along with this library; if not, write to the Free Software Foundation,
17 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 : //#
19 : //# Correspondence concerning AIPS++ should be addressed as follows:
20 : //# Internet email: casa-feedback@nrao.edu.
21 : //# Postal address: AIPS++ Project Office
22 : //# National Radio Astronomy Observatory
23 : //# 520 Edgemont Road
24 : //# Charlottesville, VA 22903-2475 USA
25 : //#
26 : //# $Id$
27 : //#
28 :
29 : #include <spectrallines/Splatalogue/SplatalogueTable.h>
30 :
31 : #include <casacore/casa/Exceptions/Error.h>
32 : #include <casacore/casa/Quanta/MVTime.h>
33 : #include <casacore/tables/TaQL/ExprNode.h>
34 :
35 : #include <casacore/tables/Tables/ScaColDesc.h>
36 : #include <casacore/tables/Tables/ScalarColumn.h>
37 : #include <iomanip>
38 :
39 : #include <iostream>
40 : using namespace std;
41 :
42 : using namespace casacore;
43 : namespace casa {
44 :
45 : const String SplatalogueTable::SPECIES = "SPECIES";
46 : const String SplatalogueTable::RECOMMENDED = "RECOMMENDED";
47 : const String SplatalogueTable::CHEMICAL_NAME = "CHEMICAL_NAME";
48 : const String SplatalogueTable::FREQUENCY = "FREQUENCY";
49 : const String SplatalogueTable::QUANTUM_NUMBERS = "QUANTUM_NUMBERS";
50 : const String SplatalogueTable::INTENSITY = "INTENSITY";
51 : const String SplatalogueTable::SMU2 = "SMU2";
52 : const String SplatalogueTable::LOGA = "LOGA";
53 : const String SplatalogueTable::EL = "EL";
54 : const String SplatalogueTable::EU = "EU";
55 : const String SplatalogueTable::LINELIST = "LINELIST";
56 : const String SplatalogueTable::ISSPLAT = "isSplat";
57 :
58 : const String SplatalogueTable::RECORD_VALUE = "value";
59 : const String SplatalogueTable::RECORD_UNIT = "unit";
60 : const String SplatalogueTable::RECORD_SPECIES = "species";
61 : const String SplatalogueTable::RECORD_RECOMMENDED = "recommended";
62 : const String SplatalogueTable::RECORD_CHEMNAME = "chemname";
63 : const String SplatalogueTable::RECORD_FREQUENCY = "freq";
64 : const String SplatalogueTable::RECORD_QNS = "qns";
65 : const String SplatalogueTable::RECORD_INTENSITY = "intensity";
66 : const String SplatalogueTable::RECORD_SMU2 = "smu2";
67 : const String SplatalogueTable::RECORD_LOGA = "loga";
68 : const String SplatalogueTable::RECORD_EL = "el";
69 : const String SplatalogueTable::RECORD_EU = "eu";
70 : const String SplatalogueTable::RECORD_LINE_LIST = "linelist";
71 :
72 0 : SplatalogueTable::SplatalogueTable(
73 : SetupNewTable& snt, uInt nrow,
74 : const String& freqUnit, const String& smu2Unit,
75 : const String& elUnit, const String& euUnit
76 0 : ) : Table(snt, nrow), _freqUnit(freqUnit), _smu2Unit(smu2Unit),
77 0 : _elUnit(elUnit), _euUnit(euUnit) {
78 0 : _construct(true);
79 0 : }
80 :
81 0 : SplatalogueTable::SplatalogueTable(
82 : const String& tablename
83 0 : ) : Table(tablename) {
84 0 : _construct(false);
85 0 : }
86 :
87 0 : SplatalogueTable::SplatalogueTable(
88 : const Table& table
89 0 : ) : Table(table) {
90 0 : _construct(false);
91 0 : }
92 :
93 0 : String SplatalogueTable::getFrequencyUnit() const {
94 0 : return _freqUnit;
95 : }
96 :
97 0 : String SplatalogueTable::list() const {
98 0 : ScalarColumn<String> species(*this, SPECIES);
99 0 : ScalarColumn<Bool> recommended(*this, RECOMMENDED);
100 0 : ScalarColumn<String> chemName(*this, CHEMICAL_NAME);
101 0 : ScalarColumn<Double> freq(*this, FREQUENCY);
102 0 : ScalarColumn<String> qns(*this, QUANTUM_NUMBERS);
103 0 : ScalarColumn<Float> intensity(*this, INTENSITY);
104 0 : ScalarColumn<Float> smu2(*this, SMU2);
105 0 : ScalarColumn<Float> logA(*this, LOGA);
106 0 : ScalarColumn<Float> el(*this, EL);
107 0 : ScalarColumn<Float> eu(*this, EU);
108 0 : ScalarColumn<String> linelist(*this, LINELIST);
109 :
110 : char cspecies[15], crec[11], cchemName[21], cfreq[12], cqns[21],
111 : cintensity[10], csmu2[10], clogA[10], cel[10], ceu[10],
112 : clinelist[11];
113 0 : ostringstream os;
114 0 : String rec;
115 0 : os << SPECIES << " " << RECOMMENDED << " "
116 0 : << CHEMICAL_NAME << " " << FREQUENCY << " "
117 0 : << QUANTUM_NUMBERS << " " << INTENSITY << " "
118 0 : << SMU2 << " " << LOGA << " "
119 0 : << EL << " " << EU << " " << LINELIST << endl;
120 0 : for (uInt i=0; i<nrow(); i++) {
121 0 : sprintf(cspecies, "%-14.14s", species.asString(i).chars());
122 0 : rec = recommended.asBool(i) ? "*" : " ";
123 0 : sprintf(crec, "%10.10s", rec.chars());
124 0 : sprintf(cchemName, "%-20.20s", chemName.asString(i).chars());
125 0 : sprintf(cfreq, "%11.6f", freq.asdouble(i));
126 0 : sprintf(cqns, "%-20.20s", qns.asString(i).chars());
127 0 : sprintf(cintensity, "%9.5f", intensity.asfloat(i));
128 0 : sprintf(csmu2, "%9.5f", smu2.asfloat(i));
129 0 : sprintf(clogA, "%9.5f", logA.asfloat(i));
130 0 : sprintf(cel, "%9.5f", el.asfloat(i));
131 0 : sprintf(ceu, "%9.5f", eu.asfloat(i));
132 0 : sprintf(clinelist, "%-10.10s", linelist.asString(i).chars());
133 :
134 : os << cspecies << " " << crec << " " << cchemName
135 : << " " << cfreq << " " << cqns << " " << cintensity
136 : << " " << csmu2 << " " << clogA << " " << cel
137 0 : << " " << ceu << " " << clinelist << endl;
138 : }
139 0 : return os.str();
140 0 : }
141 :
142 : namespace {
143 : template <typename T>
144 : class Kluge {
145 :
146 : // The latest casacore mode changed the signature to the TableExprNode::getColumnTYPE
147 : // methods. Since SplatalogueTable::toRecord is the only code that is using them,
148 : // I've installed a very limited kluge to fix this issue. FYI: The casacore mod changed
149 : // the casacore mode now requires an array of row numbers rather than defaulting to all
150 : // rows(?). jjacobs 12/17/12
151 :
152 :
153 : public:
154 :
155 : typedef Array<T> (TableExprNode::* Extractor) (const RowNumbers& rownrs) const;
156 :
157 : static Array<T>
158 0 : extract (const TableExprNode & col, Extractor extractor)
159 : {
160 0 : Vector<rownr_t> rownrs (col.nrow());
161 0 : indgen (rownrs);
162 :
163 0 : return ((& col) ->* extractor) (RowNumbers(rownrs));
164 :
165 0 : }
166 :
167 : };
168 : }
169 :
170 0 : Record SplatalogueTable::toRecord() const {
171 :
172 0 : Array<String> species = Kluge<String>::extract (col(SPECIES), & TableExprNode::getColumnString);
173 0 : Array<Bool> recommended = Kluge<Bool>::extract (col(RECOMMENDED), & TableExprNode::getColumnBool);
174 0 : Array<String> chemName = Kluge<String>::extract (col(CHEMICAL_NAME), & TableExprNode::getColumnString);
175 0 : Array<Double> freq = Kluge<Double>::extract (col(FREQUENCY), & TableExprNode::getColumnDouble);
176 0 : Array<String> qns = Kluge<String>::extract (col(QUANTUM_NUMBERS), & TableExprNode::getColumnString);
177 0 : Array<Float> intensity = Kluge<Float>::extract (col(INTENSITY), & TableExprNode::getColumnFloat);
178 0 : Array<Float> smu2 = Kluge<Float>::extract (col(SMU2), & TableExprNode::getColumnFloat);
179 0 : Array<Float> loga = Kluge<Float>::extract (col(LOGA), & TableExprNode::getColumnFloat);
180 0 : Array<Float> el = Kluge<Float>::extract (col(EL), & TableExprNode::getColumnFloat);
181 0 : Array<Float> eu = Kluge<Float>::extract (col(EU), & TableExprNode::getColumnFloat);
182 0 : Array<String> linelist = Kluge<String>::extract (col(LINELIST), & TableExprNode::getColumnString);
183 :
184 : // Array<String> species = col(SPECIES).getColumnString();
185 : // Array<Bool> recommended = col(RECOMMENDED).getColumnBool();
186 : // Array<String> chemName = col(CHEMICAL_NAME).getColumnString();
187 : // Array<Double> freq = col(FREQUENCY).getColumnDouble();
188 : // Array<String> qns = col(QUANTUM_NUMBERS).getColumnString();
189 : // Array<Float> intensity = col(INTENSITY).getColumnFloat();
190 : // Array<Float> smu2 = col(SMU2).getColumnFloat();
191 : // Array<Float> loga = col(LOGA).getColumnFloat();
192 : // Array<Float> el = col(EL).getColumnFloat();
193 : // Array<Float> eu = col(EU).getColumnFloat();
194 : // Array<String> linelist = col(LINELIST).getColumnString();
195 :
196 0 : IPosition idx = IPosition(1, 0);
197 0 : Record rec;
198 0 : Record qFreq;
199 0 : qFreq.define(RECORD_VALUE, 0.0);
200 0 : qFreq.define(RECORD_UNIT, _freqUnit);
201 0 : Record qSmu2;
202 0 : qSmu2.define(RECORD_VALUE, 0.0f);
203 :
204 0 : qSmu2.define(RECORD_UNIT, _smu2Unit);
205 0 : Record qel = qSmu2;
206 0 : qel.define(RECORD_UNIT, _elUnit);
207 0 : Record qeu = qSmu2;
208 0 : qeu.define(RECORD_UNIT, _euUnit);
209 0 : for (uInt i=0; i<species.size(); i++) {
210 0 : idx[0] = i;
211 0 : Record line;
212 0 : line.define(RECORD_SPECIES, species(idx));
213 0 : line.define(RECORD_RECOMMENDED, recommended(idx));
214 0 : line.define(RECORD_CHEMNAME, chemName(idx));
215 0 : qFreq.define(RECORD_VALUE, freq(idx));
216 0 : line.defineRecord(RECORD_FREQUENCY, qFreq);
217 0 : line.define(RECORD_QNS, qns(idx));
218 0 : line.define(RECORD_INTENSITY, intensity(idx));
219 0 : qSmu2.define(RECORD_VALUE, smu2(idx));
220 0 : line.defineRecord(RECORD_SMU2, qSmu2);
221 0 : line.define(RECORD_LOGA, loga(idx));
222 0 : qel.define(RECORD_VALUE, el(idx));
223 0 : line.defineRecord(RECORD_EL, qel);
224 0 : qeu.define(RECORD_VALUE, eu(idx));
225 0 : line.defineRecord(RECORD_EU, qeu);
226 0 : line.define(RECORD_LINE_LIST, linelist(idx));
227 0 : rec.defineRecord("*" + String::toString(i), line);
228 0 : }
229 0 : return rec;
230 0 : }
231 :
232 0 : void SplatalogueTable::_construct(const Bool setup) {
233 0 : if (
234 0 : ! setup
235 0 : && (
236 0 : ! keywordSet().isDefined(ISSPLAT)
237 0 : || ! keywordSet().asBool(ISSPLAT)
238 : )
239 : ) {
240 0 : throw AipsError("Table is not a splatalogue table");
241 : }
242 0 : Vector<String> colNames = tableDesc().columnNames();
243 0 : Vector<String> reqColNames(11);
244 0 : if (colNames.size() != reqColNames.size()) {
245 0 : throw AipsError("Table does not have the required number of columns to be a Splatalogue table");
246 : }
247 :
248 0 : reqColNames[0] = SPECIES;
249 0 : reqColNames[1] = RECOMMENDED;
250 0 : reqColNames[2] = CHEMICAL_NAME;
251 0 : reqColNames[3] = FREQUENCY;
252 0 : reqColNames[4] = QUANTUM_NUMBERS;
253 0 : reqColNames[5] = INTENSITY;
254 0 : reqColNames[6] = SMU2;
255 0 : reqColNames[7] = LOGA;
256 0 : reqColNames[8] = EL;
257 0 : reqColNames[9] = EU;
258 0 : reqColNames[10] = LINELIST;
259 0 : for (
260 0 : Vector<String>::const_iterator riter=reqColNames.begin();
261 0 : riter!=reqColNames.end(); riter++
262 : ) {
263 0 : Bool found = false;
264 0 : for (
265 0 : Vector<String>::const_iterator iter=colNames.begin();
266 0 : iter!=colNames.end(); iter++
267 : ) {
268 0 : if (*iter == *riter) {
269 0 : found = true;
270 0 : break;
271 : }
272 0 : }
273 0 : if (! found) {
274 0 : throw AipsError("Column " + *riter + " does not exist in the input table.");
275 : }
276 0 : }
277 : // TODO also check column data types
278 0 : if (setup) {
279 0 : Bool writable = isWritable();
280 0 : if (! writable) {
281 0 : reopenRW();
282 : }
283 0 : _addKeywords();
284 : }
285 : else {
286 0 : ScalarColumn<Double> freq(*this, FREQUENCY);
287 0 : _freqUnit = freq.keywordSet().asString("Unit");
288 0 : ScalarColumn<Float> smu2(*this, SMU2);
289 0 : _smu2Unit = smu2.keywordSet().asString("Unit");
290 0 : if (_smu2Unit.empty()) {
291 0 : _smu2Unit = "Debye2";
292 : }
293 0 : ScalarColumn<Float> el(*this, EL);
294 0 : _elUnit = el.keywordSet().asString("Unit");
295 0 : if (_elUnit.empty()) {
296 0 : _elUnit = "K";
297 : }
298 0 : ScalarColumn<Float> eu(*this, EU);
299 0 : _euUnit = eu.keywordSet().asString("Unit");
300 0 : if (_euUnit.empty()) {
301 0 : _euUnit = "K";
302 : }
303 0 : }
304 0 : }
305 :
306 :
307 0 : void SplatalogueTable::_addKeywords() {
308 0 : if (_freqUnit.empty()) {
309 0 : _freqUnit = "GHz";
310 : }
311 0 : ScalarColumn<Double> freq(*this, FREQUENCY);
312 0 : freq.rwKeywordSet().define("Unit", _freqUnit);
313 0 : ScalarColumn<Float> smu2(*this, SMU2);
314 0 : smu2.rwKeywordSet().define("Unit", _smu2Unit);
315 0 : ScalarColumn<Float> el(*this, EL);
316 0 : el.rwKeywordSet().define("Unit", _elUnit);
317 0 : ScalarColumn<Float> eu(*this, EU);
318 0 : eu.rwKeywordSet().define("Unit", _euUnit);
319 0 : rwKeywordSet().define(ISSPLAT, true);
320 0 : Time now;
321 0 : MVTime mv(now);
322 0 : mv.setFormat(MVTime::YMD, 3);
323 0 : String timeString = mv.string();
324 0 : timeString = String(timeString.before(timeString.size() - 1));
325 : // These are required by the standard measures loading code.
326 0 : rwKeywordSet().define("VS_CREATE", timeString);
327 0 : rwKeywordSet().define("VS_DATE", timeString);
328 0 : rwKeywordSet().define("VS_VERSION", timeString);
329 0 : rwKeywordSet().define("VS_TYPE", "List of spectral lines in Splatalogue format");
330 0 : tableInfo().setType("IERS");
331 0 : }
332 :
333 : } //# NAMESPACE CASA - END
334 :
|