|
30 | 30 | // external includes |
31 | 31 | #include <Framework/Logger.h> |
32 | 32 | #include <bitset> |
| 33 | +#include <algorithm> |
33 | 34 |
|
34 | 35 | namespace o2::quality_control_modules::tpc |
35 | 36 | { |
@@ -210,44 +211,101 @@ void calculateStatistics(const double* yValues, const double* yErrors, bool useE |
210 | 211 | return; |
211 | 212 | } |
212 | 213 |
|
| 214 | + if (useErrors && !yErrors) { |
| 215 | + ILOG(Error, Support) << "In calculateStatistics(): requested to use errors of data but TGraph does not contain errors." << ENDM; |
| 216 | + useErrors = false; |
| 217 | + } |
| 218 | + |
| 219 | + std::vector<double> v(yValues + firstPoint, yValues + lastPoint); |
| 220 | + std::vector<double> vErr; |
| 221 | + |
| 222 | + if (useErrors) { |
| 223 | + const std::vector<double> vErr_temp(yErrors + firstPoint, yErrors + lastPoint); |
| 224 | + for (int i = 0; i < vErr_temp.size(); i++) { |
| 225 | + vErr.push_back(vErr_temp[i]); |
| 226 | + } |
| 227 | + } |
| 228 | + |
| 229 | + retrieveStatistics(v, vErr, useErrors, mean, stddevOfMean); |
| 230 | +} |
| 231 | + |
| 232 | +void calculateStatistics(const double* yValues, const double* yErrors, bool useErrors, const int firstPoint, const int lastPoint, double& mean, double& stddevOfMean, std::vector<int>& maskPoints) |
| 233 | +{ |
| 234 | + // yErrors returns nullptr for TGraph (no errors) |
| 235 | + if (lastPoint - firstPoint <= 0) { |
| 236 | + ILOG(Error, Support) << "In calculateStatistics(), the first and last point of the range have to differ!" << ENDM; |
| 237 | + return; |
| 238 | + } |
| 239 | + |
| 240 | + if (useErrors && !yErrors) { |
| 241 | + ILOG(Error, Support) << "In calculateStatistics(): requested to use errors of data but TGraph does not contain errors." << ENDM; |
| 242 | + useErrors = false; |
| 243 | + } |
| 244 | + |
| 245 | + std::vector<double> v; |
| 246 | + const std::vector<double> v_temp(yValues + firstPoint, yValues + lastPoint); |
| 247 | + for (int i = 0; i < v_temp.size(); i++) { |
| 248 | + if (std::find(maskPoints.begin(), maskPoints.end(), i) == maskPoints.end()) { // i is not in the masked points |
| 249 | + v.push_back(v_temp[i]); |
| 250 | + } |
| 251 | + } |
| 252 | + |
| 253 | + std::vector<double> vErr; |
| 254 | + if (useErrors) { |
| 255 | + const std::vector<double> vErr_temp(yErrors + firstPoint, yErrors + lastPoint); |
| 256 | + for (int i = 0; i < vErr_temp.size(); i++) { |
| 257 | + if (std::find(maskPoints.begin(), maskPoints.end(), i) == maskPoints.end()) { // i is not in the masked points |
| 258 | + vErr.push_back(vErr_temp[i]); |
| 259 | + } |
| 260 | + } |
| 261 | + } |
| 262 | + |
| 263 | + retrieveStatistics(v, vErr, useErrors, mean, stddevOfMean); |
| 264 | +} |
| 265 | + |
| 266 | +void retrieveStatistics(std::vector<double>& values, std::vector<double>& errors, bool useErrors, double& mean, double& stddevOfMean) |
| 267 | +{ |
| 268 | + if ((errors.size() != values.size()) && useErrors) { |
| 269 | + ILOG(Error, Support) << "In retrieveStatistics(): errors do not match data points, omitting errors" << ENDM; |
| 270 | + useErrors = false; |
| 271 | + } |
| 272 | + |
213 | 273 | double sum = 0.; |
214 | 274 | double sumSquare = 0.; |
215 | 275 | double sumOfWeights = 0.; // sum w_i |
216 | 276 | double sumOfSquaredWeights = 0.; // sum (w_i)^2 |
217 | 277 | double weight = 0.; |
218 | 278 |
|
219 | | - const std::vector<double> v(yValues + firstPoint, yValues + lastPoint); |
220 | 279 | if (!useErrors) { |
221 | 280 | // In case of no errors, we set our weights equal to 1 |
222 | | - sum = std::accumulate(v.begin(), v.end(), 0.0); |
223 | | - sumOfWeights = v.size(); |
224 | | - sumOfSquaredWeights = v.size(); |
| 281 | + sum = std::accumulate(values.begin(), values.end(), 0.0); |
| 282 | + sumOfWeights = values.size(); |
| 283 | + sumOfSquaredWeights = values.size(); |
225 | 284 | } else { |
226 | 285 | // In case of errors, we set our weights equal to 1/sigma_i^2 |
227 | | - const std::vector<double> vErr(yErrors + firstPoint, yErrors + lastPoint); |
228 | | - for (size_t i = 0; i < v.size(); i++) { |
229 | | - weight = 1. / std::pow(vErr[i], 2.); |
230 | | - sum += v[i] * weight; |
231 | | - sumSquare += v[i] * v[i] * weight; |
| 286 | + for (size_t i = 0; i < values.size(); i++) { |
| 287 | + weight = 1. / std::pow(errors[i], 2.); |
| 288 | + sum += values[i] * weight; |
| 289 | + sumSquare += values[i] * values[i] * weight; |
232 | 290 | sumOfWeights += weight; |
233 | 291 | sumOfSquaredWeights += weight * weight; |
234 | 292 | } |
235 | 293 | } |
236 | 294 |
|
237 | 295 | mean = sum / sumOfWeights; |
238 | 296 |
|
239 | | - if (v.size() == 1) { // we only have one point, we keep it's uncertainty |
| 297 | + if (values.size() == 1) { // we only have one point, we keep it's uncertainty |
240 | 298 | if (!useErrors) { |
241 | 299 | stddevOfMean = 0.; |
242 | 300 | } else { |
243 | 301 | stddevOfMean = sqrt(1. / sumOfWeights); |
244 | 302 | } |
245 | 303 | } else { // for >= 2 points, we calculate the spread |
246 | 304 | if (!useErrors) { |
247 | | - std::vector<double> diff(v.size()); |
248 | | - std::transform(v.begin(), v.end(), diff.begin(), [mean](double x) { return x - mean; }); |
| 305 | + std::vector<double> diff(values.size()); |
| 306 | + std::transform(values.begin(), values.end(), diff.begin(), [mean](double x) { return x - mean; }); |
249 | 307 | double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0); |
250 | | - stddevOfMean = std::sqrt(sq_sum / (v.size() * (v.size() - 1.))); |
| 308 | + stddevOfMean = std::sqrt(sq_sum / (values.size() * (values.size() - 1.))); |
251 | 309 | } else { |
252 | 310 | double ratioSumWeight = sumOfSquaredWeights / (sumOfWeights * sumOfWeights); |
253 | 311 | stddevOfMean = sqrt((sumSquare / sumOfWeights - mean * mean) * (1. / (1. - ratioSumWeight)) * ratioSumWeight); |
|
0 commit comments