##// END OF EJS Templates
Makes a Data series be sorted (2)...
Alexandre Leroux -
r450:07e656efd83c
parent child
Show More
@@ -0,0 +1,38
1 #ifndef SCIQLOP_SORTUTILS_H
2 #define SCIQLOP_SORTUTILS_H
3
4 #include <algorithm>
5 #include <vector>
6
7 /**
8 * Utility class with methods for sorting data
9 */
10 struct SortUtils {
11 /**
12 * Generates a vector representing the index of insertion of each data of a container if this
13 * one had to be sorted according to a comparison function.
14 *
15 * For example:
16 * If the container is a vector {1; 4; 2; 5; 3} and the comparison function is std::less, the
17 * result would be : {0; 3; 1; 4; 2}
18 *
19 * @tparam Container the type of the container.
20 * @tparam Compare the type of the comparison function
21 * @param container the container from which to generate the result. The container must have a
22 * at() method that returns a value associated to an index
23 * @param compare the comparison function
24 */
25 template <typename Container, typename Compare>
26 static std::vector<int> sortPermutation(const Container &container, const Compare &compare)
27 {
28 auto permutation = std::vector<int>{};
29 permutation.resize(container.size());
30
31 std::iota(permutation.begin(), permutation.end(), 0);
32 std::sort(permutation.begin(), permutation.end(),
33 [&](int i, int j) { return compare(container.at(i), container.at(j)); });
34 return permutation;
35 }
36 };
37
38 #endif // SCIQLOP_SORTUTILS_H
@@ -1,116 +1,147
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
8 #include <memory>
9
7 10 /**
8 11 * @brief The ArrayData class represents a dataset for a data series.
9 12 *
10 13 * A dataset can be unidimensional or two-dimensional. This property is determined by the Dim
11 14 * template-parameter.
12 15 *
13 16 * @tparam Dim the dimension of the ArrayData (one or two)
14 17 * @sa IDataSeries
15 18 */
16 19 template <int Dim>
17 20 class ArrayData {
18 21 public:
19 22 /**
20 23 * Ctor for a unidimensional ArrayData
21 24 * @param nbColumns the number of values the ArrayData will hold
22 25 */
23 26 template <int D = Dim, typename = std::enable_if_t<D == 1> >
24 27 explicit ArrayData(int nbColumns) : m_Data{1, QVector<double>{}}
25 28 {
26 29 QWriteLocker locker{&m_Lock};
27 30 m_Data[0].resize(nbColumns);
28 31 }
29 32
30 33 /**
31 34 * Ctor for a unidimensional ArrayData
32 35 * @param data the data the ArrayData will hold
33 36 */
34 37 template <int D = Dim, typename = std::enable_if_t<D == 1> >
35 38 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
36 39 {
37 40 QWriteLocker locker{&m_Lock};
38 41 m_Data[0] = std::move(data);
39 42 }
40 43
41 44 /// Copy ctor
42 45 explicit ArrayData(const ArrayData &other)
43 46 {
44 47 QReadLocker otherLocker{&other.m_Lock};
45 48 QWriteLocker locker{&m_Lock};
46 49 m_Data = other.m_Data;
47 50 }
48 51
49 52 /**
53 * @return the data at a specified index
54 * @remarks index must be a valid position
55 * @remarks this method is only available for a unidimensional ArrayData
56 */
57 template <int D = Dim, typename = std::enable_if_t<D == 1> >
58 double at(int index) const noexcept
59 {
60 QReadLocker locker{&m_Lock};
61 return m_Data[0].at(index);
62 }
63
64 /**
50 65 * Sets a data at a specified index. The index has to be valid to be effective
51 66 * @param index the index to which the data will be set
52 67 * @param data the data to set
53 68 * @remarks this method is only available for a unidimensional ArrayData
54 69 */
55 70 template <int D = Dim, typename = std::enable_if_t<D == 1> >
56 71 void setData(int index, double data) noexcept
57 72 {
58 73 QWriteLocker locker{&m_Lock};
59 74 if (index >= 0 && index < m_Data.at(0).size()) {
60 75 m_Data[0].replace(index, data);
61 76 }
62 77 }
63 78
64 79 /**
65 80 * @return the data as a vector
66 81 * @remarks this method is only available for a unidimensional ArrayData
67 82 */
68 83 template <int D = Dim, typename = std::enable_if_t<D == 1> >
69 84 QVector<double> data() const noexcept
70 85 {
71 86 QReadLocker locker{&m_Lock};
72 87 return m_Data[0];
73 88 }
74 89
75 90 /**
76 91 * @return the data as a vector, as a const reference
77 92 * @remarks this method is only available for a unidimensional ArrayData
78 93 */
79 94 template <int D = Dim, typename = std::enable_if_t<D == 1> >
80 95 const QVector<double> &cdata() const noexcept
81 96 {
82 97 QReadLocker locker{&m_Lock};
83 98 return m_Data.at(0);
84 99 }
85 100
86 101 // TODO Comment
87 102 template <int D = Dim, typename = std::enable_if_t<D == 1> >
88 103 void merge(const ArrayData<1> &arrayData)
89 104 {
90 105 QWriteLocker locker{&m_Lock};
91 106 if (!m_Data.empty()) {
92 107 QReadLocker otherLocker{&arrayData.m_Lock};
93 108 m_Data[0] += arrayData.data();
94 109 }
95 110 }
96 111
97 112 template <int D = Dim, typename = std::enable_if_t<D == 1> >
98 113 int size() const
99 114 {
100 115 QReadLocker locker{&m_Lock};
101 116 return m_Data[0].size();
102 117 }
103 118
119 template <int D = Dim, typename = std::enable_if_t<D == 1> >
120 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> sortPermutation)
121 {
122 QReadLocker locker{&m_Lock};
123
124 const auto &data = m_Data.at(0);
125
126 // Inits result
127 auto sortedData = QVector<double>{};
128 sortedData.resize(data.size());
129
130 std::transform(sortPermutation.cbegin(), sortPermutation.cend(), sortedData.begin(),
131 [&data](int i) { return data[i]; });
132
133 return std::make_shared<ArrayData<Dim> >(std::move(sortedData));
134 }
104 135 void clear()
105 136 {
106 137 QWriteLocker locker{&m_Lock};
107 138 m_Data.clear();
108 139 }
109 140
110 141
111 142 private:
112 143 QVector<QVector<double> > m_Data;
113 144 mutable QReadWriteLock m_Lock;
114 145 };
115 146
116 147 #endif // SCIQLOP_ARRAYDATA_H
@@ -1,130 +1,134
1 1 #ifndef SCIQLOP_DATASERIES_H
2 2 #define SCIQLOP_DATASERIES_H
3 3
4 #include <Common/SortUtils.h>
5
4 6 #include <Data/ArrayData.h>
5 7 #include <Data/IDataSeries.h>
6 8
7 9 #include <QLoggingCategory>
8 10
9 11 #include <QReadLocker>
10 12 #include <QReadWriteLock>
11 13 #include <memory>
12 14
13 15 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeries)
14 16 Q_LOGGING_CATEGORY(LOG_DataSeries, "DataSeries")
15 17
16 18
17 19 /**
18 20 * @brief The DataSeries class is the base (abstract) implementation of IDataSeries.
19 21 *
20 22 * It proposes to set a dimension for the values ​​data.
21 23 *
22 24 * A DataSeries is always sorted on its x-axis data.
23 25 *
24 26 * @tparam Dim The dimension of the values data
25 27 *
26 28 */
27 29 template <int Dim>
28 30 class DataSeries : public IDataSeries {
29 31 public:
30 32 /// @sa IDataSeries::xAxisData()
31 33 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
32 34 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
33 35
34 36 /// @sa IDataSeries::xAxisUnit()
35 37 Unit xAxisUnit() const override { return m_XAxisUnit; }
36 38
37 39 /// @return the values dataset
38 40 std::shared_ptr<ArrayData<Dim> > valuesData() { return m_ValuesData; }
39 41 const std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; }
40 42
41 43 /// @sa IDataSeries::valuesUnit()
42 44 Unit valuesUnit() const override { return m_ValuesUnit; }
43 45
44 46 void clear()
45 47 {
46 48 m_XAxisData->clear();
47 49 m_ValuesData->clear();
48 50 }
49 51
50 52 /// @sa IDataSeries::merge()
51 53 void merge(IDataSeries *dataSeries) override
52 54 {
53 55 if (auto dimDataSeries = dynamic_cast<DataSeries<Dim> *>(dataSeries)) {
54 56 m_XAxisData->merge(*dimDataSeries->xAxisData());
55 57 m_ValuesData->merge(*dimDataSeries->valuesData());
56 58 dimDataSeries->clear();
57 59 }
58 60 else {
59 61 qCWarning(LOG_DataSeries())
60 62 << QObject::tr("Dection of a type of IDataSeries we cannot merge with !");
61 63 }
62 64 }
63 65
64 66 virtual void lockRead() { m_Lock.lockForRead(); }
65 67 virtual void lockWrite() { m_Lock.lockForWrite(); }
66 68 virtual void unlock() { m_Lock.unlock(); }
67 69
68 70 protected:
69 71 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
70 72 /// DataSeries with no values will be created.
71 73 /// @remarks data series is automatically sorted on its x-axis data
72 74 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit,
73 75 std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit)
74 76 : m_XAxisData{xAxisData},
75 77 m_XAxisUnit{xAxisUnit},
76 78 m_ValuesData{valuesData},
77 79 m_ValuesUnit{valuesUnit}
78 80 {
79 81 if (m_XAxisData->size() != m_ValuesData->size()) {
80 82 clear();
81 83 }
82 84
83 85 // Sorts data if it's not the case
84 86 const auto &xAxisCData = m_XAxisData->cdata();
85 87 if (!std::is_sorted(xAxisCData.cbegin(), xAxisCData.cend())) {
86 88 sort();
87 89 }
88 90 }
89 91
90 92 /// Copy ctor
91 93 explicit DataSeries(const DataSeries<Dim> &other)
92 94 : m_XAxisData{std::make_shared<ArrayData<1> >(*other.m_XAxisData)},
93 95 m_XAxisUnit{other.m_XAxisUnit},
94 96 m_ValuesData{std::make_shared<ArrayData<Dim> >(*other.m_ValuesData)},
95 97 m_ValuesUnit{other.m_ValuesUnit}
96 98 {
97 99 // Since a series is ordered from its construction and is always ordered, it is not
98 100 // necessary to call the sort method here ('other' is sorted)
99 101 }
100 102
101 103 /// Assignment operator
102 104 template <int D>
103 105 DataSeries &operator=(DataSeries<D> other)
104 106 {
105 107 std::swap(m_XAxisData, other.m_XAxisData);
106 108 std::swap(m_XAxisUnit, other.m_XAxisUnit);
107 109 std::swap(m_ValuesData, other.m_ValuesData);
108 110 std::swap(m_ValuesUnit, other.m_ValuesUnit);
109 111
110 112 return *this;
111 113 }
112 114
113 115 private:
114 116 /**
115 117 * Sorts data series on its x-axis data
116 118 */
117 119 void sort() noexcept
118 120 {
119 /// @todo ALX
121 auto permutation = SortUtils::sortPermutation(*m_XAxisData, std::less<double>());
122 m_XAxisData = m_XAxisData->sort(permutation);
123 m_ValuesData = m_ValuesData->sort(permutation);
120 124 }
121 125
122 126 std::shared_ptr<ArrayData<1> > m_XAxisData;
123 127 Unit m_XAxisUnit;
124 128 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
125 129 Unit m_ValuesUnit;
126 130
127 131 QReadWriteLock m_Lock;
128 132 };
129 133
130 134 #endif // SCIQLOP_DATASERIES_H
General Comments 0
You need to be logged in to leave comments. Login now