8#include "MantidAPI/Algorithm.tcc"
15#include "MantidIndexing/SpectrumIndexSet.h"
32const static std::string DETECTOR_WORKSPACE(
"DetectorWorkspace");
34const static std::string INCIDENT_ENERGY(
"IncidentEnergy");
36const static std::string MONITOR(
"MonitorIndex");
38const static std::string MONITOR_EPP_TABLE(
"MonitorEPPTable");
40const static std::string MONITOR_WORKSPACE(
"MonitorWorkspace");
44const static std::string MAX_ENERGY(
"MaximumEnergy");
47std::vector<size_t> toWorkspaceIndices(
const Mantid::Indexing::SpectrumIndexSet &indices) {
48 std::vector<size_t> wsIndices;
49 wsIndices.reserve(indices.size());
50 for (
size_t i = 0; i < indices.size(); ++i) {
51 wsIndices.emplace_back(indices[i]);
69 return "Calculates the kinetic energy of neutrons leaving the source based "
70 "on the time it takes for them to travel between a monitor and a "
93 auto tofWorkspace = std::make_shared<Kernel::CompositeValidator>();
96 auto mandatoryIntProperty = std::make_shared<Kernel::MandatoryValidator<int>>();
97 auto mustBePositive = std::make_shared<Kernel::BoundedValidator<double>>();
98 mustBePositive->setLower(0);
100 declareWorkspaceInputProperties<API::MatrixWorkspace, static_cast<int>(IndexType::SpectrumNum) |
101 static_cast<int>(IndexType::WorkspaceIndex)>(
102 Prop::DETECTOR_WORKSPACE,
"A workspace containing the detector spectra.", tofWorkspace);
106 "A Workspace containing the monitor spectrum; if empty, " + Prop::DETECTOR_WORKSPACE +
" will be used.");
109 "An EPP table corresponding to " + Prop::MONITOR_WORKSPACE);
114 "Interval between neutron pulses, in microseconds; taken "
115 "from the sample logs, if not specified.");
117 "Multiple pulse intervals will be added to the flight time "
118 "the until final energy is less than this value.");
129 Indexing::SpectrumIndexSet detectorIndices;
130 std::tie(detectorWs, detectorIndices) = getWorkspaceAndIndices<API::MatrixWorkspace>(Prop::DETECTOR_WORKSPACE);
133 const int monitorIndex =
getProperty(Prop::MONITOR);
135 monitorWs = detectorWs;
136 if (std::find(detectorIndices.begin(), detectorIndices.end(), monitorIndex) != detectorIndices.end()) {
137 throw std::runtime_error(
"MonitorIndex is also listed in DetectorWorkspaceIndexSet.");
140 if (!monitorWs->spectrumInfo().isMonitor(monitorIndex)) {
141 m_log.
warning(
"The monitor spectrum is not marked as a monitor.");
143 const auto detWsIndices = toWorkspaceIndices(detectorIndices);
144 auto detectorSumWs =
groupSpectra(detectorWs, detWsIndices);
146 const auto sampleToDetectorDistance = detectorSumWs->spectrumInfo().l2(0);
150 }
catch (std::runtime_error &e) {
151 throw std::runtime_error(std::string(
"Failed to find detector peak for incident energy: ") + e.what());
154 const std::vector<size_t> monWsIndices = {
static_cast<size_t>(monitorIndex)};
155 auto monitorSumWs =
groupSpectra(monitorWs, monWsIndices);
158 if (
isDefault(Prop::MONITOR_EPP_TABLE)) {
163 }
catch (std::runtime_error &e) {
164 throw std::runtime_error(std::string(
"Failed to find monitor peak for incident energy: ") + e.what());
168 const auto monitorToSampleDistance = std::abs(monitorSumWs->spectrumInfo().l2(0));
169 const double minTOF =
minimumTOF(*detectorWs, sampleToDetectorDistance);
171 double timeOfFlight =
computeTOF(*detectorWs, detectorEPP, monitorEPP, minTOF);
172 const double flightLength = sampleToDetectorDistance + monitorToSampleDistance;
173 const double velocity = flightLength / timeOfFlight * 1e6;
177 g_log.
notice() <<
"Final time-of-flight:" << timeOfFlight <<
" which gives " <<
energy <<
" as "
178 << Prop::INCIDENT_ENERGY <<
".\n";
192 const double monitorEPP,
const double minTOF) {
193 double timeOfFlight = detectorEPP - monitorEPP;
195 while (timeOfFlight <= minTOF) {
196 double pulseInterval =
getProperty(Prop::PULSE_INTERVAL);
200 pulseInterval *= 1e6;
202 throw std::invalid_argument(
"PulseInterval not explicitly given nor found in the sample logs.");
205 g_log.
notice() <<
"Frame delay of " << pulseInterval <<
" microseconds will be added to the time-of-flight.\n";
206 timeOfFlight += pulseInterval;
208 g_log.
notice() <<
"Calculated time-of-flight: " << timeOfFlight <<
".\n";
219 const std::vector<size_t> &wsIndices) {
221 group->setProperty(
"InputWorkspace", ws);
222 group->setProperty(
"OutputWorkspace",
"unused");
223 group->setProperty(
"WorkspaceIndexList", wsIndices);
225 return group->getProperty(
"OutputWorkspace");
236 const double maxEnergy =
getProperty(Prop::MAX_ENERGY);
249 const auto &status = monitorEPPWs->getRef<std::string>(
"FitStatus", monitorIndex);
250 if (status !=
"success" && status !=
"narrowPeak") {
251 throw std::runtime_error(
"Monitor EPP fit status shows a failure.");
253 return monitorEPPWs->getRef<
double>(
"PeakCentre", monitorIndex);
263 findEPP->setProperty(
"InputWorkspace", ws);
264 findEPP->setProperty(
"OutputWorkspace",
"unused");
267 const auto &status = eppTable->getRef<std::string>(
"FitStatus", 0);
268 if (status !=
"success" && status !=
"narrowPeak") {
269 throw std::runtime_error(
"Could not fit a Gaussian to the data.");
271 return eppTable->getRef<
double>(
"PeakCentre", 0);
#define DECLARE_ALGORITHM(classname)
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
bool isDefault(const std::string &name) const
Kernel::Logger m_log
Logger for this algorithm.
const SpectrumInfo & spectrumInfo() const
Return a reference to the SpectrumInfo object.
const Run & run() const
Run details object access.
A validator which checks that a workspace has a valid instrument.
bool hasProperty(const std::string &name) const
Does the property exist on the object.
double getPropertyAsSingleValue(const std::string &name, Kernel::Math::StatisticType statistic=Kernel::Math::Mean) const
Returns a property as a single double value from its name.
Base MatrixWorkspace Abstract Class.
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
Estimates the incident neutron energy from the time of flight between a monitor and a set of detector...
double computeTOF(const API::MatrixWorkspace &detectorWs, const double detectorEPP, const double monitorEPP, const double minTOF)
Calculates the time of flight from the monitor to the detectors.
const std::string summary() const override
Returns a summary of algorithm's purpose.
const std::string category() const override
Algorithm's category for identification overriding a virtual method.
void init() override
Initialized the algorithm.
int version() const override
Returns algorithm's version for identification.
double peakPosition(API::MatrixWorkspace_sptr &ws)
Returns the TOF of the grouped detectors' elastic peak.
double monitorPeakPosition(const size_t monitorIndex)
Returns the TOF of the monitor's peak.
const std::vector< std::string > seeAlso() const override
Function to return all of the seeAlso algorithms related to this algorithm.
API::MatrixWorkspace_sptr groupSpectra(API::MatrixWorkspace_sptr &ws, const std::vector< size_t > &wsIndices)
Runs GroupDetectors on given workspace indices.
double minimumTOF(const API::MatrixWorkspace &ws, const double sampleToDetectorDistance)
Computes the minimum TOF between monitor and detectors from maximum energy.
void exec() override
Executes the algorithm.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void notice(const std::string &msg)
Logs at notice level.
void warning(const std::string &msg)
Logs at warning level.
static double run(const std::string &src, const std::string &dest, const double srcValue, const double l1, const double l2, const double theta, const DeltaEMode::Type emode, const double efixed)
Convert a single value between the given units (as strings)
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
static const std::string PULSE_INTERVAL("pulse_interval")
Name of the pulse interval sample log.
A namespace containing physical constants that are required by algorithms and unit routines.
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double meV
1 meV in Joules.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
String constants for algorithm's properties.
@ Input
An input workspace.
@ Output
An output workspace.