##// END OF EJS Templates
Reorganizes methods in ArrayData...
Alexandre Leroux -
r507:1d47ad3c1bd3
parent child
Show More
@@ -1,218 +1,230
1 #ifndef SCIQLOP_ARRAYDATA_H
1 #ifndef SCIQLOP_ARRAYDATA_H
2 #define SCIQLOP_ARRAYDATA_H
2 #define SCIQLOP_ARRAYDATA_H
3
3
4 #include <Common/SortUtils.h>
4 #include <Common/SortUtils.h>
5
5
6 #include <QReadLocker>
6 #include <QReadLocker>
7 #include <QReadWriteLock>
7 #include <QReadWriteLock>
8 #include <QVector>
8 #include <QVector>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 template <int Dim>
12 template <int Dim>
13 class ArrayData;
13 class ArrayData;
14
14
15 using DataContainer = QVector<QVector<double> >;
15 using DataContainer = QVector<QVector<double> >;
16
16
17 namespace arraydata_detail {
17 namespace arraydata_detail {
18
18
19 /// Struct used to sort ArrayData
19 /// Struct used to sort ArrayData
20 template <int Dim>
20 template <int Dim>
21 struct Sort {
21 struct Sort {
22 static std::shared_ptr<ArrayData<Dim> > sort(const DataContainer &data,
22 static std::shared_ptr<ArrayData<Dim> > sort(const DataContainer &data,
23 const std::vector<int> &sortPermutation)
23 const std::vector<int> &sortPermutation)
24 {
24 {
25 auto nbComponents = data.size();
25 auto nbComponents = data.size();
26 auto sortedData = DataContainer(nbComponents);
26 auto sortedData = DataContainer(nbComponents);
27
27
28 for (auto i = 0; i < nbComponents; ++i) {
28 for (auto i = 0; i < nbComponents; ++i) {
29 sortedData[i] = SortUtils::sort(data.at(i), sortPermutation);
29 sortedData[i] = SortUtils::sort(data.at(i), sortPermutation);
30 }
30 }
31
31
32 return std::make_shared<ArrayData<Dim> >(std::move(sortedData));
32 return std::make_shared<ArrayData<Dim> >(std::move(sortedData));
33 }
33 }
34 };
34 };
35
35
36 /// Specialization for uni-dimensional ArrayData
36 /// Specialization for uni-dimensional ArrayData
37 template <>
37 template <>
38 struct Sort<1> {
38 struct Sort<1> {
39 static std::shared_ptr<ArrayData<1> > sort(const DataContainer &data,
39 static std::shared_ptr<ArrayData<1> > sort(const DataContainer &data,
40 const std::vector<int> &sortPermutation)
40 const std::vector<int> &sortPermutation)
41 {
41 {
42 return std::make_shared<ArrayData<1> >(SortUtils::sort(data.at(0), sortPermutation));
42 return std::make_shared<ArrayData<1> >(SortUtils::sort(data.at(0), sortPermutation));
43 }
43 }
44 };
44 };
45
45
46 } // namespace arraydata_detail
46 } // namespace arraydata_detail
47
47
48 /**
48 /**
49 * @brief The ArrayData class represents a dataset for a data series.
49 * @brief The ArrayData class represents a dataset for a data series.
50 *
50 *
51 * A dataset can be unidimensional or two-dimensional. This property is determined by the Dim
51 * A dataset can be unidimensional or two-dimensional. This property is determined by the Dim
52 * template-parameter. In a case of a two-dimensional dataset, each dataset component has the same
52 * template-parameter. In a case of a two-dimensional dataset, each dataset component has the same
53 * number of values
53 * number of values
54 *
54 *
55 * @tparam Dim the dimension of the ArrayData (one or two)
55 * @tparam Dim the dimension of the ArrayData (one or two)
56 * @sa IDataSeries
56 * @sa IDataSeries
57 */
57 */
58 template <int Dim>
58 template <int Dim>
59 class ArrayData {
59 class ArrayData {
60 public:
60 public:
61 // ///// //
62 // Ctors //
63 // ///// //
64
61 /**
65 /**
62 * Ctor for a unidimensional ArrayData
66 * Ctor for a unidimensional ArrayData
63 * @param data the data the ArrayData will hold
67 * @param data the data the ArrayData will hold
64 */
68 */
65 template <int D = Dim, typename = std::enable_if_t<D == 1> >
69 template <int D = Dim, typename = std::enable_if_t<D == 1> >
66 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
70 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
67 {
71 {
68 m_Data[0] = std::move(data);
72 m_Data[0] = std::move(data);
69 }
73 }
70
74
71 /**
75 /**
72 * Ctor for a two-dimensional ArrayData. The number of components (number of vectors) must be
76 * Ctor for a two-dimensional ArrayData. The number of components (number of vectors) must be
73 * greater than 2 and each component must have the same number of values
77 * greater than 2 and each component must have the same number of values
74 * @param data the data the ArrayData will hold
78 * @param data the data the ArrayData will hold
75 * @throws std::invalid_argument if the number of components is less than 2
79 * @throws std::invalid_argument if the number of components is less than 2
76 * @remarks if the number of values is not the same for each component, no value is set
80 * @remarks if the number of values is not the same for each component, no value is set
77 */
81 */
78 template <int D = Dim, typename = std::enable_if_t<D == 2> >
82 template <int D = Dim, typename = std::enable_if_t<D == 2> >
79 explicit ArrayData(DataContainer data)
83 explicit ArrayData(DataContainer data)
80 {
84 {
81 auto nbComponents = data.size();
85 auto nbComponents = data.size();
82 if (nbComponents < 2) {
86 if (nbComponents < 2) {
83 throw std::invalid_argument{
87 throw std::invalid_argument{
84 QString{"A multidimensional ArrayData must have at least 2 components (found: %1"}
88 QString{"A multidimensional ArrayData must have at least 2 components (found: %1"}
85 .arg(data.size())
89 .arg(data.size())
86 .toStdString()};
90 .toStdString()};
87 }
91 }
88
92
89 auto nbValues = data.front().size();
93 auto nbValues = data.front().size();
90 if (std::all_of(data.cbegin(), data.cend(), [nbValues](const auto &component) {
94 if (std::all_of(data.cbegin(), data.cend(), [nbValues](const auto &component) {
91 return component.size() == nbValues;
95 return component.size() == nbValues;
92 })) {
96 })) {
93 m_Data = std::move(data);
97 m_Data = std::move(data);
94 }
98 }
95 else {
99 else {
96 m_Data = DataContainer{nbComponents, QVector<double>{}};
100 m_Data = DataContainer{nbComponents, QVector<double>{}};
97 }
101 }
98 }
102 }
99
103
100 /// Copy ctor
104 /// Copy ctor
101 explicit ArrayData(const ArrayData &other)
105 explicit ArrayData(const ArrayData &other)
102 {
106 {
103 QReadLocker otherLocker{&other.m_Lock};
107 QReadLocker otherLocker{&other.m_Lock};
104 m_Data = other.m_Data;
108 m_Data = other.m_Data;
105 }
109 }
106
110
107 /**
111 // /////////////// //
108 * @return the data at a specified index
112 // General methods //
109 * @remarks index must be a valid position
113 // /////////////// //
110 * @remarks this method is only available for a unidimensional ArrayData
111 */
112 template <int D = Dim, typename = std::enable_if_t<D == 1> >
113 double at(int index) const noexcept
114 {
115 QReadLocker locker{&m_Lock};
116 return m_Data[0].at(index);
117 }
118
119 /**
120 * @return the data as a vector
121 * @remarks this method is only available for a unidimensional ArrayData
122 */
123 template <int D = Dim, typename = std::enable_if_t<D == 1> >
124 QVector<double> data() const noexcept
125 {
126 QReadLocker locker{&m_Lock};
127 return m_Data[0];
128 }
129
130 /**
131 * @return the data of a component
132 * @param componentIndex the index of the component to retrieve the data
133 * @return the component's data, empty vector if the index is invalid
134 */
135 QVector<double> data(int componentIndex) const noexcept
136 {
137 QReadLocker locker{&m_Lock};
138
139 return (componentIndex >= 0 && componentIndex < m_Data.size()) ? m_Data.at(componentIndex)
140 : QVector<double>{};
141 }
142
143 /**
144 * @return the data as a vector, as a const reference
145 * @remarks this method is only available for a unidimensional ArrayData
146 */
147 template <int D = Dim, typename = std::enable_if_t<D == 1> >
148 const QVector<double> &cdata() const noexcept
149 {
150 QReadLocker locker{&m_Lock};
151 return m_Data.at(0);
152 }
153
114
154 /**
115 /**
155 * Merges into the array data an other array data. The two array datas must have the same number
116 * Merges into the array data an other array data. The two array datas must have the same number
156 * of components so the merge can be done
117 * of components so the merge can be done
157 * @param other the array data to merge with
118 * @param other the array data to merge with
158 * @param prepend if true, the other array data is inserted at the beginning, otherwise it is
119 * @param prepend if true, the other array data is inserted at the beginning, otherwise it is
159 * inserted at the end
120 * inserted at the end
160 */
121 */
161 void add(const ArrayData<Dim> &other, bool prepend = false)
122 void add(const ArrayData<Dim> &other, bool prepend = false)
162 {
123 {
163 QWriteLocker locker{&m_Lock};
124 QWriteLocker locker{&m_Lock};
164 QReadLocker otherLocker{&other.m_Lock};
125 QReadLocker otherLocker{&other.m_Lock};
165
126
166 auto nbComponents = m_Data.size();
127 auto nbComponents = m_Data.size();
167 if (nbComponents != other.m_Data.size()) {
128 if (nbComponents != other.m_Data.size()) {
168 return;
129 return;
169 }
130 }
170
131
171 for (auto componentIndex = 0; componentIndex < nbComponents; ++componentIndex) {
132 for (auto componentIndex = 0; componentIndex < nbComponents; ++componentIndex) {
172 if (prepend) {
133 if (prepend) {
173 const auto &otherData = other.data(componentIndex);
134 const auto &otherData = other.data(componentIndex);
174 const auto otherDataSize = otherData.size();
135 const auto otherDataSize = otherData.size();
175
136
176 auto &data = m_Data[componentIndex];
137 auto &data = m_Data[componentIndex];
177 data.insert(data.begin(), otherDataSize, 0.);
138 data.insert(data.begin(), otherDataSize, 0.);
178
139
179 for (auto i = 0; i < otherDataSize; ++i) {
140 for (auto i = 0; i < otherDataSize; ++i) {
180 data.replace(i, otherData.at(i));
141 data.replace(i, otherData.at(i));
181 }
142 }
182 }
143 }
183 else {
144 else {
184 m_Data[componentIndex] += other.data(componentIndex);
145 m_Data[componentIndex] += other.data(componentIndex);
185 }
146 }
186 }
147 }
187 }
148 }
188
149
150 void clear()
151 {
152 QWriteLocker locker{&m_Lock};
153
154 auto nbComponents = m_Data.size();
155 for (auto i = 0; i < nbComponents; ++i) {
156 m_Data[i].clear();
157 }
158 }
159
160 /**
161 * @return the data of a component
162 * @param componentIndex the index of the component to retrieve the data
163 * @return the component's data, empty vector if the index is invalid
164 */
165 QVector<double> data(int componentIndex) const noexcept
166 {
167 QReadLocker locker{&m_Lock};
168
169 return (componentIndex >= 0 && componentIndex < m_Data.size()) ? m_Data.at(componentIndex)
170 : QVector<double>{};
171 }
172
189 /// @return the size (i.e. number of values) of a single component
173 /// @return the size (i.e. number of values) of a single component
190 /// @remarks in a case of a two-dimensional ArrayData, each component has the same size
174 /// @remarks in a case of a two-dimensional ArrayData, each component has the same size
191 int size() const
175 int size() const
192 {
176 {
193 QReadLocker locker{&m_Lock};
177 QReadLocker locker{&m_Lock};
194 return m_Data[0].size();
178 return m_Data[0].size();
195 }
179 }
196
180
197 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation)
181 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation)
198 {
182 {
199 QReadLocker locker{&m_Lock};
183 QReadLocker locker{&m_Lock};
200 return arraydata_detail::Sort<Dim>::sort(m_Data, sortPermutation);
184 return arraydata_detail::Sort<Dim>::sort(m_Data, sortPermutation);
201 }
185 }
202
186
203 void clear()
187 // ///////////// //
188 // 1-dim methods //
189 // ///////////// //
190
191 /**
192 * @return the data at a specified index
193 * @remarks index must be a valid position
194 * @remarks this method is only available for a unidimensional ArrayData
195 */
196 template <int D = Dim, typename = std::enable_if_t<D == 1> >
197 double at(int index) const noexcept
204 {
198 {
205 QWriteLocker locker{&m_Lock};
199 QReadLocker locker{&m_Lock};
200 return m_Data[0].at(index);
201 }
206
202
207 auto nbComponents = m_Data.size();
203 /**
208 for (auto i = 0; i < nbComponents; ++i) {
204 * @return the data as a vector, as a const reference
209 m_Data[i].clear();
205 * @remarks this method is only available for a unidimensional ArrayData
210 }
206 */
207 template <int D = Dim, typename = std::enable_if_t<D == 1> >
208 const QVector<double> &cdata() const noexcept
209 {
210 QReadLocker locker{&m_Lock};
211 return m_Data.at(0);
212 }
213
214 /**
215 * @return the data as a vector
216 * @remarks this method is only available for a unidimensional ArrayData
217 */
218 template <int D = Dim, typename = std::enable_if_t<D == 1> >
219 QVector<double> data() const noexcept
220 {
221 QReadLocker locker{&m_Lock};
222 return m_Data[0];
211 }
223 }
212
224
213 private:
225 private:
214 DataContainer m_Data;
226 DataContainer m_Data;
215 mutable QReadWriteLock m_Lock;
227 mutable QReadWriteLock m_Lock;
216 };
228 };
217
229
218 #endif // SCIQLOP_ARRAYDATA_H
230 #endif // SCIQLOP_ARRAYDATA_H
General Comments 0
You need to be logged in to leave comments. Login now