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