Line data Source code
1 : /*
2 : * Scantable2MSReader.cc
3 : *
4 : * Created on: Jan 5, 2016
5 : * Author: nakazato
6 : */
7 :
8 : #include <singledishfiller/Filler/Scantable2MSReader.h>
9 :
10 : #include <iostream>
11 : #include <string>
12 :
13 : #include <casacore/casa/OS/File.h>
14 : #include <casacore/casa/Containers/Record.h>
15 : #include <casacore/casa/Utilities/Regex.h>
16 : #include <casacore/tables/Tables/TableRecord.h>
17 : #include <casacore/casa/Arrays/Vector.h>
18 : #include <casacore/casa/Arrays/ArrayMath.h>
19 : #include <casacore/casa/IO/ArrayIO.h>
20 : #include <casacore/tables/Tables/Table.h>
21 : #include <casacore/measures/Measures/Stokes.h>
22 :
23 : using namespace casacore;
24 :
25 : namespace {
26 0 : Double queryAntennaDiameter(String const &name) {
27 0 : String capitalized = name;
28 0 : capitalized.upcase();
29 0 : Double diameter = 0.0;
30 0 : if (capitalized.matches(Regex(".*(DV|DA|PM)[0-9]+$"))) {
31 0 : diameter = 12.0;
32 0 : } else if (capitalized.matches(Regex(".*CM[0-9]+$"))) {
33 0 : diameter = 7.0;
34 0 : } else if (capitalized.contains("GBT")) {
35 0 : diameter = 104.9;
36 0 : } else if (capitalized.contains("MOPRA")) {
37 0 : diameter = 22.0;
38 0 : } else if (capitalized.contains("PKS") || capitalized.contains("PARKS")) {
39 0 : diameter = 64.0;
40 0 : } else if (capitalized.contains("TIDBINBILLA")) {
41 0 : diameter = 70.0;
42 0 : } else if (capitalized.contains("CEDUNA")) {
43 0 : diameter = 30.0;
44 0 : } else if (capitalized.contains("HOBART")) {
45 0 : diameter = 26.0;
46 0 : } else if (capitalized.contains("APEX")) {
47 0 : diameter = 12.0;
48 0 : } else if (capitalized.contains("ASTE")) {
49 0 : diameter = 10.0;
50 0 : } else if (capitalized.contains("NRO")) {
51 0 : diameter = 45.0;
52 : }
53 :
54 0 : return diameter;
55 : }
56 :
57 : template<class T, class U>
58 0 : U getMapValue(std::map<T, U> const mymap, T const key, U const default_value) {
59 0 : auto iter = mymap.find(key);
60 0 : if (iter != mymap.end()) {
61 0 : return iter->second;
62 : } else {
63 0 : return default_value;
64 : }
65 : }
66 :
67 0 : String getIntent(Int srctype) {
68 0 : static std::map<Int, String> intent_map;
69 0 : if (intent_map.size() == 0) {
70 0 : String sep1 = "#";
71 0 : String sep2 = ",";
72 0 : String target = "OBSERVE_TARGET";
73 0 : String atmcal = "CALIBRATE_ATMOSPHERE";
74 0 : String anycal = "CALIBRATE_SOMETHING";
75 0 : String onstr = "ON_SOURCE";
76 0 : String offstr = "OFF_SOURCE";
77 0 : String pswitch = "POSITION_SWITCH";
78 0 : String nod = "NOD";
79 0 : String fswitch = "FREQUENCY_SWITCH";
80 0 : String sigstr = "SIG";
81 0 : String refstr = "REF";
82 0 : String hot = "HOT";
83 0 : String warm = "WARM";
84 0 : String cold = "COLD";
85 0 : String unspecified = "UNSPECIFIED";
86 0 : String ftlow = "LOWER";
87 0 : String fthigh = "HIGHER";
88 0 : intent_map[0] = target + sep1 + onstr + sep2 + pswitch;
89 0 : intent_map[1] = target + sep1 + offstr + sep2 + pswitch;
90 0 : intent_map[2] = target + sep1 + onstr + sep2 + nod;
91 0 : intent_map[3] = target + sep1 + onstr + sep2 + fswitch + sep1 + sigstr;
92 0 : intent_map[4] = target + sep1 + onstr + sep2 + fswitch + sep1 + refstr;
93 0 : intent_map[6] = atmcal + sep1 + offstr + sep2 + unspecified;
94 0 : intent_map[7] = atmcal + sep1 + hot + sep2 + unspecified;
95 0 : intent_map[8] = atmcal + sep1 + warm + sep2 + unspecified;
96 0 : intent_map[9] = atmcal + sep1 + cold + sep2 + unspecified;
97 0 : intent_map[10] = atmcal + sep1 + onstr + sep2 + pswitch;
98 0 : intent_map[11] = atmcal + sep1 + offstr + sep2 + pswitch;
99 0 : intent_map[12] = atmcal + sep1 + onstr + sep2 + nod;
100 0 : intent_map[13] = atmcal + sep1 + onstr + sep2 + fswitch + sep1 + sigstr;
101 0 : intent_map[14] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + refstr;
102 0 : intent_map[20] = target + sep1 + onstr + sep2 + fswitch + sep1 + ftlow;
103 0 : intent_map[21] = target + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
104 0 : intent_map[26] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
105 0 : intent_map[27] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
106 0 : intent_map[28] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
107 0 : intent_map[29] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
108 0 : intent_map[30] = target + sep1 + onstr + sep2 + fswitch + sep1 + fthigh;
109 0 : intent_map[31] = target + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
110 0 : intent_map[36] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
111 0 : intent_map[37] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
112 0 : intent_map[38] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
113 0 : intent_map[39] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
114 0 : intent_map[90] = target + sep1 + onstr + sep2 + unspecified;
115 0 : intent_map[91] = target + sep1 + offstr + sep2 + unspecified;
116 0 : intent_map[92] = anycal + sep1 + offstr + sep2 + unspecified;
117 : }
118 0 : String default_type = "UNKNOWN_INTENT";
119 0 : return getMapValue(intent_map, srctype, default_type);
120 : }
121 :
122 0 : Int getSubscan(Int srctype) {
123 0 : static std::map<Int, Int> subscan_map;
124 0 : if (subscan_map.size() == 0) {
125 0 : subscan_map[0] = 1;
126 0 : subscan_map[1] = 2;
127 0 : subscan_map[2] = 1;
128 0 : subscan_map[3] = 1;
129 0 : subscan_map[4] = 2;
130 0 : subscan_map[6] = 1;
131 0 : subscan_map[7] = 2;
132 0 : subscan_map[8] = 3;
133 0 : subscan_map[9] = 4;
134 0 : subscan_map[10] = 5;
135 0 : subscan_map[11] = 6;
136 0 : subscan_map[12] = 7;
137 0 : subscan_map[13] = 8;
138 0 : subscan_map[14] = 9;
139 0 : subscan_map[20] = 1;
140 0 : subscan_map[21] = 2;
141 0 : subscan_map[26] = 1;
142 0 : subscan_map[27] = 2;
143 0 : subscan_map[28] = 3;
144 0 : subscan_map[29] = 4;
145 0 : subscan_map[30] = 3;
146 0 : subscan_map[31] = 4;
147 0 : subscan_map[36] = 5;
148 0 : subscan_map[37] = 6;
149 0 : subscan_map[38] = 7;
150 0 : subscan_map[39] = 8;
151 0 : subscan_map[90] = 1;
152 0 : subscan_map[91] = 2;
153 0 : subscan_map[92] = 1;
154 : }
155 0 : Int default_subscan = 1;
156 0 : return getMapValue(subscan_map, srctype, default_subscan);
157 : }
158 :
159 0 : casacore::Stokes::StokesTypes getPol(uInt const polno, casacore::String const poltype) {
160 0 : casacore::Stokes::StokesTypes stokes = casacore::Stokes::Undefined;
161 0 : if (poltype == "linear") {
162 0 : switch (polno) {
163 0 : case 0:
164 0 : stokes = casacore::Stokes::XX;
165 0 : break;
166 0 : case 1:
167 0 : stokes = casacore::Stokes::YY;
168 0 : break;
169 0 : case 2:
170 0 : stokes = casacore::Stokes::XY;
171 0 : break;
172 0 : case 3:
173 0 : stokes = casacore::Stokes::YX;
174 : }
175 0 : } else if (poltype == "circular") {
176 0 : switch (polno) {
177 0 : case 0:
178 0 : stokes = casacore::Stokes::RR;
179 0 : break;
180 0 : case 1:
181 0 : stokes = casacore::Stokes::LL;
182 0 : break;
183 0 : case 2:
184 0 : stokes = casacore::Stokes::RL;
185 0 : break;
186 0 : case 3:
187 0 : stokes = casacore::Stokes::LR;
188 0 : break;
189 : }
190 0 : } else if (poltype == "stokes") {
191 0 : switch (polno) {
192 0 : case 0:
193 0 : stokes = casacore::Stokes::I;
194 0 : break;
195 0 : case 1:
196 0 : stokes = casacore::Stokes::Q;
197 0 : break;
198 0 : case 2:
199 0 : stokes = casacore::Stokes::U;
200 0 : break;
201 0 : case 3:
202 0 : stokes = casacore::Stokes::V;
203 0 : break;
204 : }
205 0 : } else if (poltype == "linpol") {
206 0 : switch (polno) {
207 0 : case 0:
208 0 : stokes = casacore::Stokes::Plinear;
209 0 : break;
210 0 : case 1:
211 0 : stokes = casacore::Stokes::Pangle;
212 0 : break;
213 : }
214 : } else {
215 : throw casacore::AipsError(
216 0 : casacore::String("Invalid poltype") + poltype);
217 : }
218 0 : if (stokes == casacore::Stokes::Undefined) {
219 : throw casacore::AipsError(
220 0 : casacore::String("Invalid polno for type ") + poltype);
221 : }
222 0 : return stokes;
223 : }
224 : }
225 :
226 : using namespace casacore;
227 : namespace casa { //# NAMESPACE CASA - BEGIN
228 :
229 : using namespace sdfiller;
230 :
231 0 : Scantable2MSReader::Scantable2MSReader(std::string const &scantable_name) :
232 : ReaderInterface(scantable_name), main_table_(nullptr), tcal_table_(),
233 : weather_table_(), scan_column_(), cycle_column_(), ifno_column_(),
234 : polno_column_(), beam_column_(), flagrow_column_(), time_column_(),
235 : interval_column_(), srctype_column_(), data_column_(), flag_column_(),
236 : direction_column_(), scanrate_column_(), fieldname_column_(),
237 : tsys_column_(), tcal_id_column_(), sorted_rows_(),
238 0 : get_antenna_row_([&](sdfiller::AntennaRecord &r) {return Scantable2MSReader::getAntennaRowImpl(r);}),
239 0 : get_field_row_([&](sdfiller::FieldRecord &r) {return Scantable2MSReader::getFieldRowImpl(r);}),
240 0 : get_observation_row_([&](sdfiller::ObservationRecord &r) {return Scantable2MSReader::getObservationRowImpl(r);}),
241 0 : get_processor_row_([&](sdfiller::ProcessorRecord &r) {return Scantable2MSReader::getProcessorRowImpl(r);}),
242 0 : get_source_row_([&](sdfiller::SourceRecord &r) {return Scantable2MSReader::getSourceRowImpl(r);}),
243 0 : get_spw_row_([&](sdfiller::SpectralWindowRecord &r) {return Scantable2MSReader::getSpectralWindowRowImpl(r);}),
244 0 : field_iter_(nullptr), freq_iter_(nullptr), source_iter_(nullptr) {
245 : // std::cout << "Scantabl2MSReader::Scantable2MSReader" << std::endl;
246 0 : }
247 :
248 0 : Scantable2MSReader::~Scantable2MSReader() {
249 : // std::cout << "Scantabl2MSReader::~Scantable2MSReader" << std::endl;
250 0 : }
251 :
252 0 : void Scantable2MSReader::initializeSpecific() {
253 : // std::cout << "Scantabl2MSReader::initialize" << std::endl;
254 0 : File f(name_);
255 0 : if (f.exists() and f.isDirectory()) {
256 0 : main_table_.reset(new Table(name_, Table::Old));
257 : } else {
258 0 : throw AipsError("Input data doesn't exist or is invalid");
259 : }
260 :
261 : // subtables
262 0 : tcal_table_ = main_table_->keywordSet().asTable("TCAL");
263 0 : weather_table_ = main_table_->keywordSet().asTable("WEATHER");
264 :
265 : // attach columns
266 0 : scan_column_.attach(*main_table_, "SCANNO");
267 0 : cycle_column_.attach(*main_table_, "CYCLENO");
268 0 : ifno_column_.attach(*main_table_, "IFNO");
269 0 : polno_column_.attach(*main_table_, "POLNO");
270 0 : beam_column_.attach(*main_table_, "BEAMNO");
271 0 : flagrow_column_.attach(*main_table_, "FLAGROW");
272 0 : time_column_.attach(*main_table_, "TIME");
273 0 : interval_column_.attach(*main_table_, "INTERVAL");
274 0 : srctype_column_.attach(*main_table_, "SRCTYPE");
275 0 : data_column_.attach(*main_table_, "SPECTRA");
276 0 : flag_column_.attach(*main_table_, "FLAGTRA");
277 0 : direction_column_.attach(*main_table_, "DIRECTION");
278 0 : scanrate_column_.attach(*main_table_, "SCANRATE");
279 0 : fieldname_column_.attach(*main_table_, "FIELDNAME");
280 0 : tsys_column_.attach(*main_table_, "TSYS");
281 0 : tcal_id_column_.attach(*main_table_, "TCAL_ID");
282 0 : weather_id_column_.attach(*main_table_, "WEATHER_ID");
283 :
284 0 : tcal_column_.attach(tcal_table_, "TCAL");
285 :
286 0 : temperature_column_.attach(weather_table_, "TEMPERATURE");
287 0 : pressure_column_.attach(weather_table_, "PRESSURE");
288 0 : humidity_column_.attach(weather_table_, "HUMIDITY");
289 0 : wind_speed_column_.attach(weather_table_, "WINDSPEED");
290 0 : wind_direction_column_.attach(weather_table_, "WINDAZ");
291 :
292 : // get sort index
293 0 : Sort s;
294 0 : Vector<Double> time_list = time_column_.getColumn();
295 0 : s.sortKey(time_list.data(), TpDouble, 0, Sort::Ascending);
296 0 : Vector<uInt> beamno_list = beam_column_.getColumn();
297 0 : s.sortKey(beamno_list.data(), TpUInt, 0, Sort::Ascending);
298 0 : Vector<uInt> ifno_list = ifno_column_.getColumn();
299 0 : s.sortKey(ifno_list.data(), TpUInt, 0, Sort::Ascending);
300 0 : Vector<uInt> polno_list = polno_column_.getColumn();
301 0 : s.sortKey(polno_list.data(), TpUInt, 0, Sort::Ascending);
302 0 : uInt n = s.sort(sorted_rows_, main_table_->nrow());
303 0 : if (n != main_table_->nrow()) {
304 0 : AipsError("Internal problem when sorting rows");
305 : }
306 : // for (uInt i = 0; i < n; ++i) {
307 : // uInt j = sorted_rows_[i];
308 : // printf("id %3u row %3u T %10.3f B %2u S %2u P %2u\n", i, j, time_list[j],
309 : // beamno_list[j], ifno_list[j], polno_list[j]);
310 : // }
311 :
312 : // TCAL_ID mapping
313 0 : ScalarColumn<uInt> id_column(tcal_table_, "ID");
314 0 : tcal_id_map_.clear();
315 0 : for (uInt i = 0; i < tcal_table_.nrow(); ++i) {
316 0 : tcal_id_map_[id_column(i)] = i;
317 : }
318 :
319 : // WEATHER_ID mapping
320 0 : id_column.attach(weather_table_, "ID");
321 0 : weather_id_map_.clear();
322 0 : for (uInt i = 0; i < weather_table_.nrow(); ++i) {
323 0 : weather_id_map_[id_column(i)] = i;
324 : }
325 :
326 : // polarization type from header
327 0 : pol_type_ = main_table_->keywordSet().asString("POLTYPE");
328 0 : }
329 :
330 0 : void Scantable2MSReader::finalizeSpecific() {
331 : // std::cout << "Scantabl2MSReader::finalize" << std::endl;
332 0 : }
333 :
334 0 : Bool Scantable2MSReader::getAntennaRowImpl(AntennaRecord &record) {
335 : // std::cout << "Scantabl2MSReader::getAntennaRowImpl" << std::endl;
336 0 : TableRecord const &header = main_table_->keywordSet();
337 :
338 : // header antenna name is constructed as <ObservatoryName>//<AntennaName>@<StationName>
339 0 : String header_antenna_name = header.asString("AntennaName");
340 0 : String::size_type separator = header_antenna_name.find("//");
341 0 : String antenna_name;
342 0 : if (separator != String::npos) {
343 0 : antenna_name = header_antenna_name.substr(separator + 2);
344 : } else {
345 0 : antenna_name = header_antenna_name;
346 : }
347 0 : separator = antenna_name.find("@");
348 0 : if (separator != String::npos) {
349 0 : record.station = antenna_name.substr(separator + 1);
350 0 : record.name = antenna_name.substr(0, separator);
351 : } else {
352 0 : record.station = "";
353 0 : record.name = antenna_name;
354 : }
355 0 : record.dish_diameter = queryAntennaDiameter(record.name);
356 0 : record.type = "GROUND-BASED";
357 0 : record.mount = "ALT-AZ";
358 :
359 : Vector<Double> antenna_position_value = header.asArrayDouble(
360 0 : "AntennaPosition");
361 0 : Vector<Quantity> antenna_position_quant(3);
362 0 : antenna_position_quant[0] = Quantity(antenna_position_value[0], "m");
363 0 : antenna_position_quant[1] = Quantity(antenna_position_value[1], "m");
364 0 : antenna_position_quant[2] = Quantity(antenna_position_value[2], "m");
365 0 : record.position = MPosition(MVPosition(antenna_position_quant),
366 0 : MPosition::ITRF);
367 :
368 : // only one entry so redirect function pointer to noMoreRowImpl
369 0 : get_antenna_row_ = [&](sdfiller::AntennaRecord &r) {return Scantable2MSReader::noMoreRowImpl<AntennaRecord>(r);};
370 :
371 0 : return true;
372 : }
373 :
374 0 : Bool Scantable2MSReader::getObservationRowImpl(ObservationRecord &record) {
375 : // std::cout << "Scantabl2MSReader::getObservationRowImpl" << std::endl;
376 :
377 0 : ScalarColumn<Double> column(*main_table_, "TIME");
378 0 : Vector<Double> time_list = column.getColumn();
379 0 : if (record.time_range.size() != 2) {
380 0 : record.time_range.resize(2);
381 : }
382 0 : minMax(record.time_range[0], record.time_range[1], time_list);
383 0 : TableRecord const &header = main_table_->keywordSet();
384 0 : record.observer = header.asString("Observer");
385 0 : record.project = header.asString("Project");
386 : // header antenna name is constructed as <ObservatoryName>//<AntennaName>@<StationName>
387 0 : String header_antenna_name = header.asString("AntennaName");
388 0 : String::size_type separator = header_antenna_name.find("//");
389 0 : if (separator != String::npos) {
390 0 : record.telescope_name = header_antenna_name.substr(0, separator);
391 : } else {
392 0 : separator = header_antenna_name.find("@");
393 0 : record.telescope_name = header_antenna_name.substr(0, separator);
394 : }
395 :
396 : // only one entry so redirect function pointer to noMoreRowImpl
397 0 : get_observation_row_ = [&](sdfiller::ObservationRecord &r) {return Scantable2MSReader::noMoreRowImpl<ObservationRecord>(r);};
398 :
399 0 : return true;
400 : }
401 :
402 0 : Bool Scantable2MSReader::getProcessorRowImpl(ProcessorRecord &/*record*/) {
403 : // std::cout << "Scantabl2MSReader::getProcessorRowImpl" << std::endl;
404 :
405 : // just add empty row once
406 :
407 : // only one entry so redirect function pointer to noMoreRowImpl
408 0 : get_processor_row_ = [&](sdfiller::ProcessorRecord &r) {return Scantable2MSReader::noMoreRowImpl<ProcessorRecord>(r);};
409 :
410 0 : return true;
411 : }
412 :
413 0 : Bool Scantable2MSReader::getSourceRowImpl(SourceRecord &record) {
414 0 : return getRowImplTemplate(source_iter_, record, get_source_row_);
415 : }
416 :
417 0 : Bool Scantable2MSReader::getFieldRowImpl(FieldRecord &record) {
418 0 : return getRowImplTemplate(field_iter_, record, get_field_row_, &field_map_);
419 : }
420 :
421 0 : Bool Scantable2MSReader::getSpectralWindowRowImpl(
422 : SpectralWindowRecord &record) {
423 0 : return getRowImplTemplate(freq_iter_, record, get_spw_row_, &num_chan_map_);
424 : }
425 :
426 0 : Bool Scantable2MSReader::getData(size_t irow, DataRecord &record) {
427 : // std::cout << "Scantable2MSReader::getData(irow=" << irow << ")" << std::endl;
428 :
429 0 : if (irow >= main_table_->nrow()) {
430 0 : return false;
431 : }
432 :
433 0 : constexpr double kDay2Sec = 86400.0;
434 0 : uInt index = sorted_rows_[irow];
435 : // std::cout << "Accessing row " << index << std::endl;
436 :
437 0 : time_column_.get(index, record.time);
438 0 : record.time *= kDay2Sec;
439 0 : interval_column_.get(index, record.interval);
440 : // std::cout << "TIME=" << record.time << " INTERVAL=" << record.interval
441 : // << std::endl;
442 0 : Int srctype = srctype_column_(index);
443 0 : record.intent = getIntent(srctype);
444 0 : record.scan = (Int) scan_column_(index);
445 0 : record.subscan = getSubscan(srctype);
446 0 : String field_name = fieldname_column_.get(index);
447 0 : record.field_id = field_map_[field_name];
448 0 : record.antenna_id = (Int) 0;
449 0 : direction_column_.get(index, record.direction_vector);
450 0 : scanrate_column_.get(index, record.scan_rate);
451 0 : record.feed_id = (Int) beam_column_(index);
452 0 : record.spw_id = (Int) ifno_column_(index);
453 : uInt polno;
454 0 : polno_column_.get(index, polno);
455 0 : record.pol = getPol(polno, pol_type_);
456 0 : record.pol_type = pol_type_;
457 : // std::cout << "set data size to " << num_chan_map_[record.spw_id] << " shape "
458 : // << record.data.shape() << std::endl;
459 0 : record.setDataSize(num_chan_map_[record.spw_id]);
460 0 : data_column_.get(index, record.data);
461 0 : Vector<uChar> flag = flag_column_(index);
462 0 : convertArray(record.flag, flag);
463 0 : uInt flagrow = flagrow_column_(index);
464 0 : Bool bflagrow = (flagrow != 0);
465 0 : record.flag_row = bflagrow;
466 :
467 0 : if (tsys_column_.isDefined(index)) {
468 : // std::cout << "set tsys size to " << tsys_column_.shape(index)[0]
469 : // << " shape " << record.tsys.shape() << std::endl;
470 0 : record.setTsysSize(tsys_column_.shape(index)[0]);
471 0 : Vector<Float> tsys = tsys_column_(index);
472 0 : if (!allEQ(tsys, 1.0f) || !allEQ(tsys, 0.0f)) {
473 0 : record.tsys = tsys;
474 : }
475 : }
476 :
477 0 : uInt tcal_id = tcal_id_column_(index);
478 0 : auto iter = tcal_id_map_.find(tcal_id);
479 0 : if (iter != tcal_id_map_.end()) {
480 0 : uInt tcal_row = iter->second;
481 : // std::cout << "set tsys size to " << tcal_column.shape(0)[0] << " shape "
482 : // << record.tcal.shape() << std::endl;
483 0 : record.setTcalSize(tcal_column_.shape(tcal_row)[0]);
484 0 : Vector<Float> tcal = tcal_column_(tcal_row);
485 0 : if (!allEQ(tcal, 1.0f) || !allEQ(tcal, 0.0f)) {
486 0 : record.tcal = tcal;
487 : }
488 : }
489 :
490 0 : uInt weather_id = weather_id_column_(index);
491 0 : auto iter2 = weather_id_map_.find(weather_id);
492 0 : if (iter2 != weather_id_map_.end()) {
493 0 : uInt weather_row = iter2->second;
494 0 : record.temperature = temperature_column_(weather_row);
495 0 : record.pressure = pressure_column_(weather_row);
496 0 : record.rel_humidity = humidity_column_(weather_row);
497 0 : record.wind_speed = wind_speed_column_(weather_row);
498 0 : record.wind_direction = wind_direction_column_(weather_row);
499 : }
500 :
501 0 : return true;
502 : }
503 :
504 : } //# NAMESPACE CASA - END
|