-
Notifications
You must be signed in to change notification settings - Fork 122
/
MonitorEfficiencyCorUser.cpp
137 lines (116 loc) · 4.71 KB
/
MonitorEfficiencyCorUser.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
#include "MantidAlgorithms/MonitorEfficiencyCorUser.h"
#include "MantidAPI/InstrumentValidator.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidHistogramData/HistogramMath.h"
#include "MantidGeometry/Instrument.h"
#include "MantidGeometry/muParser_Silent.h"
#include "MantidKernel/MultiThreaded.h"
using Mantid::HistogramData::HistogramX;
using Mantid::HistogramData::HistogramY;
using Mantid::HistogramData::HistogramE;
namespace Mantid {
namespace Algorithms {
using namespace Kernel;
using namespace API;
using namespace Geometry;
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(MonitorEfficiencyCorUser)
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void MonitorEfficiencyCorUser::init() {
declareProperty(make_unique<WorkspaceProperty<>>(
"InputWorkspace", "", Direction::Input,
boost::make_shared<InstrumentValidator>()),
"The workspace to correct for monitor efficiency");
declareProperty(make_unique<WorkspaceProperty<>>("OutputWorkspace", "",
Direction::Output),
"The name of the workspace in which to store the result.");
}
void MonitorEfficiencyCorUser::exec() {
m_inputWS = this->getProperty("InputWorkspace");
m_outputWS = this->getProperty("OutputWorkspace");
if (m_inputWS->getInstrument()->getName() != "TOFTOF") {
std::string message("The input workspace does not come from TOFTOF");
g_log.error(message);
throw std::invalid_argument(message);
}
// If input and output workspaces are not the same, create a new workspace for
// the output
if (m_outputWS != this->m_inputWS) {
m_outputWS = API::WorkspaceFactory::Instance().create(m_inputWS);
}
double val;
Strings::convert(m_inputWS->run().getProperty("Ei")->value(), val);
m_Ei = val;
Strings::convert(m_inputWS->run().getProperty("monitor_counts")->value(),
m_monitorCounts);
// get Efficiency formula from the IDF - Parameters file
const std::string effFormula = getValFromInstrumentDef("formula_mon_eff");
// Calculate Efficiency for E = Ei
const double eff0 = m_monitorCounts * calculateFormulaValue(effFormula, m_Ei);
// Calculate the number of spectra in this workspace
const int numberOfSpectra =
static_cast<int>(this->m_inputWS->getNumberHistograms());
API::Progress prog(this, 0.0, 1.0, numberOfSpectra);
int64_t numberOfSpectra_i =
static_cast<int64_t>(numberOfSpectra); // cast to make openmp happy
// Loop over the histograms (detector spectra)
double factor = 1 / eff0;
PARALLEL_FOR2(m_outputWS, m_inputWS)
for (int64_t i = 0; i < numberOfSpectra_i; ++i) {
PARALLEL_START_INTERUPT_REGION
m_outputWS->setHistogram(i, m_inputWS->histogram(i) * factor);
prog.report("Detector Efficiency correction...");
PARALLEL_END_INTERUPT_REGION
} // end for i
PARALLEL_CHECK_INTERUPT_REGION
setProperty("OutputWorkspace", m_outputWS);
}
/**
* Calculate the value of a formula
* @param formula :: Formula to correct
* @param energy :: value of the energy to use in the formula
* @return calculated corrected value of the monitor count
*/
double
MonitorEfficiencyCorUser::calculateFormulaValue(const std::string &formula,
double energy) {
try {
mu::Parser p;
p.DefineVar("e", &energy);
p.SetExpr(formula);
double eff = p.Eval();
g_log.debug() << "Formula: " << formula << " with: " << energy
<< "evaluated to: " << eff << '\n';
return eff;
} catch (mu::Parser::exception_type &e) {
throw Kernel::Exception::InstrumentDefinitionError(
"Error calculating formula from string. Muparser error message is: " +
e.GetMsg());
}
}
/**
* Returns the value associated to a parameter name in the IDF
* @param parameterName :: parameter name in the IDF
* @return the value associated to the parameter name
*/
std::string MonitorEfficiencyCorUser::getValFromInstrumentDef(
const std::string ¶meterName) {
const ParameterMap &pmap = m_inputWS->constInstrumentParameters();
Instrument_const_sptr instrument = m_inputWS->getInstrument();
Parameter_sptr par =
pmap.getRecursive(instrument->getChild(0).get(), parameterName);
if (par) {
std::string ret = par->asString();
g_log.debug() << "Parsed parameter " << parameterName << ": " << ret
<< "\n";
return ret;
} else {
throw Kernel::Exception::InstrumentDefinitionError(
"There is no <" + parameterName + "> in the instrument definition!");
}
}
} // namespace Algorithms
} // namespace Mantid