/
MonitorEfficiencyCorUser.cpp
135 lines (113 loc) · 5.02 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
// 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/MonitorEfficiencyCorUser.h"
#include "MantidAPI/InstrumentValidator.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/Run.h"
#include "MantidDataObjects/TableWorkspace.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidDataObjects/WorkspaceCreation.h"
#include "MantidGeometry/Instrument.h"
#include "MantidGeometry/muParser_Silent.h"
#include "MantidHistogramData/Histogram.h"
#include "MantidHistogramData/HistogramMath.h"
#include "MantidKernel/MultiThreaded.h"
#include "MantidKernel/Strings.h"
namespace Mantid::Algorithms {
using namespace Kernel;
using namespace API;
using namespace Geometry;
using namespace DataObjects;
using namespace HistogramData;
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(MonitorEfficiencyCorUser)
/** Initialize the algorithm's properties.
*/
void MonitorEfficiencyCorUser::init() {
declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input,
std::make_shared<InstrumentValidator>()),
"The workspace to correct for monitor efficiency");
declareProperty(std::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 input and output workspaces are not the same, create a new workspace for
// the output
if (m_outputWS != this->m_inputWS) {
m_outputWS = create<MatrixWorkspace>(*m_inputWS);
}
m_Ei = m_inputWS->run().getPropertyValueAsType<double>("Ei");
std::string mon_counts_log;
// get name of the monitor counts sample log from the instrument parameter
// file
try {
mon_counts_log = getValFromInstrumentDef("monitor_counts_log");
} catch (Kernel::Exception::InstrumentDefinitionError &) {
// the default value is monitor_counts
mon_counts_log = "monitor_counts";
}
m_monitorCounts = m_inputWS->run().getPropertyValueAsType<double>(mon_counts_log);
// 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 auto numberOfSpectra = static_cast<int>(this->m_inputWS->getNumberHistograms());
API::Progress prog(this, 0.0, 1.0, numberOfSpectra);
auto numberOfSpectra_i = static_cast<int64_t>(numberOfSpectra); // cast to make openmp happy
// Loop over the histograms (detector spectra)
double factor = 1 / eff0;
PARALLEL_FOR_IF(Kernel::threadSafe(*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 Mantid::Algorithms