-
Notifications
You must be signed in to change notification settings - Fork 122
/
SANSBeamFluxCorrection.cpp
143 lines (122 loc) · 5.72 KB
/
SANSBeamFluxCorrection.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
#include "MantidWorkflowAlgorithms/SANSBeamFluxCorrection.h"
#include "MantidAPI/AlgorithmProperty.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidKernel/PropertyManager.h"
#include "Poco/Path.h"
namespace Mantid {
namespace WorkflowAlgorithms {
using namespace Kernel;
using namespace API;
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(SANSBeamFluxCorrection)
void SANSBeamFluxCorrection::init() {
declareProperty(
make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input),
"Workspace to be corrected");
declareProperty(
make_unique<WorkspaceProperty<>>("InputMonitorWorkspace", "",
Direction::Input),
"Workspace containing the monitor counts for the sample data");
std::vector<std::string> exts{"_event.nxs", ".nxs", ".nxs.h5"};
declareProperty(
Kernel::make_unique<API::FileProperty>("ReferenceFluxFilename", "",
API::FileProperty::Load, exts),
"File containing the reference flux spectrum.");
declareProperty("ReductionProperties", "__sans_reduction_properties",
Direction::Input);
declareProperty(make_unique<WorkspaceProperty<>>("OutputWorkspace", "",
Direction::Output),
"Corrected workspace.");
declareProperty("OutputMessage", "", Direction::Output);
}
void SANSBeamFluxCorrection::exec() {
Progress progress(this, 0.0, 1.0, 10);
progress.report("Setting up beam flux correction");
// Reduction property manager
m_reductionManager = getProcessProperties();
// If the beam flux correction algorithm isn't in the reduction properties,
// add it
if (!m_reductionManager->existsProperty("BeamFluxAlgorithm")) {
auto algProp = make_unique<AlgorithmProperty>("BeamFluxAlgorithm");
algProp->setValue(toString());
m_reductionManager->declareProperty(std::move(algProp));
}
MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
MatrixWorkspace_sptr monitorWS = getProperty("InputMonitorWorkspace");
// Load reference
progress.report("Loading reference data");
MatrixWorkspace_sptr fluxRefWS = loadReference();
// Rebin the reference and monitor data to the sample data workspace
progress.report("Rebinning reference data");
IAlgorithm_sptr convAlg = createChildAlgorithm("ConvertToHistogram");
convAlg->setProperty("InputWorkspace", fluxRefWS);
convAlg->executeAsChildAlg();
fluxRefWS = convAlg->getProperty("OutputWorkspace");
IAlgorithm_sptr rebinAlg = createChildAlgorithm("RebinToWorkspace");
rebinAlg->setProperty("WorkspaceToRebin", fluxRefWS);
rebinAlg->setProperty("WorkspaceToMatch", inputWS);
rebinAlg->executeAsChildAlg();
MatrixWorkspace_sptr scaledfluxRefWS =
rebinAlg->getProperty("OutputWorkspace");
progress.report("Rebinning monitor data");
rebinAlg = createChildAlgorithm("RebinToWorkspace");
rebinAlg->setProperty("WorkspaceToRebin", monitorWS);
rebinAlg->setProperty("WorkspaceToMatch", inputWS);
rebinAlg->executeAsChildAlg();
monitorWS = rebinAlg->getProperty("OutputWorkspace");
progress.report("Correcting input data");
// I = I_0 / Phi_sample
// Phi_sample = M_sample * [Phi_ref/M_ref]
// where [Phi_ref/M_ref] is the fluxRefWS workspace
IAlgorithm_sptr divideAlg = createChildAlgorithm("Divide");
divideAlg->setProperty("LHSWorkspace", inputWS);
divideAlg->setProperty("RHSWorkspace", monitorWS);
divideAlg->executeAsChildAlg();
MatrixWorkspace_sptr outputWS = divideAlg->getProperty("OutputWorkspace");
divideAlg = createChildAlgorithm("Divide");
divideAlg->setProperty("LHSWorkspace", outputWS);
divideAlg->setProperty("RHSWorkspace", scaledfluxRefWS);
divideAlg->executeAsChildAlg();
outputWS = divideAlg->getProperty("OutputWorkspace");
setProperty("OutputWorkspace", outputWS);
setProperty("OutputMessage", "Flux correction applied\n" + m_output_message);
}
/**
* It's assumed that both the flux reference files are simple Nexus
* files since they have to produced by hand by the instrument
* scientists. A simple Load algorithm should suffice.
*/
MatrixWorkspace_sptr SANSBeamFluxCorrection::loadReference() {
const std::string referenceFluxFile =
getPropertyValue("ReferenceFluxFilename");
Poco::Path path(referenceFluxFile);
const std::string entryName = "SANSBeamFluxCorrection_" + path.getBaseName();
std::string fluxRefWSName = "__beam_flux_reference_" + path.getBaseName();
// Load reference flux as needed
MatrixWorkspace_sptr fluxRefWS;
if (m_reductionManager->existsProperty(entryName)) {
fluxRefWS = m_reductionManager->getProperty(entryName);
fluxRefWSName = m_reductionManager->getPropertyValue(entryName);
m_output_message += " | Using flux reference " + referenceFluxFile + "\n";
} else {
IAlgorithm_sptr loadAlg = createChildAlgorithm("Load");
loadAlg->setProperty("Filename", referenceFluxFile);
loadAlg->executeAsChildAlg();
Workspace_sptr tmpWS = loadAlg->getProperty("OutputWorkspace");
fluxRefWS = boost::dynamic_pointer_cast<MatrixWorkspace>(tmpWS);
m_output_message +=
" | Loaded flux reference " + referenceFluxFile + "\n";
// Keep the reference data for later use
AnalysisDataService::Instance().addOrReplace(fluxRefWSName, fluxRefWS);
m_reductionManager->declareProperty(
Kernel::make_unique<WorkspaceProperty<>>(entryName, fluxRefWSName,
Direction::InOut));
m_reductionManager->setPropertyValue(entryName, fluxRefWSName);
m_reductionManager->setProperty(entryName, fluxRefWS);
}
return fluxRefWS;
}
} // namespace WorkflowAlgorithms
} // namespace Mantid