##// END OF EJS Templates
Adapts add() method to 2-dim array data
Alexandre Leroux -
r506:0599461b95ff
parent child
Show More
@@ -1,201 +1,218
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 /**
61 /**
62 * Ctor for a unidimensional ArrayData
62 * Ctor for a unidimensional ArrayData
63 * @param data the data the ArrayData will hold
63 * @param data the data the ArrayData will hold
64 */
64 */
65 template <int D = Dim, typename = std::enable_if_t<D == 1> >
65 template <int D = Dim, typename = std::enable_if_t<D == 1> >
66 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
66 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
67 {
67 {
68 m_Data[0] = std::move(data);
68 m_Data[0] = std::move(data);
69 }
69 }
70
70
71 /**
71 /**
72 * Ctor for a two-dimensional ArrayData. The number of components (number of vectors) must be
72 * 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
73 * greater than 2 and each component must have the same number of values
74 * @param data the data the ArrayData will hold
74 * @param data the data the ArrayData will hold
75 * @throws std::invalid_argument if the number of components is less than 2
75 * @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
76 * @remarks if the number of values is not the same for each component, no value is set
77 */
77 */
78 template <int D = Dim, typename = std::enable_if_t<D == 2> >
78 template <int D = Dim, typename = std::enable_if_t<D == 2> >
79 explicit ArrayData(DataContainer data)
79 explicit ArrayData(DataContainer data)
80 {
80 {
81 auto nbComponents = data.size();
81 auto nbComponents = data.size();
82 if (nbComponents < 2) {
82 if (nbComponents < 2) {
83 throw std::invalid_argument{
83 throw std::invalid_argument{
84 QString{"A multidimensional ArrayData must have at least 2 components (found: %1"}
84 QString{"A multidimensional ArrayData must have at least 2 components (found: %1"}
85 .arg(data.size())
85 .arg(data.size())
86 .toStdString()};
86 .toStdString()};
87 }
87 }
88
88
89 auto nbValues = data.front().size();
89 auto nbValues = data.front().size();
90 if (std::all_of(data.cbegin(), data.cend(), [nbValues](const auto &component) {
90 if (std::all_of(data.cbegin(), data.cend(), [nbValues](const auto &component) {
91 return component.size() == nbValues;
91 return component.size() == nbValues;
92 })) {
92 })) {
93 m_Data = std::move(data);
93 m_Data = std::move(data);
94 }
94 }
95 else {
95 else {
96 m_Data = DataContainer{nbComponents, QVector<double>{}};
96 m_Data = DataContainer{nbComponents, QVector<double>{}};
97 }
97 }
98 }
98 }
99
99
100 /// Copy ctor
100 /// Copy ctor
101 explicit ArrayData(const ArrayData &other)
101 explicit ArrayData(const ArrayData &other)
102 {
102 {
103 QReadLocker otherLocker{&other.m_Lock};
103 QReadLocker otherLocker{&other.m_Lock};
104 m_Data = other.m_Data;
104 m_Data = other.m_Data;
105 }
105 }
106
106
107 /**
107 /**
108 * @return the data at a specified index
108 * @return the data at a specified index
109 * @remarks index must be a valid position
109 * @remarks index must be a valid position
110 * @remarks this method is only available for a unidimensional ArrayData
110 * @remarks this method is only available for a unidimensional ArrayData
111 */
111 */
112 template <int D = Dim, typename = std::enable_if_t<D == 1> >
112 template <int D = Dim, typename = std::enable_if_t<D == 1> >
113 double at(int index) const noexcept
113 double at(int index) const noexcept
114 {
114 {
115 QReadLocker locker{&m_Lock};
115 QReadLocker locker{&m_Lock};
116 return m_Data[0].at(index);
116 return m_Data[0].at(index);
117 }
117 }
118
118
119 /**
119 /**
120 * @return the data as a vector
120 * @return the data as a vector
121 * @remarks this method is only available for a unidimensional ArrayData
121 * @remarks this method is only available for a unidimensional ArrayData
122 */
122 */
123 template <int D = Dim, typename = std::enable_if_t<D == 1> >
123 template <int D = Dim, typename = std::enable_if_t<D == 1> >
124 QVector<double> data() const noexcept
124 QVector<double> data() const noexcept
125 {
125 {
126 QReadLocker locker{&m_Lock};
126 QReadLocker locker{&m_Lock};
127 return m_Data[0];
127 return m_Data[0];
128 }
128 }
129
129
130 /**
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 /**
131 * @return the data as a vector, as a const reference
144 * @return the data as a vector, as a const reference
132 * @remarks this method is only available for a unidimensional ArrayData
145 * @remarks this method is only available for a unidimensional ArrayData
133 */
146 */
134 template <int D = Dim, typename = std::enable_if_t<D == 1> >
147 template <int D = Dim, typename = std::enable_if_t<D == 1> >
135 const QVector<double> &cdata() const noexcept
148 const QVector<double> &cdata() const noexcept
136 {
149 {
137 QReadLocker locker{&m_Lock};
150 QReadLocker locker{&m_Lock};
138 return m_Data.at(0);
151 return m_Data.at(0);
139 }
152 }
140
153
141 /**
154 /**
142 * Merges into the array data an other array data
155 * 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
143 * @param other the array data to merge with
157 * @param other the array data to merge with
144 * @param prepend if true, the other array data is inserted at the beginning, otherwise it is
158 * @param prepend if true, the other array data is inserted at the beginning, otherwise it is
145 * inserted at the end
159 * inserted at the end
146 * @remarks this method is only available for a unidimensional ArrayData
147 */
160 */
148 template <int D = Dim, typename = std::enable_if_t<D == 1> >
161 void add(const ArrayData<Dim> &other, bool prepend = false)
149 void add(const ArrayData<1> &other, bool prepend = false)
150 {
162 {
151 QWriteLocker locker{&m_Lock};
163 QWriteLocker locker{&m_Lock};
152 if (!m_Data.empty()) {
164 QReadLocker otherLocker{&other.m_Lock};
153 QReadLocker otherLocker{&other.m_Lock};
165
166 auto nbComponents = m_Data.size();
167 if (nbComponents != other.m_Data.size()) {
168 return;
169 }
154
170
171 for (auto componentIndex = 0; componentIndex < nbComponents; ++componentIndex) {
155 if (prepend) {
172 if (prepend) {
156 const auto &otherData = other.data();
173 const auto &otherData = other.data(componentIndex);
157 const auto otherDataSize = otherData.size();
174 const auto otherDataSize = otherData.size();
158
175
159 auto &data = m_Data[0];
176 auto &data = m_Data[componentIndex];
160 data.insert(data.begin(), otherDataSize, 0.);
177 data.insert(data.begin(), otherDataSize, 0.);
161
178
162 for (auto i = 0; i < otherDataSize; ++i) {
179 for (auto i = 0; i < otherDataSize; ++i) {
163 data.replace(i, otherData.at(i));
180 data.replace(i, otherData.at(i));
164 }
181 }
165 }
182 }
166 else {
183 else {
167 m_Data[0] += other.data();
184 m_Data[componentIndex] += other.data(componentIndex);
168 }
185 }
169 }
186 }
170 }
187 }
171
188
172 /// @return the size (i.e. number of values) of a single component
189 /// @return the size (i.e. number of values) of a single component
173 /// @remarks in a case of a two-dimensional ArrayData, each component has the same size
190 /// @remarks in a case of a two-dimensional ArrayData, each component has the same size
174 int size() const
191 int size() const
175 {
192 {
176 QReadLocker locker{&m_Lock};
193 QReadLocker locker{&m_Lock};
177 return m_Data[0].size();
194 return m_Data[0].size();
178 }
195 }
179
196
180 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation)
197 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation)
181 {
198 {
182 QReadLocker locker{&m_Lock};
199 QReadLocker locker{&m_Lock};
183 return arraydata_detail::Sort<Dim>::sort(m_Data, sortPermutation);
200 return arraydata_detail::Sort<Dim>::sort(m_Data, sortPermutation);
184 }
201 }
185
202
186 void clear()
203 void clear()
187 {
204 {
188 QWriteLocker locker{&m_Lock};
205 QWriteLocker locker{&m_Lock};
189
206
190 auto nbComponents = m_Data.size();
207 auto nbComponents = m_Data.size();
191 for (auto i = 0; i < nbComponents; ++i) {
208 for (auto i = 0; i < nbComponents; ++i) {
192 m_Data[i].clear();
209 m_Data[i].clear();
193 }
210 }
194 }
211 }
195
212
196 private:
213 private:
197 DataContainer m_Data;
214 DataContainer m_Data;
198 mutable QReadWriteLock m_Lock;
215 mutable QReadWriteLock m_Lock;
199 };
216 };
200
217
201 #endif // SCIQLOP_ARRAYDATA_H
218 #endif // SCIQLOP_ARRAYDATA_H
General Comments 0
You need to be logged in to leave comments. Login now