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