25using namespace Kernel;
27using namespace Algorithms::PeakParameterHelper;
30using namespace DataObjects;
39 "A 2D workspace with X values of d-spacing");
41 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
42 mustBePositive->setLower(0);
44 declareProperty(
"Step", 0.001, mustBePositive,
"Step size used to bin d-spacing data");
45 declareProperty(
"DReference", 2.0, mustBePositive,
"Center of reference peak in d-space");
46 declareProperty(
"XMin", 0.0,
"Minimum of CrossCorrelation data to search for peak, usually negative");
47 declareProperty(
"XMax", 0.0,
"Maximum of CrossCorrelation data to search for peak, usually positive");
50 "Optional: The name of the output CalFile to save the "
51 "generated OffsetsWorkspace.");
53 "An output workspace containing the offsets.");
59 "Mask workspace (optional input / output workspace):"
60 " when specified, if the workspace already exists, any incoming masked detectors will be combined"
61 " with any additional outgoing masked detectors detected by the algorithm");
65 std::make_shared<StringListValidator>(FunctionFactory::Instance().getFunctionNames<IPeakFunction>()),
66 "The function type for fitting the peaks.");
68 "Whether to esimate FWHM of peak function when estimating fit parameters");
69 declareProperty(
"MaxOffset", 1.0,
"Maximum absolute value of offsets; default is 1");
72 std::vector<std::string> modes{
"Relative",
"Absolute",
"Signed"};
74 declareProperty(
"OffsetMode",
"Relative", std::make_shared<StringListValidator>(modes),
75 "Whether to calculate a relative, absolute, or signed offset");
77 "The known peak centre value from the NIST standard "
78 "information, this is only used in Absolute OffsetMode.");
82 std::map<std::string, std::string> result;
86 result[
"InputWorkspace"] =
"The InputWorkspace must be a MatrixWorkspace.";
90 const auto unit = inputWS->getAxis(0)->unit()->caption();
91 if (unit !=
"Bins of Shift" && unit !=
"d-Spacing") {
92 const auto unitErrorMsg =
"GetDetectorOffsets only supports input workspaces with units 'Bins of Shift' or "
93 "'d-Spacing', your unit was : " +
95 result[
"InputWorkspace"] = unitErrorMsg;
101 const bool maskContainsAllDetIDs = maskWS->containsDetIDs(inputWS->getInstrument()->getDetectorIDs(
true));
103 if (!maskContainsAllDetIDs) {
104 result[
"MaskWorkspace"] =
105 "incoming mask workspace must be fully specified, containing an entry for each detid in the input workspace";
106 }
else if (maskWS->getInstrument()->getNumberDetectors(
true) !=
107 inputWS->getInstrument()->getNumberDetectors(
true)) {
108 result[
"MaskWorkspace"] =
"incoming mask workspace must have the same instrument as the input workspace";
109 }
else if (maskWS->getNumberHistograms() != inputWS->getInstrument()->getNumberDetectors(
true)) {
110 result[
"MaskWorkspace"] =
"incoming mask workspace must have one spectrum per detector";
127 throw std::runtime_error(
"Must specify m_Xmin<m_Xmax");
134 if (mode_str ==
"Absolute") {
138 else if (mode_str ==
"Relative") {
142 else if (mode_str ==
"Signed") {
148 int64_t nspec =
static_cast<int64_t
>(
inputW->getNumberHistograms());
151 auto outputW = std::make_shared<OffsetsWorkspace>(
inputW->getInstrument());
152 size_t N_d = outputW->getNumberHistograms();
153 for (
size_t di = 0; di < N_d; ++di)
154 outputW->mutableY(di) = 0.0;
162 g_log.
debug() <<
"[GetDetectorOffsets]: CREATING new MaskWorkspace.\n";
164 maskWS = std::make_shared<MaskWorkspace>(
inputW->getInstrument());
166 g_log.
debug() <<
"[GetDetectorOffsets]: Using EXISTING MaskWorkspace.\n";
169 maskWS->combineFromDetectorMasks(
inputW->detectorInfo());
172 Progress prog(
this, 0.0, 1.0, nspec);
174 for (int64_t wi = 0; wi < nspec; ++wi) {
177 const auto &dets =
inputW->getSpectrum(
static_cast<size_t>(wi)).getDetectorIDs();
180 if (maskWS->isMasked(dets))
184 double offset =
fitSpectra(
static_cast<size_t>(wi));
185 bool spectrumIsMasked =
false;
187 g_log.
debug() <<
"[GetDetectorOffsets]: fit failure: offset: " << std::abs(offset)
188 <<
" is greater than maximum allowed: " <<
m_maxOffset <<
".\n";
189 spectrumIsMasked =
true;
196 for (
const auto &det : dets) {
197 if (spectrumIsMasked) {
198 maskWS->setMasked(det,
true);
202 if (!maskWS->isMasked(det))
203 outputW->setValue(det, offset);
211 maskWS->combineToDetectorMasks();
212 maskWS->combineToDetectorMasks(outputW->mutableDetectorInfo());
216 trace <<
"[GetDetectorOffsets]: Computed offsets:\n" << std::endl;
217 for (
size_t ns = 0; ns <
inputW->getNumberHistograms(); ++ns) {
218 const auto dets =
inputW->getSpectrum(ns).getDetectorIDs();
219 for (
const auto &det : dets)
220 trace <<
" " << outputW->getValue(det) << (maskWS->isMasked(det) ?
"*" :
"") <<
"\n";
231 std::string filename =
getProperty(
"GroupingFileName");
232 if (!filename.empty()) {
235 childAlg->setProperty(
"OffsetsWorkspace", outputW);
236 childAlg->setProperty(
"MaskWorkspace", maskWS);
237 childAlg->setPropertyValue(
"Filename", filename);
238 childAlg->executeAsChildAlg();
249 constexpr double FIT_FAILURE = DBL_MAX;
252 const auto &yValues =
inputW->y(wksp_index);
253 auto it = std::max_element(yValues.cbegin(), yValues.cend());
256 double peakHeight = *it;
257 const double peakLoc =
inputW->x(wksp_index)[
static_cast<size_t>(it - yValues.cbegin())];
261 if (std::isnan(peakHeight))
262 return (FIT_FAILURE);
267 const auto &histogram =
inputW->histogram(wksp_index);
268 const auto &vector_x = histogram.points();
272 if (start_index != stop_index) {
274 auto bkgdFunction = std::dynamic_pointer_cast<IBackgroundFunction>(fun_ptr->getFunction(0));
275 auto peakFunction = std::dynamic_pointer_cast<IPeakFunction>(fun_ptr->getFunction(1));
276 int result =
estimatePeakParameters(histogram, std::pair<size_t, size_t>(start_index, stop_index), peakFunction,
278 if (result != PeakFitResult::GOOD) {
280 <<
" bad result for estimating peak parameters, using default peak height and loc\n";
284 <<
" range size is zero when estimating peak parameters, using default peak height and loc\n";
296 fit_alg->setProperty(
"Function", fun_ptr);
298 fit_alg->setProperty(
"InputWorkspace",
inputW);
299 fit_alg->setProperty<
int>(
"WorkspaceIndex",
300 static_cast<int>(wksp_index));
301 fit_alg->setProperty(
"StartX",
m_Xmin);
302 fit_alg->setProperty(
"EndX",
m_Xmax);
303 fit_alg->setProperty(
"MaxIterations", 100);
305 fit_alg->executeAsChildAlg();
306 std::string fitStatus = fit_alg->getProperty(
"OutputStatus");
308 if (fitStatus !=
"success") {
309 g_log.
debug() <<
"[GetDetectorOffsets]: Fit algorithm failure: " << fitStatus <<
"\n";
310 return (FIT_FAILURE);
316 double offset = function->getParameter(3);
352 peak->setHeight(peakHeight);
353 peak->setCentre(peakLoc);
354 const double sigma(10.0);
355 peak->setFwhm(2.0 * std::sqrt(2.0 * M_LN2) *
sigma);
359 fitFunc->addFunction(peak);
361 return std::shared_ptr<IFunction>(fitFunc);
#define DECLARE_ALGORITHM(classname)
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_CRITICAL(name)
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
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
A composite function is a function containing other functions.
@ OptionalSave
to specify a file to write to but an empty string is
The FunctionFactory class is in charge of the creation of concrete instances of fitting functions.
std::shared_ptr< IFunction > createFunction(const std::string &type) const
Creates an instance of a function.
Helper class for reporting progress from algorithms.
A property class for workspaces.
API::MatrixWorkspace_sptr inputW
A pointer to the input workspace.
double m_Xmax
The end of the X range for fitting.
API::IFunction_sptr createFunction(const double peakHeight, const double peakLoc)
Create a function string from the given parameters and the algorithm inputs.
double m_dreference
The expected peak position in d-spacing (?)
std::map< std::string, std::string > validateInputs() override
Method checking errors on ALL the inputs, before execution.
double fitSpectra(const size_t wksp_index)
Call Gaussian as a Child Algorithm to fit the peak in a spectrum.
void init() override
Initialisation method.
bool m_estimateFWHM
Flag to estimate fwhm fit parameter.
void exec() override
Executes the algorithm.
double m_Xmin
The start of the X range for fitting.
double m_dideal
The known peak centre value from the NIST standard.
double m_maxOffset
The maximum absolute value of offsets.
Exception for when an item is not found in a collection.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
The Logger class is in charge of the publishing messages from the framework through various channels.
void debug(const std::string &msg)
Logs at debug level.
void notice(const std::string &msg)
Logs at notice level.
void error(const std::string &msg)
Logs at error level.
std::ostream & getLogStream(const Priority &priority)
gets the correct log stream for a priority
int getLevel() const
Returns the Logger's log level.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
The concrete, templated class for properties.
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
MANTID_ALGORITHMS_DLL size_t findXIndex(const vector_like &vecx, const double x, const size_t startindex=0)
Get an index of a value in a sorted vector.
MANTID_ALGORITHMS_DLL int estimatePeakParameters(const HistogramData::Histogram &histogram, const std::pair< size_t, size_t > &peak_window, const API::IPeakFunction_sptr &peakfunction, const API::IBackgroundFunction_sptr &bkgdfunction, bool observe_peak_width, const EstimatePeakWidth peakWidthEstimateApproach, const double peakWidthPercentage, const double minPeakHeight)
Estimate peak parameters by 'observation'.
std::shared_ptr< const MaskWorkspace > MaskWorkspace_const_sptr
shared pointer to a const MaskWorkspace
std::shared_ptr< MaskWorkspace > MaskWorkspace_sptr
shared pointer to the MaskWorkspace class
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
@ Input
An input workspace.
@ Output
An output workspace.