##// END OF EJS Templates
Adapts sort() method to 2-dim array data (2)...
Alexandre Leroux -
r505:c4a0c9f4308e
parent child
Show More
@@ -1,166 +1,201
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>
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
12 /**
48 /**
13 * @brief The ArrayData class represents a dataset for a data series.
49 * @brief The ArrayData class represents a dataset for a data series.
14 *
50 *
15 * 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
16 * 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
17 * number of values
53 * number of values
18 *
54 *
19 * @tparam Dim the dimension of the ArrayData (one or two)
55 * @tparam Dim the dimension of the ArrayData (one or two)
20 * @sa IDataSeries
56 * @sa IDataSeries
21 */
57 */
22 template <int Dim>
58 template <int Dim>
23 class ArrayData {
59 class ArrayData {
24 public:
60 public:
25 /**
61 /**
26 * Ctor for a unidimensional ArrayData
62 * Ctor for a unidimensional ArrayData
27 * @param data the data the ArrayData will hold
63 * @param data the data the ArrayData will hold
28 */
64 */
29 template <int D = Dim, typename = std::enable_if_t<D == 1> >
65 template <int D = Dim, typename = std::enable_if_t<D == 1> >
30 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
66 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
31 {
67 {
32 m_Data[0] = std::move(data);
68 m_Data[0] = std::move(data);
33 }
69 }
34
70
35 /**
71 /**
36 * 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
37 * 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
38 * @param data the data the ArrayData will hold
74 * @param data the data the ArrayData will hold
39 * @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
40 * @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
41 */
77 */
42 template <int D = Dim, typename = std::enable_if_t<D == 2> >
78 template <int D = Dim, typename = std::enable_if_t<D == 2> >
43 explicit ArrayData(QVector<QVector<double> > data)
79 explicit ArrayData(DataContainer data)
44 {
80 {
45 auto nbComponents = data.size();
81 auto nbComponents = data.size();
46 if (nbComponents < 2) {
82 if (nbComponents < 2) {
47 throw std::invalid_argument{
83 throw std::invalid_argument{
48 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"}
49 .arg(data.size())
85 .arg(data.size())
50 .toStdString()};
86 .toStdString()};
51 }
87 }
52
88
53 auto nbValues = data.front().size();
89 auto nbValues = data.front().size();
54 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) {
55 return component.size() == nbValues;
91 return component.size() == nbValues;
56 })) {
92 })) {
57 m_Data = std::move(data);
93 m_Data = std::move(data);
58 }
94 }
59 else {
95 else {
60 m_Data = QVector<QVector<double> >{nbComponents, QVector<double>{}};
96 m_Data = DataContainer{nbComponents, QVector<double>{}};
61 }
97 }
62 }
98 }
63
99
64 /// Copy ctor
100 /// Copy ctor
65 explicit ArrayData(const ArrayData &other)
101 explicit ArrayData(const ArrayData &other)
66 {
102 {
67 QReadLocker otherLocker{&other.m_Lock};
103 QReadLocker otherLocker{&other.m_Lock};
68 m_Data = other.m_Data;
104 m_Data = other.m_Data;
69 }
105 }
70
106
71 /**
107 /**
72 * @return the data at a specified index
108 * @return the data at a specified index
73 * @remarks index must be a valid position
109 * @remarks index must be a valid position
74 * @remarks this method is only available for a unidimensional ArrayData
110 * @remarks this method is only available for a unidimensional ArrayData
75 */
111 */
76 template <int D = Dim, typename = std::enable_if_t<D == 1> >
112 template <int D = Dim, typename = std::enable_if_t<D == 1> >
77 double at(int index) const noexcept
113 double at(int index) const noexcept
78 {
114 {
79 QReadLocker locker{&m_Lock};
115 QReadLocker locker{&m_Lock};
80 return m_Data[0].at(index);
116 return m_Data[0].at(index);
81 }
117 }
82
118
83 /**
119 /**
84 * @return the data as a vector
120 * @return the data as a vector
85 * @remarks this method is only available for a unidimensional ArrayData
121 * @remarks this method is only available for a unidimensional ArrayData
86 */
122 */
87 template <int D = Dim, typename = std::enable_if_t<D == 1> >
123 template <int D = Dim, typename = std::enable_if_t<D == 1> >
88 QVector<double> data() const noexcept
124 QVector<double> data() const noexcept
89 {
125 {
90 QReadLocker locker{&m_Lock};
126 QReadLocker locker{&m_Lock};
91 return m_Data[0];
127 return m_Data[0];
92 }
128 }
93
129
94 /**
130 /**
95 * @return the data as a vector, as a const reference
131 * @return the data as a vector, as a const reference
96 * @remarks this method is only available for a unidimensional ArrayData
132 * @remarks this method is only available for a unidimensional ArrayData
97 */
133 */
98 template <int D = Dim, typename = std::enable_if_t<D == 1> >
134 template <int D = Dim, typename = std::enable_if_t<D == 1> >
99 const QVector<double> &cdata() const noexcept
135 const QVector<double> &cdata() const noexcept
100 {
136 {
101 QReadLocker locker{&m_Lock};
137 QReadLocker locker{&m_Lock};
102 return m_Data.at(0);
138 return m_Data.at(0);
103 }
139 }
104
140
105 /**
141 /**
106 * Merges into the array data an other array data
142 * Merges into the array data an other array data
107 * @param other the array data to merge with
143 * @param other the array data to merge with
108 * @param prepend if true, the other array data is inserted at the beginning, otherwise it is
144 * @param prepend if true, the other array data is inserted at the beginning, otherwise it is
109 * inserted at the end
145 * inserted at the end
110 * @remarks this method is only available for a unidimensional ArrayData
146 * @remarks this method is only available for a unidimensional ArrayData
111 */
147 */
112 template <int D = Dim, typename = std::enable_if_t<D == 1> >
148 template <int D = Dim, typename = std::enable_if_t<D == 1> >
113 void add(const ArrayData<1> &other, bool prepend = false)
149 void add(const ArrayData<1> &other, bool prepend = false)
114 {
150 {
115 QWriteLocker locker{&m_Lock};
151 QWriteLocker locker{&m_Lock};
116 if (!m_Data.empty()) {
152 if (!m_Data.empty()) {
117 QReadLocker otherLocker{&other.m_Lock};
153 QReadLocker otherLocker{&other.m_Lock};
118
154
119 if (prepend) {
155 if (prepend) {
120 const auto &otherData = other.data();
156 const auto &otherData = other.data();
121 const auto otherDataSize = otherData.size();
157 const auto otherDataSize = otherData.size();
122
158
123 auto &data = m_Data[0];
159 auto &data = m_Data[0];
124 data.insert(data.begin(), otherDataSize, 0.);
160 data.insert(data.begin(), otherDataSize, 0.);
125
161
126 for (auto i = 0; i < otherDataSize; ++i) {
162 for (auto i = 0; i < otherDataSize; ++i) {
127 data.replace(i, otherData.at(i));
163 data.replace(i, otherData.at(i));
128 }
164 }
129 }
165 }
130 else {
166 else {
131 m_Data[0] += other.data();
167 m_Data[0] += other.data();
132 }
168 }
133 }
169 }
134 }
170 }
135
171
136 /// @return the size (i.e. number of values) of a single component
172 /// @return the size (i.e. number of values) of a single component
137 /// @remarks in a case of a two-dimensional ArrayData, each component has the same size
173 /// @remarks in a case of a two-dimensional ArrayData, each component has the same size
138 int size() const
174 int size() const
139 {
175 {
140 QReadLocker locker{&m_Lock};
176 QReadLocker locker{&m_Lock};
141 return m_Data[0].size();
177 return m_Data[0].size();
142 }
178 }
143
179
144 template <int D = Dim, typename = std::enable_if_t<D == 1> >
145 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation)
180 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation)
146 {
181 {
147 QReadLocker locker{&m_Lock};
182 QReadLocker locker{&m_Lock};
148 return std::make_shared<ArrayData<Dim> >(SortUtils::sort(m_Data.at(0), sortPermutation));
183 return arraydata_detail::Sort<Dim>::sort(m_Data, sortPermutation);
149 }
184 }
150
185
151 void clear()
186 void clear()
152 {
187 {
153 QWriteLocker locker{&m_Lock};
188 QWriteLocker locker{&m_Lock};
154
189
155 auto nbComponents = m_Data.size();
190 auto nbComponents = m_Data.size();
156 for (auto i = 0; i < nbComponents; ++i) {
191 for (auto i = 0; i < nbComponents; ++i) {
157 m_Data[i].clear();
192 m_Data[i].clear();
158 }
193 }
159 }
194 }
160
195
161 private:
196 private:
162 QVector<QVector<double> > m_Data;
197 DataContainer m_Data;
163 mutable QReadWriteLock m_Lock;
198 mutable QReadWriteLock m_Lock;
164 };
199 };
165
200
166 #endif // SCIQLOP_ARRAYDATA_H
201 #endif // SCIQLOP_ARRAYDATA_H
General Comments 0
You need to be logged in to leave comments. Login now