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: aips2-request@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/SearchEngine.h>
30 :
31 : #include <casacore/casa/Containers/Record.h>
32 : #include <casacore/casa/IO/FiledesIO.h>
33 :
34 : #include <casacore/casa/OS/File.h>
35 : #include <imageanalysis/ImageAnalysis/ImageInputProcessor.h>
36 : #include <casacore/tables/Tables/ScalarColumn.h>
37 : #include <casacore/tables/TaQL/TableParse.h>
38 : #include <fcntl.h>
39 : #include <memory>
40 :
41 : #include <iostream>
42 : using namespace std;
43 :
44 : using namespace casacore;
45 : namespace casa {
46 :
47 58 : SearchEngine::SearchEngine(
48 : const SplatalogueTable* const table, const Bool list,
49 : const String& logfile, const Bool append
50 58 : ) : _log(new LogIO), _table(table), _logfile(logfile),
51 58 : _list(list), _append(append){
52 58 : if (!logfile.empty()) {
53 12 : OutputDestinationChecker::OutputStruct logfile;
54 6 : logfile.label = "logfile";
55 6 : logfile.outputFile = &_logfile;
56 6 : logfile.required = true;
57 6 : logfile.replaceable = true;
58 12 : vector<OutputDestinationChecker::OutputStruct> output(1);
59 6 : output[0] = logfile;
60 6 : OutputDestinationChecker::checkOutputs(&output, *_log);
61 : }
62 58 : }
63 :
64 58 : SearchEngine::~SearchEngine() {
65 58 : delete _log;
66 58 : }
67 :
68 58 : SplatalogueTable* SearchEngine::search(
69 : const String& resultsTableName, const Double freqLow, const Double freqHigh,
70 : const Vector<String>& species, const Bool recommendedOnly,
71 : const Vector<String>& chemNames, const Vector<String>& qns,
72 : const Double intensityLow, const Double intensityHigh,
73 : const Double smu2Low, const Double smu2High,
74 : const Double logaLow, const Double logaHigh,
75 : const Double elLow, const Double elHigh,
76 : const Double euLow, const Double euHigh,
77 : const Bool includeRRLs, const Bool onlyRRLs
78 : ) const {
79 174 : LogOrigin origin("SearchEngine", __FUNCTION__);
80 58 : *_log << origin;
81 58 : if (! resultsTableName.empty()) {
82 60 : File tab(resultsTableName);
83 30 : if (! tab.canCreate()) {
84 0 : *_log << "Cannot create table " << resultsTableName << LogIO::EXCEPTION;
85 : }
86 : }
87 116 : ostringstream query;
88 58 : query << "SELECT FROM " << _table->tableName();
89 58 : query << " WHERE ";
90 :
91 58 : query << "(" << _getBetweenClause(SplatalogueTable::FREQUENCY, freqLow, freqHigh) << ")";
92 58 : if (species.size() > 0) {
93 4 : query << " AND (" << SplatalogueTable::SPECIES << " IN (";
94 10 : for (uInt i=0; i<species.size(); i++) {
95 6 : query << "'" << species[i] << "'";
96 6 : if (i != species.size() - 1) {
97 2 : query << ", ";
98 : }
99 : }
100 4 : query << "))";
101 : }
102 :
103 58 : if (recommendedOnly) {
104 58 : query << " AND (" << SplatalogueTable::RECOMMENDED << ")";
105 : }
106 :
107 58 : if (chemNames.size() > 0) {
108 4 : query << " AND (" << SplatalogueTable::CHEMICAL_NAME << " IN (";
109 10 : for (uInt i=0; i<chemNames.size(); i++) {
110 6 : query << "'" << chemNames[i] << "'";
111 6 : if (i != chemNames.size() - 1) {
112 2 : query << ", ";
113 : }
114 : }
115 4 : query << "))";
116 : }
117 58 : if (qns.size() > 0) {
118 2 : query << " AND (" << SplatalogueTable::QUANTUM_NUMBERS << " IN (";
119 4 : for (uInt i=0; i<qns.size(); i++) {
120 2 : query << "'" << qns[i] << "'";
121 2 : if (i != qns.size() - 1) {
122 0 : query << ", ";
123 : }
124 : }
125 2 : query << "))";
126 : }
127 18 : String rrlPortion = (includeRRLs || onlyRRLs)
128 : ? "LINELIST = 'Recomb'"
129 134 : : "";
130 116 : ostringstream nonRRLPortion;
131 58 : if (! onlyRRLs) {
132 50 : nonRRLPortion << "(LINELIST != 'Recomb')";
133 50 : if (intensityLow < intensityHigh) {
134 8 : nonRRLPortion << " AND " << _getBetweenClause(
135 : SplatalogueTable::INTENSITY, intensityLow, intensityHigh
136 4 : );
137 : }
138 50 : if (smu2Low < smu2High) {
139 8 : nonRRLPortion << " AND " << _getBetweenClause(
140 : SplatalogueTable::SMU2, smu2Low, smu2High
141 4 : );
142 : }
143 50 : if (logaLow < logaHigh) {
144 8 : nonRRLPortion << " AND " << _getBetweenClause(
145 : SplatalogueTable::LOGA, logaLow, logaHigh
146 4 : );
147 : }
148 50 : if (elLow < elHigh) {
149 16 : nonRRLPortion << " AND " << _getBetweenClause(
150 : SplatalogueTable::EL, elLow, elHigh
151 8 : );
152 : }
153 50 : if (euLow < euHigh) {
154 16 : nonRRLPortion << " AND " << _getBetweenClause(
155 : SplatalogueTable::EU, euLow, euHigh
156 8 : );
157 : }
158 : }
159 58 : if (onlyRRLs) {
160 8 : query << " AND " << rrlPortion;
161 : }
162 50 : else if (includeRRLs) {
163 32 : query << " AND ((" << rrlPortion << ") OR (" << nonRRLPortion.str() << "))";
164 : }
165 : else {
166 18 : query << " AND " << nonRRLPortion.str();
167 : }
168 58 : query << " ORDER BY " << SplatalogueTable::FREQUENCY;
169 :
170 174 : Table resTable = _runQuery(query.str());
171 116 : std::unique_ptr<SplatalogueTable> resSplatTable(new SplatalogueTable(resTable));
172 58 : if (!resultsTableName.empty()) {
173 30 : resSplatTable->rename(resultsTableName, Table::NewNoReplace);
174 30 : resSplatTable->flush(true, true);
175 : }
176 58 : if (_list) {
177 4 : _logIt(resSplatTable->list());
178 : }
179 116 : return resSplatTable.release();
180 : }
181 :
182 0 : Vector<String> SearchEngine::uniqueSpecies() const {
183 0 : String query = "SELECT UNIQUE(" + SplatalogueTable::SPECIES
184 0 : + ") FROM " + _table->tableName() + " ORDER BY " + SplatalogueTable::SPECIES;
185 : // Table resTable = tableCommand(query).table();
186 0 : Table resTable = _runQuery(query);
187 :
188 0 : String logString;
189 0 : ScalarColumn<String> species(resTable, SplatalogueTable::SPECIES);
190 0 : Vector<String> vSpecies(species.nrow());
191 0 : for (uInt i=0; i<species.nrow(); i++) {
192 0 : vSpecies[i] = species(i);
193 0 : logString += species(i) + "\n";
194 : }
195 0 : _logIt(logString);
196 0 : return vSpecies;
197 : }
198 :
199 0 : Vector<String> SearchEngine::uniqueChemicalNames() const {
200 0 : String query = "SELECT UNIQUE(" + SplatalogueTable::CHEMICAL_NAME
201 0 : + ") FROM " + _table->tableName() + " ORDER BY " + SplatalogueTable::CHEMICAL_NAME;
202 : // Table resTable = tableCommand(query).table();
203 0 : Table resTable = _runQuery(query);
204 :
205 0 : ScalarColumn<String> chemNames(resTable, SplatalogueTable::CHEMICAL_NAME);
206 0 : Vector<String> vChemNames(chemNames.nrow());
207 0 : String logString;
208 0 : for (uInt i=0; i<chemNames.nrow(); i++) {
209 0 : vChemNames[i] = chemNames(i);
210 0 : logString += chemNames(i) + "\n";
211 : }
212 0 : _logIt(logString);
213 0 : return vChemNames;
214 : }
215 :
216 86 : String SearchEngine::_getBetweenClause(
217 : const String& col, const Double low, const Double high
218 : ) const {
219 86 : ostringstream os;
220 86 : os << col << " BETWEEN " << low << " AND " << high;
221 172 : return os.str();
222 : }
223 :
224 58 : Table SearchEngine::_runQuery(const String& query) const {
225 116 : String tablename = _table->tableName();
226 116 : File file(tablename);
227 58 : Bool dump = false;
228 116 : String queryCopy = query;
229 58 : if (! file.exists()) {
230 0 : *_log << LogIO::NORMAL << "Flushing a copy of " << tablename << " to disk so it can be queried" << LogIO::POST;
231 0 : Path newName = File::newUniqueName(".");
232 0 : uInt pos = query.find(tablename);
233 0 : uInt length = tablename.length();
234 0 : tablename = newName.absoluteName();
235 0 : _table->deepCopy(tablename, Table::Scratch, true, Table::AipsrcEndian, false);
236 0 : dump = true;
237 0 : cout << "query " << query << endl;
238 0 : cout << "new table " << tablename << endl;
239 0 : String begin = query.substr(0, pos);
240 0 : String end = query.substr(pos+length, query.length());
241 0 : queryCopy = begin + tablename + end;
242 0 : cout << "new query " << queryCopy << endl;
243 :
244 : }
245 58 : Table resTable = tableCommand(queryCopy).table();
246 58 : if (dump) {
247 0 : Table t(tablename);
248 0 : t.markForDelete();
249 : //*_log << LogIO::NORMAL << "Removing temporary disk copy " << tablename << LogIO::POST;
250 : //Table::deleteTable(tablename, true);
251 : }
252 116 : return resTable;
253 : }
254 :
255 4 : void SearchEngine::_logIt(const String& logString) const {
256 8 : LogOrigin origin("SearchEngine", __FUNCTION__);
257 4 : *_log << origin << logString << LogIO::POST;
258 4 : if (! _list) {
259 0 : return;
260 : }
261 4 : if (! _logfile.empty()) {
262 8 : File log(_logfile);
263 4 : switch (File::FileWriteStatus status = log.getWriteStatus()) {
264 3 : case File::OVERWRITABLE:
265 3 : if (_append) {
266 2 : Int fd = open(_logfile.c_str(), O_RDWR | O_APPEND);
267 4 : FiledesIO fio(fd, _logfile.c_str());
268 2 : fio.write(logString.length(), logString.c_str());
269 2 : FiledesIO::close(fd);
270 2 : *_log << LogIO::NORMAL << "Appended results to file "
271 2 : << _logfile << LogIO::POST;
272 : }
273 : // no break here to fall through to the File::CREATABLE block if logFileAppend is false
274 : case File::CREATABLE:
275 4 : if (status == File::CREATABLE || ! _append) {
276 : // can fall through from previous case block so status can be File::OVERWRITABLE
277 4 : String action = (status == File::OVERWRITABLE) ? "Overwrote" : "Created";
278 2 : Int fd = FiledesIO::create(_logfile.c_str());
279 4 : FiledesIO fio (fd, _logfile.c_str());
280 2 : fio.write(logString.length(), logString.c_str());
281 2 : FiledesIO::close(fd);
282 2 : *_log << LogIO::NORMAL << action << " file "
283 2 : << _logfile << " with new log file"
284 2 : << LogIO::POST;
285 : }
286 4 : break;
287 0 : default:
288 : // checks to see if the log file is not creatable or not writeable should have already been
289 : // done and if so _logFileName set to the empty string so this method wouldn't be called in
290 : // those cases.
291 0 : *_log << "Programming logic error. This block should never be reached" << LogIO::EXCEPTION;
292 : }
293 : }
294 :
295 : }
296 :
297 :
298 : } //# NAMESPACE CASA - END
299 :
|