##// END OF EJS Templates
Merge branch 'feature/MultidimArrayData' into develop
Alexandre Leroux -
r469:691002e2544c merge
parent child
Show More
@@ -1,39 +1,64
1 #ifndef SCIQLOP_SORTUTILS_H
1 #ifndef SCIQLOP_SORTUTILS_H
2 #define SCIQLOP_SORTUTILS_H
2 #define SCIQLOP_SORTUTILS_H
3
3
4 #include <algorithm>
4 #include <algorithm>
5 #include <numeric>
5 #include <numeric>
6 #include <vector>
6 #include <vector>
7
7
8 /**
8 /**
9 * Utility class with methods for sorting data
9 * Utility class with methods for sorting data
10 */
10 */
11 struct SortUtils {
11 struct SortUtils {
12 /**
12 /**
13 * Generates a vector representing the index of insertion of each data of a container if this
13 * Generates a vector representing the index of insertion of each data of a container if this
14 * one had to be sorted according to a comparison function.
14 * one had to be sorted according to a comparison function.
15 *
15 *
16 * For example:
16 * For example:
17 * If the container is a vector {1; 4; 2; 5; 3} and the comparison function is std::less, the
17 * If the container is a vector {1; 4; 2; 5; 3} and the comparison function is std::less, the
18 * result would be : {0; 3; 1; 4; 2}
18 * result would be : {0; 3; 1; 4; 2}
19 *
19 *
20 * @tparam Container the type of the container.
20 * @tparam Container the type of the container.
21 * @tparam Compare the type of the comparison function
21 * @tparam Compare the type of the comparison function
22 * @param container the container from which to generate the result. The container must have a
22 * @param container the container from which to generate the result. The container must have a
23 * at() method that returns a value associated to an index
23 * at() method that returns a value associated to an index
24 * @param compare the comparison function
24 * @param compare the comparison function
25 */
25 */
26 template <typename Container, typename Compare>
26 template <typename Container, typename Compare>
27 static std::vector<int> sortPermutation(const Container &container, const Compare &compare)
27 static std::vector<int> sortPermutation(const Container &container, const Compare &compare)
28 {
28 {
29 auto permutation = std::vector<int>{};
29 auto permutation = std::vector<int>{};
30 permutation.resize(container.size());
30 permutation.resize(container.size());
31
31
32 std::iota(permutation.begin(), permutation.end(), 0);
32 std::iota(permutation.begin(), permutation.end(), 0);
33 std::sort(permutation.begin(), permutation.end(),
33 std::sort(permutation.begin(), permutation.end(),
34 [&](int i, int j) { return compare(container.at(i), container.at(j)); });
34 [&](int i, int j) { return compare(container.at(i), container.at(j)); });
35 return permutation;
35 return permutation;
36 }
36 }
37
38 /**
39 * Sorts a container according to indices passed in parameter
40 * @param container the container sorted
41 * @param sortPermutation the indices used to sort the container
42 * @return the container sorted
43 * @warning no verification is made on validity of sortPermutation (i.e. the vector has unique
44 * indices and its range is [0 ; vector.size()[ )
45 */
46 template <typename Container>
47 static Container sort(const Container &container, const std::vector<int> &sortPermutation)
48 {
49 if (container.size() != sortPermutation.size()) {
50 return Container{};
51 }
52
53 // Inits result
54 auto sortedData = Container{};
55 sortedData.resize(container.size());
56
57 std::transform(sortPermutation.cbegin(), sortPermutation.cend(), sortedData.begin(),
58 [&container](int i) { return container.at(i); });
59
60 return sortedData;
61 }
37 };
62 };
38
63
39 #endif // SCIQLOP_SORTUTILS_H
64 #endif // SCIQLOP_SORTUTILS_H
@@ -1,169 +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>
5
4 #include <QReadLocker>
6 #include <QReadLocker>
5 #include <QReadWriteLock>
7 #include <QReadWriteLock>
6 #include <QVector>
8 #include <QVector>
7
9
8 #include <memory>
10 #include <memory>
9
11
12 template <int Dim>
13 class ArrayData;
14
15 using DataContainer = QVector<QVector<double> >;
16
17 namespace arraydata_detail {
18
19 /// Struct used to sort ArrayData
20 template <int Dim>
21 struct Sort {
22 static std::shared_ptr<ArrayData<Dim> > sort(const DataContainer &data,
23 const std::vector<int> &sortPermutation)
24 {
25 auto nbComponents = data.size();
26 auto sortedData = DataContainer(nbComponents);
27
28 for (auto i = 0; i < nbComponents; ++i) {
29 sortedData[i] = SortUtils::sort(data.at(i), sortPermutation);
30 }
31
32 return std::make_shared<ArrayData<Dim> >(std::move(sortedData));
33 }
34 };
35
36 /// Specialization for uni-dimensional ArrayData
37 template <>
38 struct Sort<1> {
39 static std::shared_ptr<ArrayData<1> > sort(const DataContainer &data,
40 const std::vector<int> &sortPermutation)
41 {
42 return std::make_shared<ArrayData<1> >(SortUtils::sort(data.at(0), sortPermutation));
43 }
44 };
45
46 } // namespace arraydata_detail
47
10 /**
48 /**
11 * @brief The ArrayData class represents a dataset for a data series.
49 * @brief The ArrayData class represents a dataset for a data series.
12 *
50 *
13 * 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
14 * template-parameter.
52 * template-parameter. In a case of a two-dimensional dataset, each dataset component has the same
53 * number of values
15 *
54 *
16 * @tparam Dim the dimension of the ArrayData (one or two)
55 * @tparam Dim the dimension of the ArrayData (one or two)
17 * @sa IDataSeries
56 * @sa IDataSeries
18 */
57 */
19 template <int Dim>
58 template <int Dim>
20 class ArrayData {
59 class ArrayData {
21 public:
60 public:
22 /**
61 // ///// //
23 * Ctor for a unidimensional ArrayData
62 // Ctors //
24 * @param nbColumns the number of values the ArrayData will hold
63 // ///// //
25 */
26 template <int D = Dim, typename = std::enable_if_t<D == 1> >
27 explicit ArrayData(int nbColumns) : m_Data{1, QVector<double>{}}
28 {
29 QWriteLocker locker{&m_Lock};
30 m_Data[0].resize(nbColumns);
31 }
32
64
33 /**
65 /**
34 * Ctor for a unidimensional ArrayData
66 * Ctor for a unidimensional ArrayData
35 * @param data the data the ArrayData will hold
67 * @param data the data the ArrayData will hold
36 */
68 */
37 template <int D = Dim, typename = std::enable_if_t<D == 1> >
69 template <int D = Dim, typename = std::enable_if_t<D == 1> >
38 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
70 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
39 {
71 {
40 QWriteLocker locker{&m_Lock};
41 m_Data[0] = std::move(data);
72 m_Data[0] = std::move(data);
42 }
73 }
43
74
44 /// Copy ctor
45 explicit ArrayData(const ArrayData &other)
46 {
47 QReadLocker otherLocker{&other.m_Lock};
48 QWriteLocker locker{&m_Lock};
49 m_Data = other.m_Data;
50 }
51
52 /**
75 /**
53 * @return the data at a specified index
76 * Ctor for a two-dimensional ArrayData. The number of components (number of vectors) must be
54 * @remarks index must be a valid position
77 * greater than 2 and each component must have the same number of values
55 * @remarks this method is only available for a unidimensional ArrayData
78 * @param data the data the ArrayData will hold
79 * @throws std::invalid_argument if the number of components is less than 2
80 * @remarks if the number of values is not the same for each component, no value is set
56 */
81 */
57 template <int D = Dim, typename = std::enable_if_t<D == 1> >
82 template <int D = Dim, typename = std::enable_if_t<D == 2> >
58 double at(int index) const noexcept
83 explicit ArrayData(DataContainer data)
59 {
84 {
60 QReadLocker locker{&m_Lock};
85 auto nbComponents = data.size();
61 return m_Data[0].at(index);
86 if (nbComponents < 2) {
62 }
87 throw std::invalid_argument{
88 QString{"A multidimensional ArrayData must have at least 2 components (found: %1"}
89 .arg(data.size())
90 .toStdString()};
91 }
63
92
64 /**
93 auto nbValues = data.front().size();
65 * Sets a data at a specified index. The index has to be valid to be effective
94 if (std::all_of(data.cbegin(), data.cend(), [nbValues](const auto &component) {
66 * @param index the index to which the data will be set
95 return component.size() == nbValues;
67 * @param data the data to set
96 })) {
68 * @remarks this method is only available for a unidimensional ArrayData
97 m_Data = std::move(data);
69 */
98 }
70 template <int D = Dim, typename = std::enable_if_t<D == 1> >
99 else {
71 void setData(int index, double data) noexcept
100 m_Data = DataContainer{nbComponents, QVector<double>{}};
72 {
73 QWriteLocker locker{&m_Lock};
74 if (index >= 0 && index < m_Data.at(0).size()) {
75 m_Data[0].replace(index, data);
76 }
101 }
77 }
102 }
78
103
79 /**
104 /// Copy ctor
80 * @return the data as a vector
105 explicit ArrayData(const ArrayData &other)
81 * @remarks this method is only available for a unidimensional ArrayData
82 */
83 template <int D = Dim, typename = std::enable_if_t<D == 1> >
84 QVector<double> data() const noexcept
85 {
106 {
86 QReadLocker locker{&m_Lock};
107 QReadLocker otherLocker{&other.m_Lock};
87 return m_Data[0];
108 m_Data = other.m_Data;
88 }
109 }
89
110
90 /**
111 // /////////////// //
91 * @return the data as a vector, as a const reference
112 // General methods //
92 * @remarks this method is only available for a unidimensional ArrayData
113 // /////////////// //
93 */
94 template <int D = Dim, typename = std::enable_if_t<D == 1> >
95 const QVector<double> &cdata() const noexcept
96 {
97 QReadLocker locker{&m_Lock};
98 return m_Data.at(0);
99 }
100
114
101 /**
115 /**
102 * Merges into the array data an other array data
116 * Merges into the array data an other array data. The two array datas must have the same number
117 * of components so the merge can be done
103 * @param other the array data to merge with
118 * @param other the array data to merge with
104 * @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
105 * inserted at the end
120 * inserted at the end
106 * @remarks this method is only available for a unidimensional ArrayData
107 */
121 */
108 template <int D = Dim, typename = std::enable_if_t<D == 1> >
122 void add(const ArrayData<Dim> &other, bool prepend = false)
109 void add(const ArrayData<1> &other, bool prepend = false)
110 {
123 {
111 QWriteLocker locker{&m_Lock};
124 QWriteLocker locker{&m_Lock};
112 if (!m_Data.empty()) {
125 QReadLocker otherLocker{&other.m_Lock};
113 QReadLocker otherLocker{&other.m_Lock};
126
127 auto nbComponents = m_Data.size();
128 if (nbComponents != other.m_Data.size()) {
129 return;
130 }
114
131
132 for (auto componentIndex = 0; componentIndex < nbComponents; ++componentIndex) {
115 if (prepend) {
133 if (prepend) {
116 const auto &otherData = other.data();
134 const auto &otherData = other.data(componentIndex);
117 const auto otherDataSize = otherData.size();
135 const auto otherDataSize = otherData.size();
118
136
119 auto &data = m_Data[0];
137 auto &data = m_Data[componentIndex];
120 data.insert(data.begin(), otherDataSize, 0.);
138 data.insert(data.begin(), otherDataSize, 0.);
121
139
122 for (auto i = 0; i < otherDataSize; ++i) {
140 for (auto i = 0; i < otherDataSize; ++i) {
123 data.replace(i, otherData.at(i));
141 data.replace(i, otherData.at(i));
124 }
142 }
125 }
143 }
126 else {
144 else {
127 m_Data[0] += other.data();
145 m_Data[componentIndex] += other.data(componentIndex);
128 }
146 }
129 }
147 }
130 }
148 }
131
149
132 template <int D = Dim, typename = std::enable_if_t<D == 1> >
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
173 /// @return the size (i.e. number of values) of a single component
174 /// @remarks in a case of a two-dimensional ArrayData, each component has the same size
133 int size() const
175 int size() const
134 {
176 {
135 QReadLocker locker{&m_Lock};
177 QReadLocker locker{&m_Lock};
136 return m_Data[0].size();
178 return m_Data[0].size();
137 }
179 }
138
180
139 template <int D = Dim, typename = std::enable_if_t<D == 1> >
181 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation)
140 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> sortPermutation)
141 {
182 {
142 QReadLocker locker{&m_Lock};
183 QReadLocker locker{&m_Lock};
184 return arraydata_detail::Sort<Dim>::sort(m_Data, sortPermutation);
185 }
143
186
144 const auto &data = m_Data.at(0);
187 // ///////////// //
145
188 // 1-dim methods //
146 // Inits result
189 // ///////////// //
147 auto sortedData = QVector<double>{};
148 sortedData.resize(data.size());
149
150 std::transform(sortPermutation.cbegin(), sortPermutation.cend(), sortedData.begin(),
151 [&data](int i) { return data[i]; });
152
190
153 return std::make_shared<ArrayData<Dim> >(std::move(sortedData));
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
198 {
199 QReadLocker locker{&m_Lock};
200 return m_Data[0].at(index);
154 }
201 }
155
202
203 /**
204 * @return the data as a vector, as a const reference
205 * @remarks this method is only available for a unidimensional ArrayData
206 */
156 template <int D = Dim, typename = std::enable_if_t<D == 1> >
207 template <int D = Dim, typename = std::enable_if_t<D == 1> >
157 void clear()
208 const QVector<double> &cdata() const noexcept
158 {
209 {
159 QWriteLocker locker{&m_Lock};
210 QReadLocker locker{&m_Lock};
160 m_Data[0].clear();
211 return m_Data.at(0);
161 }
212 }
162
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];
223 }
163
224
164 private:
225 private:
165 QVector<QVector<double> > m_Data;
226 DataContainer m_Data;
166 mutable QReadWriteLock m_Lock;
227 mutable QReadWriteLock m_Lock;
167 };
228 };
168
229
169 #endif // SCIQLOP_ARRAYDATA_H
230 #endif // SCIQLOP_ARRAYDATA_H
@@ -1,17 +1,18
1 # On ignore toutes les règles vera++ pour le fichier spimpl
1 # On ignore toutes les règles vera++ pour le fichier spimpl
2 Common/spimpl\.h:\d+:.*
2 Common/spimpl\.h:\d+:.*
3
3
4 # Ignore false positive relative to two class definitions in a same file
4 # Ignore false positive relative to two class definitions in a same file
5 DataSourceItem\.h:\d+:.*IPSIS_S01.*
5 DataSourceItem\.h:\d+:.*IPSIS_S01.*
6
6
7 # Ignore false positive relative to a template class
7 # Ignore false positive relative to a template class
8 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (D)
8 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (D)
9 ArrayData\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (arraydata_detail)
9 ArrayData\.h:\d+:.*IPSIS_S06.*found: (D)
10 ArrayData\.h:\d+:.*IPSIS_S06.*found: (D)
10 ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim)
11 ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim)
11 DataSeries\.h:\d+:.*IPSIS_S04_VARIABLE.*
12 DataSeries\.h:\d+:.*IPSIS_S04_VARIABLE.*
12
13
13 # Ignore false positive relative to an alias
14 # Ignore false positive relative to an alias
14 DataSourceItemAction\.h:\d+:.*IPSIS_S06.*found: (ExecuteFunction)
15 DataSourceItemAction\.h:\d+:.*IPSIS_S06.*found: (ExecuteFunction)
15
16
16 # Ignore false positive relative to unnamed namespace
17 # Ignore false positive relative to unnamed namespace
17 VariableController\.cpp:\d+:.*IPSIS_F13.*
18 VariableController\.cpp:\d+:.*IPSIS_F13.*
General Comments 0
You need to be logged in to leave comments. Login now