##// END OF EJS Templates
Updates declaration of logger to avoid multiple definitions
Alexandre Leroux -
r562:d3e47b0fbfb0
parent child
Show More
@@ -1,288 +1,293
1 1 #ifndef SCIQLOP_DATASERIES_H
2 2 #define SCIQLOP_DATASERIES_H
3 3
4 #include "CoreGlobal.h"
5
4 6 #include <Common/SortUtils.h>
5 7
6 8 #include <Data/ArrayData.h>
7 9 #include <Data/IDataSeries.h>
8 10
9 11 #include <QLoggingCategory>
10
11 12 #include <QReadLocker>
12 13 #include <QReadWriteLock>
13 14 #include <memory>
14 15
15 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeries)
16 Q_LOGGING_CATEGORY(LOG_DataSeries, "DataSeries")
17
16 // We don't use the Qt macro since the log is used in the header file, which causes multiple log
17 // definitions with inheritance. Inline method is used instead
18 inline const QLoggingCategory &LOG_DataSeries()
19 {
20 static const QLoggingCategory category{"DataSeries"};
21 return category;
22 }
18 23
19 24 /**
20 25 * @brief The DataSeries class is the base (abstract) implementation of IDataSeries.
21 26 *
22 27 * It proposes to set a dimension for the values ​​data.
23 28 *
24 29 * A DataSeries is always sorted on its x-axis data.
25 30 *
26 31 * @tparam Dim The dimension of the values data
27 32 *
28 33 */
29 34 template <int Dim>
30 class DataSeries : public IDataSeries {
35 class SCIQLOP_CORE_EXPORT DataSeries : public IDataSeries {
31 36 public:
32 37 class IteratorValue {
33 38 public:
34 39 explicit IteratorValue(const DataSeries &dataSeries, bool begin)
35 40 : m_XIt(begin ? dataSeries.xAxisData()->cbegin() : dataSeries.xAxisData()->cend()),
36 41 m_ValuesIt(begin ? dataSeries.valuesData()->cbegin()
37 42 : dataSeries.valuesData()->cend())
38 43 {
39 44 }
40 45
41 46 double x() const { return m_XIt->at(0); }
42 47 double value() const { return m_ValuesIt->at(0); }
43 48 double value(int componentIndex) const { return m_ValuesIt->at(componentIndex); }
44 49
45 50 void next()
46 51 {
47 52 ++m_XIt;
48 53 ++m_ValuesIt;
49 54 }
50 55
51 56 bool operator==(const IteratorValue &other) const
52 57 {
53 58 return std::tie(m_XIt, m_ValuesIt) == std::tie(other.m_XIt, other.m_ValuesIt);
54 59 }
55 60
56 61 private:
57 62 ArrayData<1>::Iterator m_XIt;
58 63 typename ArrayData<Dim>::Iterator m_ValuesIt;
59 64 };
60 65
61 66 class Iterator {
62 67 public:
63 68 using iterator_category = std::forward_iterator_tag;
64 69 using value_type = const IteratorValue;
65 70 using difference_type = std::ptrdiff_t;
66 71 using pointer = value_type *;
67 72 using reference = value_type &;
68 73
69 74 Iterator(const DataSeries &dataSeries, bool begin) : m_CurrentValue{dataSeries, begin} {}
70 75 virtual ~Iterator() noexcept = default;
71 76 Iterator(const Iterator &) = default;
72 77 Iterator(Iterator &&) = default;
73 78 Iterator &operator=(const Iterator &) = default;
74 79 Iterator &operator=(Iterator &&) = default;
75 80
76 81 Iterator &operator++()
77 82 {
78 83 m_CurrentValue.next();
79 84 return *this;
80 85 }
81 86
82 87 pointer operator->() const { return &m_CurrentValue; }
83 88
84 89 reference operator*() const { return m_CurrentValue; }
85 90
86 91 bool operator==(const Iterator &other) const
87 92 {
88 93 return m_CurrentValue == other.m_CurrentValue;
89 94 }
90 95
91 96 bool operator!=(const Iterator &other) const { return !(*this == other); }
92 97
93 98 private:
94 99 IteratorValue m_CurrentValue;
95 100 };
96 101
97 102 /// @sa IDataSeries::xAxisData()
98 103 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
99 104 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
100 105
101 106 /// @sa IDataSeries::xAxisUnit()
102 107 Unit xAxisUnit() const override { return m_XAxisUnit; }
103 108
104 109 /// @return the values dataset
105 110 std::shared_ptr<ArrayData<Dim> > valuesData() { return m_ValuesData; }
106 111 const std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; }
107 112
108 113 /// @sa IDataSeries::valuesUnit()
109 114 Unit valuesUnit() const override { return m_ValuesUnit; }
110 115
111 116
112 117 SqpRange range() const override
113 118 {
114 119 if (!m_XAxisData->cdata().isEmpty()) {
115 120 return SqpRange{m_XAxisData->cdata().first(), m_XAxisData->cdata().last()};
116 121 }
117 122
118 123 return SqpRange{};
119 124 }
120 125
121 126 void clear()
122 127 {
123 128 m_XAxisData->clear();
124 129 m_ValuesData->clear();
125 130 }
126 131
127 132 /// Merges into the data series an other data series
128 133 /// @remarks the data series to merge with is cleared after the operation
129 134 void merge(IDataSeries *dataSeries) override
130 135 {
131 136 dataSeries->lockWrite();
132 137 lockWrite();
133 138
134 139 if (auto other = dynamic_cast<DataSeries<Dim> *>(dataSeries)) {
135 140 const auto &otherXAxisData = other->xAxisData()->cdata();
136 141 const auto &xAxisData = m_XAxisData->cdata();
137 142
138 143 // As data series are sorted, we can improve performances of merge, by call the sort
139 144 // method only if the two data series overlap.
140 145 if (!otherXAxisData.empty()) {
141 146 auto firstValue = otherXAxisData.front();
142 147 auto lastValue = otherXAxisData.back();
143 148
144 149 auto xAxisDataBegin = xAxisData.cbegin();
145 150 auto xAxisDataEnd = xAxisData.cend();
146 151
147 152 bool prepend;
148 153 bool sortNeeded;
149 154
150 155 if (std::lower_bound(xAxisDataBegin, xAxisDataEnd, firstValue) == xAxisDataEnd) {
151 156 // Other data series if after data series
152 157 prepend = false;
153 158 sortNeeded = false;
154 159 }
155 160 else if (std::upper_bound(xAxisDataBegin, xAxisDataEnd, lastValue)
156 161 == xAxisDataBegin) {
157 162 // Other data series if before data series
158 163 prepend = true;
159 164 sortNeeded = false;
160 165 }
161 166 else {
162 167 // The two data series overlap
163 168 prepend = false;
164 169 sortNeeded = true;
165 170 }
166 171
167 172 // Makes the merge
168 173 m_XAxisData->add(*other->xAxisData(), prepend);
169 174 m_ValuesData->add(*other->valuesData(), prepend);
170 175
171 176 if (sortNeeded) {
172 177 sort();
173 178 }
174 179 }
175 180
176 181 // Clears the other data series
177 182 other->clear();
178 183 }
179 184 else {
180 185 qCWarning(LOG_DataSeries())
181 186 << QObject::tr("Detection of a type of IDataSeries we cannot merge with !");
182 187 }
183 188 unlock();
184 189 dataSeries->unlock();
185 190 }
186 191
187 192 // ///////// //
188 193 // Iterators //
189 194 // ///////// //
190 195
191 196 Iterator cbegin() const { return Iterator{*this, true}; }
192 197
193 198 Iterator cend() const { return Iterator{*this, false}; }
194 199
195 200 std::pair<Iterator, Iterator> subData(double min, double max) const
196 201 {
197 202 if (min > max) {
198 203 std::swap(min, max);
199 204 }
200 205
201 206 auto begin = cbegin();
202 207 auto end = cend();
203 208
204 209 auto lowerIt
205 210 = std::lower_bound(begin, end, min, [](const auto &itValue, const auto &value) {
206 211 return itValue.x() == value;
207 212 });
208 213 auto upperIt
209 214 = std::upper_bound(begin, end, max, [](const auto &value, const auto &itValue) {
210 215 return itValue.x() == value;
211 216 });
212 217
213 218 return std::make_pair(lowerIt, upperIt);
214 219 }
215 220
216 221 // /////// //
217 222 // Mutexes //
218 223 // /////// //
219 224
220 225 virtual void lockRead() { m_Lock.lockForRead(); }
221 226 virtual void lockWrite() { m_Lock.lockForWrite(); }
222 227 virtual void unlock() { m_Lock.unlock(); }
223 228
224 229 protected:
225 230 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
226 231 /// DataSeries with no values will be created.
227 232 /// @remarks data series is automatically sorted on its x-axis data
228 233 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit,
229 234 std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit)
230 235 : m_XAxisData{xAxisData},
231 236 m_XAxisUnit{xAxisUnit},
232 237 m_ValuesData{valuesData},
233 238 m_ValuesUnit{valuesUnit}
234 239 {
235 240 if (m_XAxisData->size() != m_ValuesData->size()) {
236 241 clear();
237 242 }
238 243
239 244 // Sorts data if it's not the case
240 245 const auto &xAxisCData = m_XAxisData->cdata();
241 246 if (!std::is_sorted(xAxisCData.cbegin(), xAxisCData.cend())) {
242 247 sort();
243 248 }
244 249 }
245 250
246 251 /// Copy ctor
247 252 explicit DataSeries(const DataSeries<Dim> &other)
248 253 : m_XAxisData{std::make_shared<ArrayData<1> >(*other.m_XAxisData)},
249 254 m_XAxisUnit{other.m_XAxisUnit},
250 255 m_ValuesData{std::make_shared<ArrayData<Dim> >(*other.m_ValuesData)},
251 256 m_ValuesUnit{other.m_ValuesUnit}
252 257 {
253 258 // Since a series is ordered from its construction and is always ordered, it is not
254 259 // necessary to call the sort method here ('other' is sorted)
255 260 }
256 261
257 262 /// Assignment operator
258 263 template <int D>
259 264 DataSeries &operator=(DataSeries<D> other)
260 265 {
261 266 std::swap(m_XAxisData, other.m_XAxisData);
262 267 std::swap(m_XAxisUnit, other.m_XAxisUnit);
263 268 std::swap(m_ValuesData, other.m_ValuesData);
264 269 std::swap(m_ValuesUnit, other.m_ValuesUnit);
265 270
266 271 return *this;
267 272 }
268 273
269 274 private:
270 275 /**
271 276 * Sorts data series on its x-axis data
272 277 */
273 278 void sort() noexcept
274 279 {
275 280 auto permutation = SortUtils::sortPermutation(*m_XAxisData, std::less<double>());
276 281 m_XAxisData = m_XAxisData->sort(permutation);
277 282 m_ValuesData = m_ValuesData->sort(permutation);
278 283 }
279 284
280 285 std::shared_ptr<ArrayData<1> > m_XAxisData;
281 286 Unit m_XAxisUnit;
282 287 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
283 288 Unit m_ValuesUnit;
284 289
285 290 QReadWriteLock m_Lock;
286 291 };
287 292
288 293 #endif // SCIQLOP_DATASERIES_H
@@ -1,44 +1,45
1 1 # On ignore toutes les règles vera++ pour le fichier spimpl
2 2 Common/spimpl\.h:\d+:.*
3 3
4 4 # Ignore false positive relative to two class definitions in a same file
5 5 DataSourceItem\.h:\d+:.*IPSIS_S01.*
6 6
7 7 # Ignore false positive relative to a template class
8 8 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (D)
9 9 ArrayData\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (arraydata_detail)
10 10 ArrayData\.h:\d+:.*IPSIS_S06.*found: (D)
11 11 ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim)
12 DataSeries\.h:\d+:.*IPSIS_S04_METHOD.*found: LOG_DataSeries
12 13 DataSeries\.h:\d+:.*IPSIS_S04_VARIABLE.*
13 14
14 15 # Ignore false positive relative to iterators
15 16 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (forward_iterator_tag)
16 17 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (IteratorValue)
17 18 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (ptrdiff_t)
18 19 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (value_type)
19 20 ArrayData\.h:\d+:.*IPSIS_S05.*
20 21 ArrayData\.h:\d+:.*IPSIS_S06.*found: (iterator_category)
21 22 ArrayData\.h:\d+:.*IPSIS_S06.*found: (forward_iterator_tag)
22 23 ArrayData\.h:\d+:.*IPSIS_S06.*found: (value_type)
23 24 ArrayData\.h:\d+:.*IPSIS_S06.*found: (IteratorValue)
24 25 ArrayData\.h:\d+:.*IPSIS_S06.*found: (difference_type)
25 26 ArrayData\.h:\d+:.*IPSIS_S06.*found: (ptrdiff_t)
26 27 ArrayData\.h:\d+:.*IPSIS_S06.*found: (pointer)
27 28 ArrayData\.h:\d+:.*IPSIS_S06.*found: (reference)
28 29 ArrayData\.h:\d+:.*IPSIS_S06.*found: (value_type)
29 30 DataSeries\.h:\d+:.*IPSIS_S05.*
30 31 DataSeries\.h:\d+:.*IPSIS_S06.*found: (iterator_category)
31 32 DataSeries\.h:\d+:.*IPSIS_S06.*found: (forward_iterator_tag)
32 33 DataSeries\.h:\d+:.*IPSIS_S06.*found: (value_type)
33 34 DataSeries\.h:\d+:.*IPSIS_S06.*found: (IteratorValue)
34 35 DataSeries\.h:\d+:.*IPSIS_S06.*found: (difference_type)
35 36 DataSeries\.h:\d+:.*IPSIS_S06.*found: (ptrdiff_t)
36 37 DataSeries\.h:\d+:.*IPSIS_S06.*found: (pointer)
37 38 DataSeries\.h:\d+:.*IPSIS_S06.*found: (reference)
38 39 DataSeries\.h:\d+:.*IPSIS_S06.*found: (value_type)
39 40
40 41 # Ignore false positive relative to an alias
41 42 DataSourceItemAction\.h:\d+:.*IPSIS_S06.*found: (ExecuteFunction)
42 43
43 44 # Ignore false positive relative to unnamed namespace
44 45 VariableController\.cpp:\d+:.*IPSIS_F13.*
General Comments 0
You need to be logged in to leave comments. Login now