-
Notifications
You must be signed in to change notification settings - Fork 122
/
SetUncertainties.cpp
173 lines (150 loc) · 6.63 KB
/
SetUncertainties.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidAlgorithms/SetUncertainties.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/SpectrumInfo.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidGeometry/IDetector.h"
#include "MantidGeometry/Instrument.h"
#include "MantidKernel/BoundedValidator.h"
#include "MantidKernel/ListValidator.h"
#include "MantidKernel/VisibleWhenProperty.h"
#include <algorithm>
#include <vector>
namespace Mantid {
namespace Algorithms {
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(SetUncertainties)
using namespace Kernel;
using namespace API;
namespace {
/// Used to compare signal to zero
const double TOLERANCE = 1.e-10;
const std::string ZERO("zero");
const std::string SQRT("sqrt");
const std::string ONE_IF_ZERO("oneIfZero");
const std::string SQRT_OR_ONE("sqrtOrOne");
const std::string CUSTOM("custom");
struct SetError {
explicit SetError(const double setTo, const double ifEqualTo, const double tolerance)
: valueToSet(setTo), valueToCompare(ifEqualTo), tolerance(tolerance) {}
double operator()(const double error) {
double deviation = error - valueToCompare;
if (deviation < tolerance && deviation >= 0) {
return valueToSet;
} else {
return error;
}
}
double valueToSet;
double valueToCompare;
double tolerance;
};
struct SqrtError {
explicit SqrtError(const double constant) : zeroSqrtValue(constant) {}
double operator()(const double intensity) {
const double localIntensity = fabs(intensity);
if (localIntensity > TOLERANCE) {
return sqrt(localIntensity);
} else {
return zeroSqrtValue;
}
}
double zeroSqrtValue;
};
} // namespace
/// Algorithm's name
const std::string SetUncertainties::name() const { return "SetUncertainties"; }
/// Algorithm's version
int SetUncertainties::version() const { return (1); }
void SetUncertainties::init() {
auto mustBePositive = std::make_shared<BoundedValidator<double>>();
auto mustBePositiveInt = std::make_shared<BoundedValidator<int>>();
mustBePositive->setLower(0);
mustBePositiveInt->setLower(0);
declareProperty(std::make_unique<WorkspaceProperty<API::MatrixWorkspace>>("InputWorkspace", "", Direction::Input));
declareProperty(std::make_unique<WorkspaceProperty<API::MatrixWorkspace>>("OutputWorkspace", "", Direction::Output));
std::vector<std::string> errorTypes = {ZERO, SQRT, SQRT_OR_ONE, ONE_IF_ZERO, CUSTOM};
declareProperty("SetError", ZERO, std::make_shared<StringListValidator>(errorTypes),
"How to reset the uncertainties");
declareProperty("SetErrorTo", 1.000, mustBePositive, "The error value to set when using custom mode");
setPropertySettings("SetErrorTo", std::make_unique<VisibleWhenProperty>("SetError", IS_EQUAL_TO, "custom"));
declareProperty("IfEqualTo", 0.000, mustBePositive,
"Which error values in the input workspace should be "
"replaced when using custom mode");
setPropertySettings("IfEqualTo", std::make_unique<VisibleWhenProperty>("SetError", IS_EQUAL_TO, "custom"));
declareProperty("Precision", 3, mustBePositiveInt,
"How many decimal places of ``IfEqualTo`` are taken into "
"account for matching when using custom mode");
setPropertySettings("Precision", std::make_unique<VisibleWhenProperty>("SetError", IS_EQUAL_TO, "custom"));
}
void SetUncertainties::exec() {
MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace");
auto inputEventWorkspace = std::dynamic_pointer_cast<const DataObjects::EventWorkspace>(inputWorkspace);
MatrixWorkspace_sptr outputWorkspace = getProperty("OutputWorkspace");
std::string errorType = getProperty("SetError");
bool zeroError = (errorType == ZERO);
bool takeSqrt = ((errorType == SQRT) || (errorType == SQRT_OR_ONE));
bool resetOne = ((errorType == ONE_IF_ZERO) || (errorType == SQRT_OR_ONE));
bool customError = (errorType == CUSTOM);
double valueToSet = resetOne ? 1.0 : getProperty("SetErrorTo");
double valueToCompare = resetOne ? 0.0 : getProperty("IfEqualTo");
int precision = getProperty("Precision");
double tolerance = resetOne ? 1E-10 : std::pow(10.0, -1. * precision);
// Create the output workspace. This will copy many aspects from the input
// one.
const int64_t numHists = static_cast<int64_t>(inputWorkspace->getNumberHistograms());
if (inputEventWorkspace) {
if (inputWorkspace == outputWorkspace && errorType == SQRT &&
inputEventWorkspace->getEventType() == Mantid::API::EventType::TOF) {
// Uncertainty is already square root of the y value
return;
}
// Copy the histogram representation over to a Workspace2D
outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace);
PARALLEL_FOR_IF(Kernel::threadSafe(*inputWorkspace, *outputWorkspace))
for (int64_t i = 0; i < numHists; ++i) {
PARALLEL_START_INTERUPT_REGION
// copy X/Y/E
outputWorkspace->setSharedX(i, inputWorkspace->sharedX(i));
outputWorkspace->setSharedY(i, inputWorkspace->sharedY(i));
outputWorkspace->setSharedE(i, inputWorkspace->sharedE(i));
PARALLEL_END_INTERUPT_REGION
}
PARALLEL_CHECK_INTERUPT_REGION
} else if (inputWorkspace != outputWorkspace) {
outputWorkspace = inputWorkspace->clone();
}
const auto &spectrumInfo = inputWorkspace->spectrumInfo();
Progress prog(this, 0.0, 1.0, numHists);
PARALLEL_FOR_IF(Kernel::threadSafe(*inputWorkspace, *outputWorkspace))
for (int64_t i = 0; i < numHists; ++i) {
PARALLEL_START_INTERUPT_REGION
// copy the E or set to zero depending on the mode
if (errorType == ONE_IF_ZERO || customError) {
} else {
outputWorkspace->mutableE(i) = 0.0;
}
// ZERO mode doesn't calculate anything further
if ((!zeroError) && (!(spectrumInfo.hasDetectors(i) && spectrumInfo.isMasked(i)))) {
auto &E = outputWorkspace->mutableE(i);
if (takeSqrt) {
const auto &Y = outputWorkspace->y(i);
std::transform(Y.begin(), Y.end(), E.begin(), SqrtError(resetOne ? 1. : 0.));
} else {
std::transform(E.begin(), E.end(), E.begin(), SetError(valueToSet, valueToCompare, tolerance));
}
}
prog.report();
PARALLEL_END_INTERUPT_REGION
}
PARALLEL_CHECK_INTERUPT_REGION
setProperty("OutputWorkspace", outputWorkspace);
}
} // namespace Algorithms
} // namespace Mantid