##// END OF EJS Templates
Reads variable's metadata to retrieve the type of data series (scalar, vector, spectrogram)
Alexandre Leroux -
r1333:88939ef97b8f
parent child
Show More
@@ -1,89 +1,93
1 1 #ifndef SCIQLOP_VARIABLE_H
2 2 #define SCIQLOP_VARIABLE_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/DataSeriesIterator.h>
7 #include <Data/DataSeriesType.h>
7 8 #include <Data/SqpRange.h>
8 9
9 10 #include <QLoggingCategory>
10 11 #include <QObject>
11 12
12 13 #include <Common/MetaTypes.h>
13 14 #include <Common/spimpl.h>
14 15
15 16 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
16 17
17 18 class IDataSeries;
18 19 class QString;
19 20
20 21 /**
21 22 * @brief The Variable class represents a variable in SciQlop.
22 23 */
23 24 class SCIQLOP_CORE_EXPORT Variable : public QObject {
24 25
25 26 Q_OBJECT
26 27
27 28 public:
28 29 explicit Variable(const QString &name, const QVariantHash &metadata = {});
29 30
30 31 /// Copy ctor
31 32 explicit Variable(const Variable &other);
32 33
33 34 std::shared_ptr<Variable> clone() const;
34 35
35 36 QString name() const noexcept;
36 37 void setName(const QString &name) noexcept;
37 38 SqpRange range() const noexcept;
38 39 void setRange(const SqpRange &range) noexcept;
39 40 SqpRange cacheRange() const noexcept;
40 41 void setCacheRange(const SqpRange &cacheRange) noexcept;
41 42
42 43 /// @return the number of points hold by the variable. The number of points is updated each time
43 44 /// the data series changes
44 45 int nbPoints() const noexcept;
45 46
46 47 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
47 48 /// series between the range of the variable. The real range is updated each time the variable
48 49 /// range or the data series changed
49 50 /// @return the real range, invalid range if the data series is null or empty
50 51 /// @sa setDataSeries()
51 52 /// @sa setRange()
52 53 SqpRange realRange() const noexcept;
53 54
54 55 /// @return the data of the variable, nullptr if there is no data
55 56 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
56 57
58 /// @return the type of data that the variable holds
59 DataSeriesType type() const noexcept;
60
57 61 QVariantHash metadata() const noexcept;
58 62
59 63 bool contains(const SqpRange &range) const noexcept;
60 64 bool intersect(const SqpRange &range) const noexcept;
61 65 bool isInside(const SqpRange &range) const noexcept;
62 66
63 67 bool cacheContains(const SqpRange &range) const noexcept;
64 68 bool cacheIntersect(const SqpRange &range) const noexcept;
65 69 bool cacheIsInside(const SqpRange &range) const noexcept;
66 70
67 71 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
68 72 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
69 73 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
70 74
71 75 static QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &oldRange,
72 76 const SqpRange &nextRange);
73 77
74 78 static QVector<SqpRange> provideInCacheRangeList(const SqpRange &oldRange,
75 79 const SqpRange &nextRange);
76 80
77 81 signals:
78 82 void updated();
79 83
80 84 private:
81 85 class VariablePrivate;
82 86 spimpl::unique_impl_ptr<VariablePrivate> impl;
83 87 };
84 88
85 89 // Required for using shared_ptr in signals/slots
86 90 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
87 91 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
88 92
89 93 #endif // SCIQLOP_VARIABLE_H
@@ -1,388 +1,423
1 1 #include "Variable/Variable.h"
2 2
3 3 #include <Data/IDataSeries.h>
4 4 #include <Data/SqpRange.h>
5 5
6 6 #include <QMutex>
7 7 #include <QReadWriteLock>
8 8 #include <QThread>
9 9
10 10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
11 11
12 namespace {
13
14 /**
15 * Searches in metadata for a value that can be converted to DataSeriesType
16 * @param metadata the metadata where to search
17 * @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise
18 * @sa DataSeriesType
19 */
20 DataSeriesType findDataSeriesType(const QVariantHash &metadata)
21 {
22 auto dataSeriesType = DataSeriesType::UNKNOWN;
23
24 // Go through the metadata and stop at the first value that could be converted to DataSeriesType
25 for (auto it = metadata.cbegin(), end = metadata.cend();
26 it != end && dataSeriesType == DataSeriesType::UNKNOWN; ++it) {
27 dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
28 }
29
30 return dataSeriesType;
31 }
32
33 } // namespace
34
12 35 struct Variable::VariablePrivate {
13 36 explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
14 37 : m_Name{name},
15 38 m_Range{INVALID_RANGE},
16 39 m_CacheRange{INVALID_RANGE},
17 40 m_Metadata{metadata},
18 41 m_DataSeries{nullptr},
19 42 m_RealRange{INVALID_RANGE},
20 m_NbPoints{0}
43 m_NbPoints{0},
44 m_Type{findDataSeriesType(m_Metadata)}
21 45 {
22 46 }
23 47
24 48 VariablePrivate(const VariablePrivate &other)
25 49 : m_Name{other.m_Name},
26 50 m_Range{other.m_Range},
27 51 m_CacheRange{other.m_CacheRange},
28 52 m_Metadata{other.m_Metadata},
29 53 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
30 54 m_RealRange{other.m_RealRange},
31 m_NbPoints{other.m_NbPoints}
55 m_NbPoints{other.m_NbPoints},
56 m_Type{findDataSeriesType(m_Metadata)}
32 57 {
33 58 }
34 59
35 60 void lockRead() { m_Lock.lockForRead(); }
36 61 void lockWrite() { m_Lock.lockForWrite(); }
37 62 void unlock() { m_Lock.unlock(); }
38 63
39 64 void purgeDataSeries()
40 65 {
41 66 if (m_DataSeries) {
42 67 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
43 68 }
44 69 updateRealRange();
45 70 updateNbPoints();
46 71 }
47 72
48 73 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
49 74
50 75 /// Updates real range according to current variable range and data series
51 76 void updateRealRange()
52 77 {
53 78 if (m_DataSeries) {
54 79 m_DataSeries->lockRead();
55 80 auto end = m_DataSeries->cend();
56 81 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
57 82 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
58 83
59 84 m_RealRange
60 85 = (minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
61 86 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
62 87 : INVALID_RANGE;
63 88 m_DataSeries->unlock();
64 89 }
65 90 else {
66 91 m_RealRange = INVALID_RANGE;
67 92 }
68 93 }
69 94
70 95 QString m_Name;
71 96
72 97 SqpRange m_Range;
73 98 SqpRange m_CacheRange;
74 99 QVariantHash m_Metadata;
75 100 std::shared_ptr<IDataSeries> m_DataSeries;
76 101 SqpRange m_RealRange;
77 102 int m_NbPoints;
103 DataSeriesType m_Type;
78 104
79 105 QReadWriteLock m_Lock;
80 106 };
81 107
82 108 Variable::Variable(const QString &name, const QVariantHash &metadata)
83 109 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)}
84 110 {
85 111 }
86 112
87 113 Variable::Variable(const Variable &other)
88 114 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)}
89 115 {
90 116 }
91 117
92 118 std::shared_ptr<Variable> Variable::clone() const
93 119 {
94 120 return std::make_shared<Variable>(*this);
95 121 }
96 122
97 123 QString Variable::name() const noexcept
98 124 {
99 125 impl->lockRead();
100 126 auto name = impl->m_Name;
101 127 impl->unlock();
102 128 return name;
103 129 }
104 130
105 131 void Variable::setName(const QString &name) noexcept
106 132 {
107 133 impl->lockWrite();
108 134 impl->m_Name = name;
109 135 impl->unlock();
110 136 }
111 137
112 138 SqpRange Variable::range() const noexcept
113 139 {
114 140 impl->lockRead();
115 141 auto range = impl->m_Range;
116 142 impl->unlock();
117 143 return range;
118 144 }
119 145
120 146 void Variable::setRange(const SqpRange &range) noexcept
121 147 {
122 148 impl->lockWrite();
123 149 impl->m_Range = range;
124 150 impl->updateRealRange();
125 151 impl->unlock();
126 152 }
127 153
128 154 SqpRange Variable::cacheRange() const noexcept
129 155 {
130 156 impl->lockRead();
131 157 auto cacheRange = impl->m_CacheRange;
132 158 impl->unlock();
133 159 return cacheRange;
134 160 }
135 161
136 162 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
137 163 {
138 164 impl->lockWrite();
139 165 if (cacheRange != impl->m_CacheRange) {
140 166 impl->m_CacheRange = cacheRange;
141 167 }
142 168 impl->unlock();
143 169 }
144 170
145 171 int Variable::nbPoints() const noexcept
146 172 {
147 173 return impl->m_NbPoints;
148 174 }
149 175
150 176 SqpRange Variable::realRange() const noexcept
151 177 {
152 178 return impl->m_RealRange;
153 179 }
154 180
155 181 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
156 182 {
157 183 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
158 184 << QThread::currentThread()->objectName();
159 185 if (!dataSeries) {
160 186 /// @todo ALX : log
161 187 return;
162 188 }
163 189
164 190 // Add or merge the data
165 191 impl->lockWrite();
166 192 if (!impl->m_DataSeries) {
167 193 impl->m_DataSeries = dataSeries->clone();
168 194 }
169 195 else {
170 196 impl->m_DataSeries->merge(dataSeries.get());
171 197 }
172 198 impl->purgeDataSeries();
173 199 impl->unlock();
174 200 }
175 201
176 202
177 203 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
178 204 {
179 205 impl->lockRead();
180 206 auto dataSeries = impl->m_DataSeries;
181 207 impl->unlock();
182 208
183 209 return dataSeries;
184 210 }
185 211
212 DataSeriesType Variable::type() const noexcept
213 {
214 impl->lockRead();
215 auto type = impl->m_Type;
216 impl->unlock();
217
218 return type;
219 }
220
186 221 QVariantHash Variable::metadata() const noexcept
187 222 {
188 223 impl->lockRead();
189 224 auto metadata = impl->m_Metadata;
190 225 impl->unlock();
191 226 return metadata;
192 227 }
193 228
194 229 bool Variable::contains(const SqpRange &range) const noexcept
195 230 {
196 231 impl->lockRead();
197 232 auto res = impl->m_Range.contains(range);
198 233 impl->unlock();
199 234 return res;
200 235 }
201 236
202 237 bool Variable::intersect(const SqpRange &range) const noexcept
203 238 {
204 239
205 240 impl->lockRead();
206 241 auto res = impl->m_Range.intersect(range);
207 242 impl->unlock();
208 243 return res;
209 244 }
210 245
211 246 bool Variable::isInside(const SqpRange &range) const noexcept
212 247 {
213 248 impl->lockRead();
214 249 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
215 250 impl->unlock();
216 251 return res;
217 252 }
218 253
219 254 bool Variable::cacheContains(const SqpRange &range) const noexcept
220 255 {
221 256 impl->lockRead();
222 257 auto res = impl->m_CacheRange.contains(range);
223 258 impl->unlock();
224 259 return res;
225 260 }
226 261
227 262 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
228 263 {
229 264 impl->lockRead();
230 265 auto res = impl->m_CacheRange.intersect(range);
231 266 impl->unlock();
232 267 return res;
233 268 }
234 269
235 270 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
236 271 {
237 272 impl->lockRead();
238 273 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
239 274 impl->unlock();
240 275 return res;
241 276 }
242 277
243 278
244 279 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
245 280 {
246 281 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
247 282 auto notInCache = QVector<SqpRange>{};
248 283 if (impl->m_CacheRange != INVALID_RANGE) {
249 284
250 285 if (!this->cacheContains(range)) {
251 286 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
252 287 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
253 288 notInCache << range;
254 289 }
255 290 else if (range.m_TStart < impl->m_CacheRange.m_TStart
256 291 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
257 292 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
258 293 }
259 294 else if (range.m_TStart < impl->m_CacheRange.m_TStart
260 295 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
261 296 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
262 297 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
263 298 }
264 299 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
265 300 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
266 301 }
267 302 else {
268 303 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
269 304 << QThread::currentThread();
270 305 }
271 306 }
272 307 }
273 308 else {
274 309 notInCache << range;
275 310 }
276 311
277 312 return notInCache;
278 313 }
279 314
280 315 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
281 316 {
282 317 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
283 318
284 319 auto inCache = QVector<SqpRange>{};
285 320
286 321 if (impl->m_CacheRange != INVALID_RANGE) {
287 322
288 323 if (this->cacheIntersect(range)) {
289 324 if (range.m_TStart <= impl->m_CacheRange.m_TStart
290 325 && range.m_TEnd >= impl->m_CacheRange.m_TStart
291 326 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
292 327 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
293 328 }
294 329
295 330 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
296 331 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
297 332 inCache << range;
298 333 }
299 334 else if (range.m_TStart > impl->m_CacheRange.m_TStart
300 335 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
301 336 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
302 337 }
303 338 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
304 339 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
305 340 inCache << impl->m_CacheRange;
306 341 }
307 342 else {
308 343 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
309 344 << QThread::currentThread();
310 345 }
311 346 }
312 347 }
313 348
314 349 return inCache;
315 350 }
316 351
317 352
318 353 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &oldRange,
319 354 const SqpRange &nextRange)
320 355 {
321 356
322 357 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
323 358 auto notInCache = QVector<SqpRange>{};
324 359 if (oldRange != INVALID_RANGE) {
325 360
326 361 if (!oldRange.contains(nextRange)) {
327 362 if (nextRange.m_TEnd <= oldRange.m_TStart || nextRange.m_TStart >= oldRange.m_TEnd) {
328 363 notInCache << nextRange;
329 364 }
330 365 else if (nextRange.m_TStart < oldRange.m_TStart
331 366 && nextRange.m_TEnd <= oldRange.m_TEnd) {
332 367 notInCache << SqpRange{nextRange.m_TStart, oldRange.m_TStart};
333 368 }
334 369 else if (nextRange.m_TStart < oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
335 370 notInCache << SqpRange{nextRange.m_TStart, oldRange.m_TStart}
336 371 << SqpRange{oldRange.m_TEnd, nextRange.m_TEnd};
337 372 }
338 373 else if (nextRange.m_TStart < oldRange.m_TEnd) {
339 374 notInCache << SqpRange{oldRange.m_TEnd, nextRange.m_TEnd};
340 375 }
341 376 else {
342 377 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
343 378 << QThread::currentThread();
344 379 }
345 380 }
346 381 }
347 382 else {
348 383 notInCache << nextRange;
349 384 }
350 385
351 386 return notInCache;
352 387 }
353 388
354 389 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &oldRange,
355 390 const SqpRange &nextRange)
356 391 {
357 392 // This code assume that cach is contigue. Can return 0 or 1 SqpRange
358 393
359 394 auto inCache = QVector<SqpRange>{};
360 395
361 396 if (oldRange != INVALID_RANGE) {
362 397
363 398 if (oldRange.intersect(nextRange)) {
364 399 if (nextRange.m_TStart <= oldRange.m_TStart && nextRange.m_TEnd >= oldRange.m_TStart
365 400 && nextRange.m_TEnd < oldRange.m_TEnd) {
366 401 inCache << SqpRange{oldRange.m_TStart, nextRange.m_TEnd};
367 402 }
368 403
369 404 else if (nextRange.m_TStart >= oldRange.m_TStart
370 405 && nextRange.m_TEnd <= oldRange.m_TEnd) {
371 406 inCache << nextRange;
372 407 }
373 408 else if (nextRange.m_TStart > oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
374 409 inCache << SqpRange{nextRange.m_TStart, oldRange.m_TEnd};
375 410 }
376 411 else if (nextRange.m_TStart <= oldRange.m_TStart
377 412 && nextRange.m_TEnd >= oldRange.m_TEnd) {
378 413 inCache << oldRange;
379 414 }
380 415 else {
381 416 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
382 417 << QThread::currentThread();
383 418 }
384 419 }
385 420 }
386 421
387 422 return inCache;
388 423 }
General Comments 0
You need to be logged in to leave comments. Login now