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