MeteoIODoc 20241221.207bde49
iCSVHelper.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-3.0-or-later
2/***********************************************************************************/
3/* Copyright 2009 WSL Institute for Snow and Avalanche Research SLF-DAVOS */
4/***********************************************************************************/
5/* This file is part of MeteoIO.
6 MeteoIO is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 MeteoIO is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with MeteoIO. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifndef iCSVHELP_H
20#define iCSVHELP_H
21
22#include <meteoio/IOUtils.h>
23
24#include <map>
25#include <sstream>
26#include <string>
27#include <vector>
28#include <algorithm>
29
30static const double default_nodata = M_PI;
31namespace mio {
32namespace iCSV {
33
34
35// ----------------- Datat structures -----------------
40 double x = default_nodata;
41 double y = default_nodata;
42 double z = default_nodata;
50 bool isEmpty() const { return x == default_nodata && y == default_nodata && z == default_nodata; }
51
56 std::string toString() const {
57 std::stringstream ss;
58 ss << "x: " << x << " y: " << y << " z: " << z
59 << (slope_angle != default_nodata ? " slope_angle: " + std::to_string(slope_angle) : "")
60 << (slope_azi != default_nodata ? " slope_azi: " + std::to_string(slope_azi) : "");
61 return ss.str();
62 }
63
65 if (x == default_nodata) {
67 }
68 if (y == default_nodata) {
70 }
71 if (z == default_nodata) {
73 }
74 }
75
76 Coords toCoords(const int& epsg) const {
77 Coords loc;
78 loc.setPoint(x, y, z, epsg);
79 return loc;
80 }
81
83 geoLocation(const geoLocation& rhs);
84 geoLocation() = default;
85 geoLocation(const double& in_x, const double& in_y, const double& in_z, const double& in_slope_angle=default_nodata, const double& in_slope_azi=default_nodata);
86
87};
88
89bool operator==(const geoLocation& lhs, const geoLocation& rhs);
90bool operator!=(const geoLocation& lhs, const geoLocation& rhs);
91
96 char field_delimiter = '0';
97 std::string geometry = "";
98 std::string srid = "";
99 int epsg = -1;
100 std::string station_id = "";
101 std::string timestamp_meaning = "";
104 std::string doi = "";
106 std::map<std::string, std::string> optional_metadata = {};
108 const std::vector<char> valid_delimiters = {',', '/', '\\', '|', ':', ';'};
114 void setEPSG(const int &in_epsg) {
115 epsg = in_epsg;
116 srid = "EPSG:" + std::to_string(in_epsg);
117 }
118
125 std::string getOptionalMetaData(const std::string &key) const {
126 const auto it = optional_metadata.find(key);
127 if (it != optional_metadata.end()) {
128 return it->second;
129 }
130 return "";
131 }
132
138 std::map<std::string, std::string> toMetaMap() const {
139 std::map<std::string, std::string> dict;
140 if (!doi.empty()) {
141 dict["doi"] = doi;
142 }
143
144 // Append optional_metadata to dict
145 dict.insert(optional_metadata.begin(), optional_metadata.end());
146
147 return dict;
148 }
149
155 std::map<std::string, std::string> toOutputMap() const {
156 std::map<std::string, std::string> dict;
157 dict["field_delimiter"] = field_delimiter;
158 dict["geometry"] = geometry;
159 dict["srid"] = srid;
160 if (!station_id.empty()) {
161 dict["station_id"] = station_id;
162 }
163 if (!timestamp_meaning.empty()) {
164 dict["timestamp_meaning"] = timestamp_meaning;
165 }
166 if (nodata != default_nodata) {
167 dict["nodata"] = std::to_string(nodata);
168 }
169 if (timezone != default_nodata) {
170 dict["timezone"] = std::to_string(timezone);
171 }
172 if (!doi.empty()) {
173 dict["doi"] = doi;
174 }
175
176 dict.insert(optional_metadata.begin(), optional_metadata.end());
177 return dict;
178 }
179};
180
181bool operator==(const MetaDataSection &lhs, const MetaDataSection &rhs);
182
190bool roughlyEqual(const MetaDataSection &lhs, const MetaDataSection &rhs);
191
193
199 std::vector<std::string> fields = {};
200 std::vector<double> units_multipliers = {};
201 std::vector<double> units_offsets = {};
202 std::vector<std::string> units = {};
203 std::vector<std::string> long_name = {};
204 std::vector<std::string> standard_name = {};
205
206 std::map<std::string, std::vector<std::string>> other_fields = {};
207
208 size_t getFieldIndex(const std::string &fieldname) const {
209 for (size_t id = 0; id < fields.size(); id++) {
210 if (fieldname == fields[id])
211 return id;
212 }
213 return IOUtils::npos;
214 }
215
216 std::vector<std::string> getOtherFields(const std::string &key) {
217 auto it = other_fields.find(key);
218 if (it != other_fields.end()) {
219 return it->second;
220 }
221 return {};
222 }
223 std::map<std::string, std::vector<std::string>> toMap() const {
224 std::map<std::string, std::vector<std::string>> dict;
225 dict["fields"] = fields;
226
227 if (!units.empty()) {
228 dict["units"] = units;
229 }
230 if (!long_name.empty()) {
231 dict["long_name"] = long_name;
232 }
233 if (!standard_name.empty()) {
234 dict["standard_name"] = standard_name;
235 }
236
237 // Convert vector<double> to vector<string>
238 if (!units_multipliers.empty()) {
239 std::vector<std::string> str_units_multipliers(units_multipliers.size());
240 std::transform(units_multipliers.begin(), units_multipliers.end(), str_units_multipliers.begin(),
241 [](double d) { return std::to_string(d); });
242 dict["units_multipliers"] = str_units_multipliers;
243 }
244
245 if (!units_offsets.empty()) {
246 std::vector<std::string> str_units_offsets(units_offsets.size());
247 std::transform(units_offsets.begin(), units_offsets.end(), str_units_offsets.begin(),
248 [](double d) { return std::to_string(d); });
249 dict["units_offsets"] = str_units_offsets;
250 }
251
252 // Append other_fields to dict
253 if (!other_fields.empty()) {
254 dict.insert(other_fields.begin(), other_fields.end());
255 }
256 return dict;
257 }
258};
259
260bool operator==(const fieldsSection &lhs, const fieldsSection &rhs);
261
269bool roughlyEqual(const fieldsSection &lhs, const fieldsSection &rhs);
271
272// ----------------- Helper functions -----------------
273std::vector<double> convertVector(const std::vector<std::string> &vec);
274std::vector<Coords> convertVector(const std::vector<geoLocation> &vec, const int& epsg);
275geoLocation extractCoordinates(const std::string &geometry);
276geoLocation toiCSVLocation(Coords coords, const int& epsg);
277
278
279
280// ----------------- iCSVFile class -----------------
281
297class iCSVFile {
298 public:
299 // Essential information
301 std::string filename;
302 std::string firstline;
304
307
308 // helper flags
310 bool timezone_in_data = false;
311 bool timestamp_present = false;
312 bool julian_present = false;
315
316 private:
317 // File data
318 std::vector<Date> dates_in_file;
319 std::vector<std::vector<double>> row_data;
320 std::vector<geoLocation> locations_in_data;
321
322
323 public:
324 // Constructors
325 iCSVFile();
326 iCSVFile(const iCSVFile &);
327 iCSVFile(const std::string &infile, const bool& read_sequential);
328
329 // Main methods
330 void readFile(const std::string &infile, const bool& sequentially);
331 bool checkFormatValidity();
332 bool checkMeteoIOCompatibility() const;
333 void parseGeometry();
334
335 // Getters
336 double getNoData() const {
338 return nodat;
339 }
341 const std::vector<std::vector<double>>& getRowData() const { return row_data; }
342 const std::vector<Date>& getAllDatesInFile() const { return dates_in_file; }
343 const std::vector<geoLocation>& getAllLocationsInData() const { return locations_in_data; }
344 geoLocation getLocationAt(size_t index) const {
345 if (index >= locations_in_data.size()) {
346 throw std::out_of_range("Index out of range for locations");
347 }
348 return locations_in_data[index];
349 }
350 std::vector<Date> getDatesInFile(const Date &start_date, const Date &end_date) const {
351 std::vector<Date> dates;
352 for (const Date &date : dates_in_file) {
353 if (date >= start_date && date <= end_date) {
354 dates.push_back(date);
355 }
356 }
357 return dates;
358 }
359 std::vector<geoLocation> getLocationsInData(const Date &start_date, const Date &end_date) const {
361 return std::vector<geoLocation>();
362
363 std::vector<geoLocation> locations;
364 for (size_t i = 0; i < dates_in_file.size(); i++) {
365 if (dates_in_file[i] >= start_date && dates_in_file[i] <= end_date) {
366 locations.push_back(locations_in_data[i]);
367 }
368 }
369 return locations;
370 }
371 // reading helpers
372 bool processLine(const std::string& line, std::string& section, const bool& sequentially);
373 void processContent(const std::string& content, const std::string& section);
374 void processData(const std::string& content);
375
376 // Format helpers
377 bool isValidLocation(const geoLocation& location);
378 bool isColumnName(const std::string &geometry);
379 void findTime();
380 void findLocation();
381 std::vector<std::string> columnsToAppend(const std::vector<MeteoData> &vecMeteo) const;
382
383 // Data methods
384 double readData(const Date &r_date, const std::string &fieldname);
385 void aggregateData(const std::vector<MeteoData> &vecMeteo);
386 void populateMetaData(const std::string &key, const std::string &value);
387 void populateFields(const std::string &key, const std::string &value);
388};
389
390} // namespace iCSV
391} // namespace mio
392#endif // iCSVHELP_H
A class to handle geographic coordinate systems. This class offers an easy way to transparently conve...
Definition: Coords.h:83
void setPoint(const double in_x_or_lat, const double in_y_or_lon, const double in_altitude)
Set coordinates based on the previously defined EPSG code If the EPSG code is 4326 (which represents ...
Definition: Coords.cc:551
A class to handle timestamps. This class handles conversion between different time display formats (I...
Definition: Date.h:87
This class is responsible for handling and storing iCSV files.
Definition: iCSVHelper.h:297
std::vector< std::string > columnsToAppend(const std::vector< MeteoData > &vecMeteo) const
Definition: iCSVHelper.cc:549
void aggregateData(const std::vector< MeteoData > &vecMeteo)
Definition: iCSVHelper.cc:424
const std::vector< Date > & getAllDatesInFile() const
Definition: iCSVHelper.h:342
bool timezone_in_data
Definition: iCSVHelper.h:310
std::string firstline
Definition: iCSVHelper.h:302
geoLocation station_location
Definition: iCSVHelper.h:303
std::vector< geoLocation > getLocationsInData(const Date &start_date, const Date &end_date) const
Definition: iCSVHelper.h:359
double getNoData() const
Definition: iCSVHelper.h:336
size_t time_id
Definition: iCSVHelper.h:313
void processContent(const std::string &content, const std::string &section)
Definition: iCSVHelper.cc:303
iCSVFile()
Definition: iCSVHelper.cc:192
double getTimeZone() const
Definition: iCSVHelper.h:340
fieldsSection FIELDS
Definition: iCSVHelper.h:306
size_t skip_lines_to_data
Definition: iCSVHelper.h:300
bool checkFormatValidity()
Checks the validity of the format for the iCSVFile.
Definition: iCSVHelper.cc:460
bool isValidLocation(const geoLocation &location)
Definition: iCSVHelper.cc:536
void findTime()
Definition: iCSVHelper.cc:605
void populateMetaData(const std::string &key, const std::string &value)
Definition: iCSVHelper.cc:348
bool location_in_header
Definition: iCSVHelper.h:309
bool timestamp_present
Definition: iCSVHelper.h:311
void findLocation()
Definition: iCSVHelper.cc:622
bool isColumnName(const std::string &geometry)
Definition: iCSVHelper.cc:538
std::vector< Date > getDatesInFile(const Date &start_date, const Date &end_date) const
Definition: iCSVHelper.h:350
bool checkMeteoIOCompatibility() const
Definition: iCSVHelper.cc:523
std::string filename
Definition: iCSVHelper.h:301
geoLocation getLocationAt(size_t index) const
Definition: iCSVHelper.h:344
void readFile(const std::string &infile, const bool &sequentially)
Definition: iCSVHelper.cc:236
void populateFields(const std::string &key, const std::string &value)
Definition: iCSVHelper.cc:376
const std::vector< geoLocation > & getAllLocationsInData() const
Definition: iCSVHelper.h:343
size_t location_id
Definition: iCSVHelper.h:314
void processData(const std::string &content)
Definition: iCSVHelper.cc:327
void parseGeometry()
Parses the geometry information of the iCSV file.
Definition: iCSVHelper.cc:584
MetaDataSection METADATA
Definition: iCSVHelper.h:305
const std::vector< std::vector< double > > & getRowData() const
Definition: iCSVHelper.h:341
bool processLine(const std::string &line, std::string &section, const bool &sequentially)
Definition: iCSVHelper.cc:266
double readData(const Date &r_date, const std::string &fieldname)
Definition: iCSVHelper.cc:403
bool julian_present
Definition: iCSVHelper.h:312
static const double default_nodata
Definition: iCSVHelper.h:30
const size_t npos
npos is the out-of-range value
Definition: IOUtils.h:80
const double nodata
This is the internal nodata value.
Definition: IOUtils.h:75
std::vector< double > convertVector(const std::vector< std::string > &vec)
Definition: iCSVHelper.cc:130
bool roughlyEqual(const MetaDataSection &lhs, const MetaDataSection &rhs)
Checks if two MetaDataSection objects are roughly equal.
Definition: iCSVHelper.cc:691
MetaDataSection & operator+=(MetaDataSection &lhs, const MetaDataSection &rhs)
Definition: iCSVHelper.cc:731
bool operator!=(const geoLocation &lhs, const geoLocation &rhs)
Definition: iCSVHelper.cc:634
bool operator==(const geoLocation &lhs, const geoLocation &rhs)
Definition: iCSVHelper.cc:633
geoLocation toiCSVLocation(Coords loc, const int &epsg)
Definition: iCSVHelper.cc:157
geoLocation extractCoordinates(const std::string &geometry)
extracts a geoLocation object out of a WKT geometry string.
Definition: iCSVHelper.cc:173
Definition: Config.cc:31
Stores information on the METADATA section of a iCSV file.
Definition: iCSVHelper.h:95
std::map< std::string, std::string > toOutputMap() const
Convert the metadata section to an output map.
Definition: iCSVHelper.h:155
int epsg
Definition: iCSVHelper.h:99
void setEPSG(const int &in_epsg)
Set the EPSG code and update the SRID.
Definition: iCSVHelper.h:114
std::map< std::string, std::string > toMetaMap() const
Convert the metadata section to a map.
Definition: iCSVHelper.h:138
std::string geometry
Definition: iCSVHelper.h:97
double nodata
Definition: iCSVHelper.h:102
std::string timestamp_meaning
Definition: iCSVHelper.h:101
char field_delimiter
Definition: iCSVHelper.h:96
std::string station_id
Definition: iCSVHelper.h:100
double timezone
Definition: iCSVHelper.h:103
std::map< std::string, std::string > optional_metadata
Definition: iCSVHelper.h:106
std::string getOptionalMetaData(const std::string &key) const
Get the value of an optional metadata field.
Definition: iCSVHelper.h:125
std::string doi
Definition: iCSVHelper.h:104
std::string srid
Definition: iCSVHelper.h:98
const std::vector< char > valid_delimiters
Definition: iCSVHelper.h:108
Stores Information on the FIELDS section of a iCSV file.
Definition: iCSVHelper.h:198
size_t getFieldIndex(const std::string &fieldname) const
Definition: iCSVHelper.h:208
std::vector< double > units_offsets
Definition: iCSVHelper.h:201
std::map< std::string, std::vector< std::string > > other_fields
Definition: iCSVHelper.h:206
std::vector< std::string > units
Definition: iCSVHelper.h:202
std::vector< double > units_multipliers
Definition: iCSVHelper.h:200
std::vector< std::string > long_name
Definition: iCSVHelper.h:203
std::vector< std::string > fields
Definition: iCSVHelper.h:199
std::map< std::string, std::vector< std::string > > toMap() const
Definition: iCSVHelper.h:223
std::vector< std::string > standard_name
Definition: iCSVHelper.h:204
std::vector< std::string > getOtherFields(const std::string &key)
Definition: iCSVHelper.h:216
Represents a geographic location extracted from iCSV files. (POINT(X Y)...)
Definition: iCSVHelper.h:39
bool isEmpty() const
Checks if the geoLocation is empty.
Definition: iCSVHelper.h:50
geoLocation & operator=(const geoLocation &rhs)
Definition: iCSVHelper.cc:636
void standardizeNodata()
Definition: iCSVHelper.h:64
double x
Definition: iCSVHelper.h:40
std::string toString() const
Converts the geoLocation to a string representation.
Definition: iCSVHelper.h:56
Coords toCoords(const int &epsg) const
Definition: iCSVHelper.h:76
double slope_angle
Definition: iCSVHelper.h:43
double slope_azi
Definition: iCSVHelper.h:44
double z
Definition: iCSVHelper.h:42
double y
Definition: iCSVHelper.h:41