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 5 : Double queryAntennaDiameter(String const &name) {
27 5 : String capitalized = name;
28 5 : capitalized.upcase();
29 5 : Double diameter = 0.0;
30 5 : if (capitalized.matches(Regex(".*(DV|DA|PM)[0-9]+$"))) {
31 5 : 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 10 : return diameter;
55 : }
56 :
57 : template<class T, class U>
58 1980 : U getMapValue(std::map<T, U> const mymap, T const key, U const default_value) {
59 1980 : auto iter = mymap.find(key);
60 1980 : if (iter != mymap.end()) {
61 1980 : return iter->second;
62 : } else {
63 0 : return default_value;
64 : }
65 : }
66 :
67 990 : String getIntent(Int srctype) {
68 990 : static std::map<Int, String> intent_map;
69 990 : if (intent_map.size() == 0) {
70 2 : String sep1 = "#";
71 2 : String sep2 = ",";
72 2 : String target = "OBSERVE_TARGET";
73 2 : String atmcal = "CALIBRATE_ATMOSPHERE";
74 2 : String anycal = "CALIBRATE_SOMETHING";
75 2 : String onstr = "ON_SOURCE";
76 2 : String offstr = "OFF_SOURCE";
77 2 : String pswitch = "POSITION_SWITCH";
78 2 : String nod = "NOD";
79 2 : String fswitch = "FREQUENCY_SWITCH";
80 2 : String sigstr = "SIG";
81 2 : String refstr = "REF";
82 2 : String hot = "HOT";
83 2 : String warm = "WARM";
84 2 : String cold = "COLD";
85 2 : String unspecified = "UNSPECIFIED";
86 2 : String ftlow = "LOWER";
87 1 : String fthigh = "HIGHER";
88 1 : intent_map[0] = target + sep1 + onstr + sep2 + pswitch;
89 1 : intent_map[1] = target + sep1 + offstr + sep2 + pswitch;
90 1 : intent_map[2] = target + sep1 + onstr + sep2 + nod;
91 1 : intent_map[3] = target + sep1 + onstr + sep2 + fswitch + sep1 + sigstr;
92 1 : intent_map[4] = target + sep1 + onstr + sep2 + fswitch + sep1 + refstr;
93 1 : intent_map[6] = atmcal + sep1 + offstr + sep2 + unspecified;
94 1 : intent_map[7] = atmcal + sep1 + hot + sep2 + unspecified;
95 1 : intent_map[8] = atmcal + sep1 + warm + sep2 + unspecified;
96 1 : intent_map[9] = atmcal + sep1 + cold + sep2 + unspecified;
97 1 : intent_map[10] = atmcal + sep1 + onstr + sep2 + pswitch;
98 1 : intent_map[11] = atmcal + sep1 + offstr + sep2 + pswitch;
99 1 : intent_map[12] = atmcal + sep1 + onstr + sep2 + nod;
100 1 : intent_map[13] = atmcal + sep1 + onstr + sep2 + fswitch + sep1 + sigstr;
101 1 : intent_map[14] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + refstr;
102 1 : intent_map[20] = target + sep1 + onstr + sep2 + fswitch + sep1 + ftlow;
103 1 : intent_map[21] = target + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
104 1 : intent_map[26] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
105 1 : intent_map[27] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
106 1 : intent_map[28] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
107 1 : intent_map[29] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + ftlow;
108 1 : intent_map[30] = target + sep1 + onstr + sep2 + fswitch + sep1 + fthigh;
109 1 : intent_map[31] = target + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
110 1 : intent_map[36] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
111 1 : intent_map[37] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
112 1 : intent_map[38] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
113 1 : intent_map[39] = atmcal + sep1 + offstr + sep2 + fswitch + sep1 + fthigh;
114 1 : intent_map[90] = target + sep1 + onstr + sep2 + unspecified;
115 1 : intent_map[91] = target + sep1 + offstr + sep2 + unspecified;
116 1 : intent_map[92] = anycal + sep1 + offstr + sep2 + unspecified;
117 : }
118 990 : String default_type = "UNKNOWN_INTENT";
119 1980 : return getMapValue(intent_map, srctype, default_type);
120 : }
121 :
122 990 : Int getSubscan(Int srctype) {
123 990 : static std::map<Int, Int> subscan_map;
124 990 : if (subscan_map.size() == 0) {
125 1 : subscan_map[0] = 1;
126 1 : subscan_map[1] = 2;
127 1 : subscan_map[2] = 1;
128 1 : subscan_map[3] = 1;
129 1 : subscan_map[4] = 2;
130 1 : subscan_map[6] = 1;
131 1 : subscan_map[7] = 2;
132 1 : subscan_map[8] = 3;
133 1 : subscan_map[9] = 4;
134 1 : subscan_map[10] = 5;
135 1 : subscan_map[11] = 6;
136 1 : subscan_map[12] = 7;
137 1 : subscan_map[13] = 8;
138 1 : subscan_map[14] = 9;
139 1 : subscan_map[20] = 1;
140 1 : subscan_map[21] = 2;
141 1 : subscan_map[26] = 1;
142 1 : subscan_map[27] = 2;
143 1 : subscan_map[28] = 3;
144 1 : subscan_map[29] = 4;
145 1 : subscan_map[30] = 3;
146 1 : subscan_map[31] = 4;
147 1 : subscan_map[36] = 5;
148 1 : subscan_map[37] = 6;
149 1 : subscan_map[38] = 7;
150 1 : subscan_map[39] = 8;
151 1 : subscan_map[90] = 1;
152 1 : subscan_map[91] = 2;
153 1 : subscan_map[92] = 1;
154 : }
155 990 : Int default_subscan = 1;
156 990 : return getMapValue(subscan_map, srctype, default_subscan);
157 : }
158 :
159 990 : casacore::Stokes::StokesTypes getPol(uInt const polno, casacore::String const poltype) {
160 990 : casacore::Stokes::StokesTypes stokes = casacore::Stokes::Undefined;
161 990 : if (poltype == "linear") {
162 990 : switch (polno) {
163 590 : case 0:
164 590 : stokes = casacore::Stokes::XX;
165 590 : break;
166 400 : case 1:
167 400 : stokes = casacore::Stokes::YY;
168 400 : 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 990 : if (stokes == casacore::Stokes::Undefined) {
219 : throw casacore::AipsError(
220 0 : casacore::String("Invalid polno for type ") + poltype);
221 : }
222 990 : return stokes;
223 : }
224 : }
225 :
226 : using namespace casacore;
227 : namespace casa { //# NAMESPACE CASA - BEGIN
228 :
229 : using namespace sdfiller;
230 :
231 5 : 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 5 : get_antenna_row_([&](sdfiller::AntennaRecord &r) {return Scantable2MSReader::getAntennaRowImpl(r);}),
239 10 : get_field_row_([&](sdfiller::FieldRecord &r) {return Scantable2MSReader::getFieldRowImpl(r);}),
240 5 : get_observation_row_([&](sdfiller::ObservationRecord &r) {return Scantable2MSReader::getObservationRowImpl(r);}),
241 5 : get_processor_row_([&](sdfiller::ProcessorRecord &r) {return Scantable2MSReader::getProcessorRowImpl(r);}),
242 30 : get_source_row_([&](sdfiller::SourceRecord &r) {return Scantable2MSReader::getSourceRowImpl(r);}),
243 30 : get_spw_row_([&](sdfiller::SpectralWindowRecord &r) {return Scantable2MSReader::getSpectralWindowRowImpl(r);}),
244 5 : field_iter_(nullptr), freq_iter_(nullptr), source_iter_(nullptr) {
245 : // std::cout << "Scantabl2MSReader::Scantable2MSReader" << std::endl;
246 5 : }
247 :
248 10 : Scantable2MSReader::~Scantable2MSReader() {
249 : // std::cout << "Scantabl2MSReader::~Scantable2MSReader" << std::endl;
250 10 : }
251 :
252 5 : void Scantable2MSReader::initializeSpecific() {
253 : // std::cout << "Scantabl2MSReader::initialize" << std::endl;
254 10 : File f(name_);
255 5 : if (f.exists() and f.isDirectory()) {
256 5 : 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 5 : tcal_table_ = main_table_->keywordSet().asTable("TCAL");
263 5 : weather_table_ = main_table_->keywordSet().asTable("WEATHER");
264 :
265 : // attach columns
266 5 : scan_column_.attach(*main_table_, "SCANNO");
267 5 : cycle_column_.attach(*main_table_, "CYCLENO");
268 5 : ifno_column_.attach(*main_table_, "IFNO");
269 5 : polno_column_.attach(*main_table_, "POLNO");
270 5 : beam_column_.attach(*main_table_, "BEAMNO");
271 5 : flagrow_column_.attach(*main_table_, "FLAGROW");
272 5 : time_column_.attach(*main_table_, "TIME");
273 5 : interval_column_.attach(*main_table_, "INTERVAL");
274 5 : srctype_column_.attach(*main_table_, "SRCTYPE");
275 5 : data_column_.attach(*main_table_, "SPECTRA");
276 5 : flag_column_.attach(*main_table_, "FLAGTRA");
277 5 : direction_column_.attach(*main_table_, "DIRECTION");
278 5 : scanrate_column_.attach(*main_table_, "SCANRATE");
279 5 : fieldname_column_.attach(*main_table_, "FIELDNAME");
280 5 : tsys_column_.attach(*main_table_, "TSYS");
281 5 : tcal_id_column_.attach(*main_table_, "TCAL_ID");
282 5 : weather_id_column_.attach(*main_table_, "WEATHER_ID");
283 :
284 5 : tcal_column_.attach(tcal_table_, "TCAL");
285 :
286 5 : temperature_column_.attach(weather_table_, "TEMPERATURE");
287 5 : pressure_column_.attach(weather_table_, "PRESSURE");
288 5 : humidity_column_.attach(weather_table_, "HUMIDITY");
289 5 : wind_speed_column_.attach(weather_table_, "WINDSPEED");
290 5 : wind_direction_column_.attach(weather_table_, "WINDAZ");
291 :
292 : // get sort index
293 10 : Sort s;
294 10 : Vector<Double> time_list = time_column_.getColumn();
295 5 : s.sortKey(time_list.data(), TpDouble, 0, Sort::Ascending);
296 10 : Vector<uInt> beamno_list = beam_column_.getColumn();
297 5 : s.sortKey(beamno_list.data(), TpUInt, 0, Sort::Ascending);
298 10 : Vector<uInt> ifno_list = ifno_column_.getColumn();
299 5 : s.sortKey(ifno_list.data(), TpUInt, 0, Sort::Ascending);
300 10 : Vector<uInt> polno_list = polno_column_.getColumn();
301 5 : s.sortKey(polno_list.data(), TpUInt, 0, Sort::Ascending);
302 5 : uInt n = s.sort(sorted_rows_, main_table_->nrow());
303 5 : 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 5 : ScalarColumn<uInt> id_column(tcal_table_, "ID");
314 5 : tcal_id_map_.clear();
315 325 : for (uInt i = 0; i < tcal_table_.nrow(); ++i) {
316 320 : tcal_id_map_[id_column(i)] = i;
317 : }
318 :
319 : // WEATHER_ID mapping
320 5 : id_column.attach(weather_table_, "ID");
321 5 : weather_id_map_.clear();
322 1580 : for (uInt i = 0; i < weather_table_.nrow(); ++i) {
323 1575 : weather_id_map_[id_column(i)] = i;
324 : }
325 :
326 : // polarization type from header
327 5 : pol_type_ = main_table_->keywordSet().asString("POLTYPE");
328 5 : }
329 :
330 5 : void Scantable2MSReader::finalizeSpecific() {
331 : // std::cout << "Scantabl2MSReader::finalize" << std::endl;
332 5 : }
333 :
334 5 : Bool Scantable2MSReader::getAntennaRowImpl(AntennaRecord &record) {
335 : // std::cout << "Scantabl2MSReader::getAntennaRowImpl" << std::endl;
336 5 : TableRecord const &header = main_table_->keywordSet();
337 :
338 : // header antenna name is constructed as <ObservatoryName>//<AntennaName>@<StationName>
339 10 : String header_antenna_name = header.asString("AntennaName");
340 5 : String::size_type separator = header_antenna_name.find("//");
341 10 : String antenna_name;
342 5 : if (separator != String::npos) {
343 5 : antenna_name = header_antenna_name.substr(separator + 2);
344 : } else {
345 0 : antenna_name = header_antenna_name;
346 : }
347 5 : separator = antenna_name.find("@");
348 5 : if (separator != String::npos) {
349 5 : record.station = antenna_name.substr(separator + 1);
350 5 : record.name = antenna_name.substr(0, separator);
351 : } else {
352 0 : record.station = "";
353 0 : record.name = antenna_name;
354 : }
355 5 : record.dish_diameter = queryAntennaDiameter(record.name);
356 5 : record.type = "GROUND-BASED";
357 5 : record.mount = "ALT-AZ";
358 :
359 : Vector<Double> antenna_position_value = header.asArrayDouble(
360 10 : "AntennaPosition");
361 5 : Vector<Quantity> antenna_position_quant(3);
362 5 : antenna_position_quant[0] = Quantity(antenna_position_value[0], "m");
363 5 : antenna_position_quant[1] = Quantity(antenna_position_value[1], "m");
364 5 : antenna_position_quant[2] = Quantity(antenna_position_value[2], "m");
365 10 : record.position = MPosition(MVPosition(antenna_position_quant),
366 5 : MPosition::ITRF);
367 :
368 : // only one entry so redirect function pointer to noMoreRowImpl
369 10 : get_antenna_row_ = [&](sdfiller::AntennaRecord &r) {return Scantable2MSReader::noMoreRowImpl<AntennaRecord>(r);};
370 :
371 10 : return true;
372 : }
373 :
374 5 : Bool Scantable2MSReader::getObservationRowImpl(ObservationRecord &record) {
375 : // std::cout << "Scantabl2MSReader::getObservationRowImpl" << std::endl;
376 :
377 10 : ScalarColumn<Double> column(*main_table_, "TIME");
378 10 : Vector<Double> time_list = column.getColumn();
379 5 : if (record.time_range.size() != 2) {
380 5 : record.time_range.resize(2);
381 : }
382 5 : minMax(record.time_range[0], record.time_range[1], time_list);
383 5 : TableRecord const &header = main_table_->keywordSet();
384 5 : record.observer = header.asString("Observer");
385 5 : record.project = header.asString("Project");
386 : // header antenna name is constructed as <ObservatoryName>//<AntennaName>@<StationName>
387 5 : String header_antenna_name = header.asString("AntennaName");
388 5 : String::size_type separator = header_antenna_name.find("//");
389 5 : if (separator != String::npos) {
390 5 : 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 10 : get_observation_row_ = [&](sdfiller::ObservationRecord &r) {return Scantable2MSReader::noMoreRowImpl<ObservationRecord>(r);};
398 :
399 10 : return true;
400 : }
401 :
402 5 : 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 10 : get_processor_row_ = [&](sdfiller::ProcessorRecord &r) {return Scantable2MSReader::noMoreRowImpl<ProcessorRecord>(r);};
409 :
410 5 : return true;
411 : }
412 :
413 30 : Bool Scantable2MSReader::getSourceRowImpl(SourceRecord &record) {
414 30 : return getRowImplTemplate(source_iter_, record, get_source_row_);
415 : }
416 :
417 10 : Bool Scantable2MSReader::getFieldRowImpl(FieldRecord &record) {
418 10 : return getRowImplTemplate(field_iter_, record, get_field_row_, &field_map_);
419 : }
420 :
421 30 : Bool Scantable2MSReader::getSpectralWindowRowImpl(
422 : SpectralWindowRecord &record) {
423 30 : return getRowImplTemplate(freq_iter_, record, get_spw_row_, &num_chan_map_);
424 : }
425 :
426 990 : Bool Scantable2MSReader::getData(size_t irow, DataRecord &record) {
427 : // std::cout << "Scantable2MSReader::getData(irow=" << irow << ")" << std::endl;
428 :
429 990 : if (irow >= main_table_->nrow()) {
430 0 : return false;
431 : }
432 :
433 990 : constexpr double kDay2Sec = 86400.0;
434 990 : uInt index = sorted_rows_[irow];
435 : // std::cout << "Accessing row " << index << std::endl;
436 :
437 990 : time_column_.get(index, record.time);
438 990 : record.time *= kDay2Sec;
439 990 : interval_column_.get(index, record.interval);
440 : // std::cout << "TIME=" << record.time << " INTERVAL=" << record.interval
441 : // << std::endl;
442 990 : Int srctype = srctype_column_(index);
443 990 : record.intent = getIntent(srctype);
444 990 : record.scan = (Int) scan_column_(index);
445 990 : record.subscan = getSubscan(srctype);
446 1980 : String field_name = fieldname_column_.get(index);
447 990 : record.field_id = field_map_[field_name];
448 990 : record.antenna_id = (Int) 0;
449 990 : direction_column_.get(index, record.direction_vector);
450 990 : scanrate_column_.get(index, record.scan_rate);
451 990 : record.feed_id = (Int) beam_column_(index);
452 990 : record.spw_id = (Int) ifno_column_(index);
453 : uInt polno;
454 990 : polno_column_.get(index, polno);
455 990 : record.pol = getPol(polno, pol_type_);
456 990 : 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 990 : record.setDataSize(num_chan_map_[record.spw_id]);
460 990 : data_column_.get(index, record.data);
461 990 : Vector<uChar> flag = flag_column_(index);
462 990 : convertArray(record.flag, flag);
463 990 : uInt flagrow = flagrow_column_(index);
464 990 : Bool bflagrow = (flagrow != 0);
465 990 : record.flag_row = bflagrow;
466 :
467 990 : 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 990 : record.setTsysSize(tsys_column_.shape(index)[0]);
471 1980 : Vector<Float> tsys = tsys_column_(index);
472 990 : if (!allEQ(tsys, 1.0f) || !allEQ(tsys, 0.0f)) {
473 990 : record.tsys = tsys;
474 : }
475 : }
476 :
477 990 : uInt tcal_id = tcal_id_column_(index);
478 990 : auto iter = tcal_id_map_.find(tcal_id);
479 990 : if (iter != tcal_id_map_.end()) {
480 990 : 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 990 : record.setTcalSize(tcal_column_.shape(tcal_row)[0]);
484 1980 : Vector<Float> tcal = tcal_column_(tcal_row);
485 990 : if (!allEQ(tcal, 1.0f) || !allEQ(tcal, 0.0f)) {
486 990 : record.tcal = tcal;
487 : }
488 : }
489 :
490 990 : uInt weather_id = weather_id_column_(index);
491 990 : auto iter2 = weather_id_map_.find(weather_id);
492 990 : if (iter2 != weather_id_map_.end()) {
493 990 : uInt weather_row = iter2->second;
494 990 : record.temperature = temperature_column_(weather_row);
495 990 : record.pressure = pressure_column_(weather_row);
496 990 : record.rel_humidity = humidity_column_(weather_row);
497 990 : record.wind_speed = wind_speed_column_(weather_row);
498 990 : record.wind_direction = wind_direction_column_(weather_row);
499 : }
500 :
501 990 : return true;
502 : }
503 :
504 : } //# NAMESPACE CASA - END
|