##// END OF EJS Templates
Initializes spectrogram management in the plugin...
Alexandre Leroux -
r895:244a7d7caff1
parent child
Show More
@@ -1,228 +1,263
1 1 #include "CosinusProvider.h"
2 2 #include "MockDefs.h"
3 3
4 4 #include <Data/DataProviderParameters.h>
5 5 #include <Data/ScalarSeries.h>
6 #include <Data/SpectrogramSeries.h>
6 7 #include <Data/VectorSeries.h>
7 8
8 9 #include <cmath>
9 10
10 11 #include <QFuture>
11 12 #include <QThread>
12 13 #include <QtConcurrent/QtConcurrent>
13 14
14 15 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
15 16
16 17 namespace {
17 18
19 /// Number of bands generated for a spectrogram
20 const auto SPECTROGRAM_NUMBER_BANDS = 30;
21
18 22 /// Abstract cosinus type
19 23 struct ICosinusType {
20 24 virtual ~ICosinusType() = default;
21 25 /// @return the number of components generated for the type
22 26 virtual int componentCount() const = 0;
23 27 /// @return the data series created for the type
24 28 virtual std::shared_ptr<IDataSeries> createDataSeries(std::vector<double> xAxisData,
25 29 std::vector<double> valuesData,
26 30 Unit xAxisUnit,
27 31 Unit valuesUnit) const = 0;
28 32 /// Generates values (one value per component)
29 33 /// @param x the x-axis data used to generate values
30 34 /// @param values the vector in which to insert the generated values
31 35 /// @param dataIndex the index of insertion of the generated values
32 36 ///
33 37 virtual void generateValues(double x, std::vector<double> &values, int dataIndex) const = 0;
34 38 };
35 39
36 40 struct ScalarCosinus : public ICosinusType {
37 41 int componentCount() const override { return 1; }
38 42
39 43 std::shared_ptr<IDataSeries> createDataSeries(std::vector<double> xAxisData,
40 44 std::vector<double> valuesData, Unit xAxisUnit,
41 45 Unit valuesUnit) const override
42 46 {
43 47 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
44 48 xAxisUnit, valuesUnit);
45 49 }
46 50
47 51 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
48 52 {
49 53 values[dataIndex] = std::cos(x);
50 54 }
51 55 };
56
57 struct SpectrogramCosinus : public ICosinusType {
58 /// Ctor with y-axis
59 explicit SpectrogramCosinus(std::vector<double> yAxisData, Unit yAxisUnit)
60 : m_YAxisData{std::move(yAxisData)}, m_YAxisUnit{std::move(yAxisUnit)}
61 {
62 }
63
64 int componentCount() const override { return m_YAxisData.size(); }
65
66 std::shared_ptr<IDataSeries> createDataSeries(std::vector<double> xAxisData,
67 std::vector<double> valuesData, Unit xAxisUnit,
68 Unit valuesUnit) const override
69 {
70 }
71
72 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
73 {
74 }
75
76 std::vector<double> m_YAxisData;
77 Unit m_YAxisUnit;
78 };
79
52 80 struct VectorCosinus : public ICosinusType {
53 81 int componentCount() const override { return 3; }
54 82
55 83 std::shared_ptr<IDataSeries> createDataSeries(std::vector<double> xAxisData,
56 84 std::vector<double> valuesData, Unit xAxisUnit,
57 85 Unit valuesUnit) const override
58 86 {
59 87 return std::make_shared<VectorSeries>(std::move(xAxisData), std::move(valuesData),
60 88 xAxisUnit, valuesUnit);
61 89 }
62 90
63 91 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
64 92 {
65 93 // Generates value for each component: cos(x), cos(x)/2, cos(x)/3
66 94 auto xValue = std::cos(x);
67 95 auto componentCount = this->componentCount();
68 96 for (auto i = 0; i < componentCount; ++i) {
69 97 values[componentCount * dataIndex + i] = xValue / (i + 1);
70 98 }
71 99 }
72 100 };
73 101
74 102 /// Converts string to cosinus type
75 103 /// @return the cosinus type if the string could be converted, nullptr otherwise
76 104 std::unique_ptr<ICosinusType> cosinusType(const QString &type) noexcept
77 105 {
78 106 if (type.compare(QStringLiteral("scalar"), Qt::CaseInsensitive) == 0) {
79 107 return std::make_unique<ScalarCosinus>();
80 108 }
109 else if (type.compare(QStringLiteral("spectrogram"), Qt::CaseInsensitive) == 0) {
110 // Generates default y-axis data for spectrogram [0., 1., 2., ...]
111 std::vector<double> yAxisData(SPECTROGRAM_NUMBER_BANDS);
112 std::iota(yAxisData.begin(), yAxisData.end(), 0.);
113
114 return std::make_unique<SpectrogramCosinus>(std::move(yAxisData), Unit{"eV"});
115 }
81 116 else if (type.compare(QStringLiteral("vector"), Qt::CaseInsensitive) == 0) {
82 117 return std::make_unique<VectorCosinus>();
83 118 }
84 119 else {
85 120 return nullptr;
86 121 }
87 122 }
88 123
89 124 } // namespace
90 125
91 126 std::shared_ptr<IDataProvider> CosinusProvider::clone() const
92 127 {
93 128 // No copy is made in clone
94 129 return std::make_shared<CosinusProvider>();
95 130 }
96 131
97 132 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
98 133 const SqpRange &dataRangeRequested,
99 134 const QVariantHash &data)
100 135 {
101 136 // TODO: Add Mutex
102 137 auto dataIndex = 0;
103 138
104 139 // Retrieves cosinus type
105 140 auto typeVariant = data.value(COSINUS_TYPE_KEY, COSINUS_TYPE_DEFAULT_VALUE);
106 141 if (!typeVariant.canConvert<QString>()) {
107 142 qCCritical(LOG_CosinusProvider()) << tr("Can't retrieve data: invalid type");
108 143 return nullptr;
109 144 }
110 145
111 146 auto type = cosinusType(typeVariant.toString());
112 147 if (!type) {
113 148 qCCritical(LOG_CosinusProvider()) << tr("Can't retrieve data: unknown type");
114 149 return nullptr;
115 150 }
116 151
117 152 // Retrieves frequency
118 153 auto freqVariant = data.value(COSINUS_FREQUENCY_KEY, COSINUS_FREQUENCY_DEFAULT_VALUE);
119 154 if (!freqVariant.canConvert<double>()) {
120 155 qCCritical(LOG_CosinusProvider()) << tr("Can't retrieve data: invalid frequency");
121 156 return nullptr;
122 157 }
123 158
124 159 // Gets the timerange from the parameters
125 160 double freq = freqVariant.toDouble();
126 161 double start = std::ceil(dataRangeRequested.m_TStart * freq);
127 162 double end = std::floor(dataRangeRequested.m_TEnd * freq);
128 163
129 164 // We assure that timerange is valid
130 165 if (end < start) {
131 166 std::swap(start, end);
132 167 }
133 168
134 169 // Generates scalar series containing cosinus values (one value per second, end value is
135 170 // included)
136 171 auto dataCount = end - start + 1;
137 172
138 173 // Number of components (depending on the cosinus type)
139 174 auto componentCount = type->componentCount();
140 175
141 176 auto xAxisData = std::vector<double>{};
142 177 xAxisData.resize(dataCount);
143 178
144 179 auto valuesData = std::vector<double>{};
145 180 valuesData.resize(dataCount * componentCount);
146 181
147 182 int progress = 0;
148 183 auto progressEnd = dataCount;
149 184 for (auto time = start; time <= end; ++time, ++dataIndex) {
150 185 auto it = m_VariableToEnableProvider.find(acqIdentifier);
151 186 if (it != m_VariableToEnableProvider.end() && it.value()) {
152 187 const auto x = time / freq;
153 188
154 189 xAxisData[dataIndex] = x;
155 190
156 191 // Generates values (depending on the type)
157 192 type->generateValues(x, valuesData, dataIndex);
158 193
159 194 // progression
160 195 int currentProgress = (time - start) * 100.0 / progressEnd;
161 196 if (currentProgress != progress) {
162 197 progress = currentProgress;
163 198
164 199 emit dataProvidedProgress(acqIdentifier, progress);
165 200 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::retrieveData"
166 201 << QThread::currentThread()->objectName()
167 202 << progress;
168 203 // NOTE: Try to use multithread if possible
169 204 }
170 205 }
171 206 else {
172 207 if (!it.value()) {
173 208 qCDebug(LOG_CosinusProvider())
174 209 << "CosinusProvider::retrieveData: ARRET De l'acquisition detectΓ©"
175 210 << end - time;
176 211 }
177 212 }
178 213 }
179 214 if (progress != 100) {
180 215 // We can close progression beacause all data has been retrieved
181 216 emit dataProvidedProgress(acqIdentifier, 100);
182 217 }
183 218 return type->createDataSeries(std::move(xAxisData), std::move(valuesData),
184 219 Unit{QStringLiteral("t"), true}, Unit{});
185 220 }
186 221
187 222 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
188 223 const DataProviderParameters &parameters)
189 224 {
190 225 // TODO: Add Mutex
191 226 m_VariableToEnableProvider[acqIdentifier] = true;
192 227 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::requestDataLoading"
193 228 << QThread::currentThread()->objectName();
194 229 // NOTE: Try to use multithread if possible
195 230 const auto times = parameters.m_Times;
196 231
197 232 for (const auto &dateTime : qAsConst(times)) {
198 233 if (m_VariableToEnableProvider[acqIdentifier]) {
199 234 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime, parameters.m_Data);
200 235 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
201 236 }
202 237 }
203 238 }
204 239
205 240 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
206 241 {
207 242 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
208 243 << QThread::currentThread()->objectName();
209 244 auto it = m_VariableToEnableProvider.find(acqIdentifier);
210 245 if (it != m_VariableToEnableProvider.end()) {
211 246 it.value() = false;
212 247 }
213 248 else {
214 249 qCDebug(LOG_CosinusProvider())
215 250 << tr("Aborting progression of inexistant identifier detected !!!");
216 251 }
217 252 }
218 253
219 254 std::shared_ptr<IDataSeries> CosinusProvider::provideDataSeries(const SqpRange &dataRangeRequested,
220 255 const QVariantHash &data)
221 256 {
222 257 auto uid = QUuid::createUuid();
223 258 m_VariableToEnableProvider[uid] = true;
224 259 auto dataSeries = this->retrieveData(uid, dataRangeRequested, data);
225 260
226 261 m_VariableToEnableProvider.remove(uid);
227 262 return dataSeries;
228 263 }
General Comments 0
You need to be logged in to leave comments. Login now