OGS
DiagramList.cpp
Go to the documentation of this file.
1
15#include "DiagramList.h"
16
17#include <QFile>
18#include <QTextStream>
19#include <limits>
20
21#include "BaseLib/DateTools.h"
22#include "BaseLib/Logging.h"
23#include "BaseLib/StringTools.h"
24#include "GeoLib/SensorData.h"
25#include "GetDateTime.h"
26
27DiagramList::DiagramList() : _xLabel(""), _yLabel(""), _xUnit(""), _yUnit("") {}
28
30
32{
33 auto min = std::min_element(_coords.begin(), _coords.end(),
34 [](auto const& c0, auto const& c1)
35 { return c0.first < c1.first; });
36 if (min != _coords.end())
37 {
38 return min->first;
39 }
40 return std::numeric_limits<float>::max();
41}
42
44{
45 float max = std::numeric_limits<float>::lowest();
46 std::size_t nCoords = _coords.size();
47 for (std::size_t i = 0; i < nCoords; i++)
48 {
49 if (_coords[i].first > max)
50 {
51 max = _coords[i].first;
52 }
53 }
54 return max;
55}
56
58{
59 float min = std::numeric_limits<float>::max();
60 std::size_t nCoords = _coords.size();
61 for (std::size_t i = 0; i < nCoords; i++)
62 {
63 if (_coords[i].second < min)
64 {
65 min = _coords[i].second;
66 }
67 }
68 return min;
69}
70
72{
73 float max = std::numeric_limits<float>::lowest();
74 std::size_t nCoords = _coords.size();
75 for (std::size_t i = 0; i < nCoords; i++)
76 {
77 if (_coords[i].second > max)
78 {
79 max = _coords[i].second;
80 }
81 }
82 return max;
83}
84
85bool DiagramList::getPath(QPainterPath& path, float scaleX, float scaleY)
86{
87 QPointF p;
88 if (getPoint(p, 0))
89 {
90 QPainterPath pp(QPointF(p.x() * scaleX, p.y() * scaleY));
91 path = pp;
92
93 std::size_t nCoords = _coords.size();
94 for (std::size_t i = 1; i < nCoords; i++)
95 {
96 getPoint(p, i);
97 path.lineTo(QPointF(p.x() * scaleX, p.y() * scaleY));
98 }
99 return true;
100 }
101
102 return false;
103}
104
105bool DiagramList::getPoint(QPointF& p, std::size_t i)
106{
107 if (i < _coords.size())
108 {
109 p.setX(_coords[i].first);
110 p.setY(_coords[i].second);
111 return true;
112 }
113
114 return false;
115}
116
117/*
118 * Reads an external list into the coordinate arrays.
119 * This method uses files containing the following format:
120 * xValue <tab> yValue
121 * Both values may be int or double.
122 */
123/*
124 int DiagramList::readList(char* path)
125 {
126 int date;
127 double xVal, yVal;
128 QString line;
129 QStringList fields;
130
131 QFile file(path);
132 QTextStream in( &file );
133
134 if (!file.open(QIODevice::ReadOnly))
135 {
136 return 0;
137 }
138
139 while (!in.atEnd()) {
140 line = in.readLine();
141 fields = line.split('\t');
142 if (fields.size() >= 2) {
143 xVal = fields.takeFirst().toDouble();
144 yVal = fields.takeFirst().toDouble();
145 xCoords.push_back(xVal);
146 yCoords.push_back(yVal);
147 }
148 else return 0;
149 }
150
151 file.close();
152 update();
153
154 return 1;
155 }*/
156
157int DiagramList::readList(const QString& path, std::vector<DiagramList*>& lists)
158{
159 QFile file(path);
160 QTextStream in(&file);
161
162 if (!file.open(QIODevice::ReadOnly))
163 {
164 qDebug("Could not open file...");
165 return 0;
166 }
167
168 QString line = in.readLine();
169 QStringList fields = line.split('\t');
170 int nLists(fields.size() - 1);
171
172 if (fields.size() >= 2)
173 {
174 fields.takeFirst();
175 for (int i = 0; i < nLists; i++)
176 {
177 auto* l = new DiagramList;
178 l->setName(fields.takeFirst());
179 // value = strtod(BaseLib::replaceStringreplaceString(",", ".",
180 // fields.takeFirst().toStdString()).c_str(),0);
181 // l->setStartDate(startDate);
182 // l->addNextPoint(0,value);
183 lists.push_back(l);
184 }
185
186 bool first_loop(true);
187 QDateTime startDate;
188 QDateTime currentDate;
189 unsigned line_count(1);
190
191 while (!in.atEnd())
192 {
193 line = in.readLine();
194 line_count++;
195 fields = line.split('\t');
196 if (fields.size() >= (nLists + 1))
197 {
198 QString const stringDate = fields.takeFirst();
199 currentDate = getDateTime(stringDate);
200 if (first_loop)
201 {
202 startDate = currentDate;
203 for (int i = 0; i < nLists; i++)
204 {
205 lists[i]->setStartDate(startDate);
206 }
207 first_loop = false;
208 }
209
210 auto const numberOfSecs =
211 static_cast<float>(startDate.secsTo(currentDate));
212 for (int i = 0; i < nLists; i++)
213 {
214 float const value = static_cast<float>(
216 ",", ".", fields.takeFirst().toStdString())
217 .c_str(),
218 nullptr));
219 lists[i]->addNextPoint(numberOfSecs, value);
220 }
221 }
222 else
223 {
224 WARN("DiagramList::readList(): Unexpected format in line {:d}.",
225 line_count);
226 file.close();
227 return 0;
228 }
229 }
230 }
231 else
232 {
233 qDebug("Unexpected file format...");
234 file.close();
235 return 0;
236 }
237
238 file.close();
239
240 for (int i = 0; i < nLists; i++)
241 {
242 lists[i]->update();
243 }
244
245 return nLists;
246}
247
249 std::vector<DiagramList*>& lists)
250{
251 std::vector<SensorDataType> const& time_series_names(
252 data->getTimeSeriesNames());
253 int nLists(time_series_names.size());
254
255 std::vector<std::size_t> time_steps;
256 if (data->getStepSize() > 0)
257 {
258 const std::size_t start = data->getStartTime();
259 const std::size_t end = data->getEndTime();
260 const std::size_t stepsize = data->getStepSize();
261 for (std::size_t i = start; i <= end; i += stepsize)
262 {
263 time_steps.push_back(i);
264 }
265 }
266 else
267 {
268 time_steps = data->getTimeSteps();
269 }
270
271 bool is_date(false);
272
273 if (!(BaseLib::int2date(time_steps[0])).empty())
274 {
275 is_date = true;
276 }
277
278 std::size_t nValues(time_steps.size());
279
280 for (int i = 0; i < nLists; i++)
281 {
282 auto const* time_series = data->getTimeSeries(time_series_names[i]);
283 if (!time_series)
284 {
285 continue;
286 }
287
288 auto* l = new DiagramList;
289 l->setName(QString::fromStdString(
290 SensorData::convertSensorDataType2String(time_series_names[i])));
291 l->setXLabel("Time");
292 lists.push_back(l);
293
294 if (is_date)
295 {
296 l->setXUnit("day");
297 QDateTime const startDate(
298 getDateTime(BaseLib::int2date(time_steps[0])));
299 lists[i]->setStartDate(startDate);
300 for (std::size_t j = 0; j < nValues; j++)
301 {
302 QDateTime const currentDate(
303 getDateTime(BaseLib::int2date(time_steps[j])));
304 auto numberOfSecs =
305 static_cast<float>(startDate.secsTo(currentDate));
306 lists[i]->addNextPoint(numberOfSecs, (*time_series)[j]);
307 }
308 }
309 else
310 {
311 l->setXUnit("time step");
312 for (std::size_t j = 0; j < nValues; j++)
313 {
314 lists[i]->addNextPoint(static_cast<float>(time_steps[j]),
315 (*time_series)[j]);
316 }
317 }
318
319 lists[i]->update();
320 }
321
322 return nLists;
323}
324
325void DiagramList::truncateToRange(QDateTime const& start, QDateTime const& end)
326{
327 auto start_secs = static_cast<float>(_startDate.secsTo(start));
328 if (start_secs < 0)
329 {
330 start_secs = 0;
331 }
332 auto end_secs = static_cast<float>(_startDate.secsTo(end));
333 if (end_secs < start_secs)
334 {
335 end_secs = _coords.back().first;
336 }
337
338 if (start_secs == 0 && end_secs == _coords.back().first)
339 {
340 return;
341 }
342
343 _coords.erase(std::remove_if(
344 _coords.begin(), _coords.end(),
345 [&](std::pair<float, float> const& c)
346 { return (c.first < start_secs || c.first > end_secs); }),
347 _coords.end());
348 _startDate = start;
349 for (auto& c : _coords)
350 {
351 c.first -= start_secs;
352 }
353 update();
354}
355
357 std::vector<std::pair<QDateTime, float>> const& coords)
358{
359 if (coords.empty())
360 {
361 return;
362 }
363
364 _startDate = coords[0].first;
365 std::transform(coords.begin(), coords.end(), std::back_inserter(_coords),
366 [this](auto const& p)
367 {
368 return std::make_pair(
369 static_cast<float>(_startDate.daysTo(p.first)),
370 p.second);
371 });
372
373 update();
374}
375
376void DiagramList::setList(std::vector<std::pair<float, float>> const& coords)
377{
378 if (coords.empty())
379 {
380 return;
381 }
382
383 this->_startDate = QDateTime();
384 std::copy(coords.begin(), coords.end(), std::back_inserter(_coords));
385 update();
386}
387
388std::size_t DiagramList::size() const
389{
390 return _coords.size();
391}
392
Definition of date helper functions.
Definition of the DiagramList class.
QDateTime getDateTime(QString const &stringDate)
Converts string into QDateTime-format.
Definition GetDateTime.h:18
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
Definition of the SensorData class.
Definition of string helper functions.
void update()
Updates the bounds of the data points contained in the list.
bool getPoint(QPointF &p, std::size_t i)
std::size_t size() const
Returns the number of data points.
void truncateToRange(QDateTime const &start, QDateTime const &end)
cut list entries not within the given range
DiagramList()
Constructor containing an empty list.
QDateTime _startDate
float calcMinXValue()
Returns the minimum x-value of all the data points.
static int readList(const QString &path, std::vector< DiagramList * > &list)
float calcMaxXValue()
Returns the maximum x-value of all the data points.
float calcMinYValue()
Returns the minimum y-value of all the data points.
float calcMaxYValue()
Returns the maximum y-value of all the data points.
std::vector< std::pair< float, float > > _coords
void setList(std::vector< std::pair< float, float > > const &coords)
bool getPath(QPainterPath &path, float scaleX, float scaleY)
A container for sensor data at an observation site. The class stores a number of time series and has ...
Definition SensorData.h:63
std::size_t getEndTime() const
Returns the last time step.
Definition SensorData.h:104
const std::vector< float > * getTimeSeries(SensorDataType time_series_name) const
Returns the time series with the given name.
const std::vector< std::size_t > & getTimeSteps() const
Returns the time step vector (if it exists)
Definition SensorData.h:98
std::size_t getStartTime() const
Returns the first time step.
Definition SensorData.h:101
const std::vector< SensorDataType > & getTimeSeriesNames() const
Returns all time series names contained in this container.
Definition SensorData.h:92
std::size_t getStepSize() const
Definition SensorData.h:108
static std::string convertSensorDataType2String(SensorDataType t)
Converts Sensor Data Types to Strings.
std::string replaceString(const std::string &searchString, const std::string &replaceString, std::string stringToReplace)
std::string int2date(int date)
Definition DateTools.cpp:42