8#include "MantidHistogramData/Exception.h"
9#include "MantidHistogramData/Rebin.h"
38const std::string
POWER(
"Power");
43const std::vector<std::string> binningModeNames{
"Default",
"Linear",
"Logarithmic",
"ReverseLogarithmic",
"Power"};
44enum class BinningMode { DEFAULT,
LINEAR,
LOGARITHMIC, REVERSELOG, POWER, enum_count };
53using namespace Kernel;
55using DataObjects::EventList;
56using DataObjects::EventWorkspace;
59using HistogramData::BinEdges;
60using HistogramData::Frequencies;
61using HistogramData::FrequencyStandardDeviations;
62using HistogramData::Histogram;
63using HistogramData::Exception::InvalidBinEdgesError;
81 const std::string &binModeName) {
83 std::vector<double> rbParams;
85 if (inParams.size() >= 3) {
88 }
else if (inParams.size() == 1) {
93 logger.
information() <<
"Using the current min and max as default " << xmin <<
", " << xmax <<
'\n';
96 rbParams[1] = inParams[0];
102 BINMODE binMode = binModeName;
103 if (binMode != BinningMode::DEFAULT) {
104 logger.
information() <<
"Bin mode set, forcing bin parameters to match.";
105 for (
size_t i = 0; i < rbParams.size() - 2; i += 2) {
106 if (binMode == BinningMode::LINEAR || binMode == BinningMode::POWER) {
107 rbParams[i + 1] =
fabs(rbParams[i + 1]);
108 }
else if (binMode == BinningMode::LOGARITHMIC || binMode == BinningMode::REVERSELOG) {
109 rbParams[i + 1] = -
fabs(rbParams[i + 1]);
113 for (
size_t i = 0; i < rbParams.size() - 2; i += 2) {
115 if (rbParams[i] < 0 && rbParams[i + 1] < 0 && rbParams[i + 2] > 0) {
116 std::stringstream msg;
117 msg <<
"Cannot create logarithmic binning that changes sign (xmin=";
118 msg << rbParams[i] <<
", xmax=" << rbParams[i + 2] <<
")";
119 throw std::runtime_error(msg.str());
131 std::map<std::string, std::string> helpMessages;
143 const auto eventInputWS = std::dynamic_pointer_cast<const EventWorkspace>(inputWS);
145 std::vector<double> validParams;
146 bool paramsWereReset =
false;
147 if (inputWS ==
nullptr) {
152 if (!AnalysisDataService::Instance().doesExist(inputWsName)) {
159 if (binMode != BinningMode::DEFAULT) {
161 paramsWereReset =
true;
163 }
catch (std::exception &err) {
169 if (binMode == BinningMode::REVERSELOG) {
173 }
else if (binMode != BinningMode::DEFAULT) {
183 std::string msg =
"The binning mode was set to 'Power', but no power was given.";
188 if (binMode != BinningMode::DEFAULT && binMode != BinningMode::POWER) {
189 g_log.
information() <<
"Discarding input power for incompatible binning mode.";
196 if (inputWS && !validParams.empty()) {
199 if (power != 0. && numBins > 10'001) {
201 }
else if (!(eventInputWS && preserveEvents)) {
202 size_t numSpec = inputWS->getNumberHistograms();
203 std::size_t binSpaceInBytes = 2 * numSpec * numBins *
sizeof(double);
205 if (!memMsg.empty()) {
206 memMsg =
"This binning is expected to create " +
std::to_string(numBins * numSpec) +
" bins. " + memMsg +
207 " Consider grouping spectra before rebinning, or using a coarser binning.";
213 const auto ¶msToValidate = paramsWereReset ? validParams : rbParams;
215 }
catch (std::exception &err) {
228 "Workspace containing the input data");
230 "The name to give the output workspace");
234 "A comma separated list of first bin boundary, width, last bin boundary. "
235 "Optionally this can be followed by a comma and more widths and last boundary pairs. "
236 "Optionally this can also be a single number, which is the bin width. In this case, the boundary of "
237 "binning will be determined by minimum and maximum TOF values among all events, or previous binning "
238 "boundary, in case of event Workspace, or non-event Workspace, respectively. "
239 "Negative width values indicate logarithmic binning.");
242 "Keep the output workspace as an EventWorkspace, if the input has events. If the input and output "
243 "EventWorkspace names are the same, only the X bins are set, which is very quick. If false, then the "
244 "workspace gets converted to a Workspace2D histogram.");
249 "Ignore errors related to zero/negative bin widths in input/output workspaces. When ignored, the "
250 "signal and errors are set to zero");
254 "For logarithmic intervals, the splitting starts from the end and goes back to the start, ie the bins are bigger "
255 "at the start getting exponentially smaller until they reach the end. For these bins, the FullBinsOnly flag is "
258 auto powerValidator = std::make_shared<Mantid::Kernel::BoundedValidator<double>>();
259 powerValidator->setLower(0);
260 powerValidator->setUpper(1);
262 "Splits the interval in bins which actual width is equal to requested width / (i ^ power); default "
263 "is linear. Power must be between 0 and 1.");
268 "Binning behavior can be specified in the usual way through sign of binwidth and other properties ('Default'); "
269 "or can be set to one of the allowed binning modes. "
270 "This will override all other specification or default behavior.");
287 bool inPlace = (inputWS == outputWS);
291 const bool dist = inputWS->isDistribution();
292 const bool isHist = inputWS->isHistogramData();
295 const auto histnumber =
static_cast<int>(inputWS->getNumberHistograms());
303 inputWS->getXMinMax(xmin, xmax);
306 std::vector<double> xAxisTmp;
308 HistogramData::BinEdges XValues_new(std::move(xAxisTmp));
313 if (eventInputWS !=
nullptr) {
316 if (PreserveEvents) {
318 outputWS = inputWS->clone();
320 auto eventOutputWS = std::dynamic_pointer_cast<EventWorkspace>(outputWS);
323 eventOutputWS->setAllX(XValues_new);
326 g_log.
information() <<
"Creating a Workspace2D from the EventWorkspace " << eventInputWS->getName() <<
".\n";
327 outputWS = DataObjects::create<DataObjects::Workspace2D>(*inputWS, histnumber, XValues_new);
330 Progress prog(
this, 0.0, 1.0, histnumber);
332 bool useUnsortingHistogram = (rbParams.size() < 4) && !useReverseLog && power == 0.0;
333 g_log.
information() <<
"Generating histogram without sorting=" << useUnsortingHistogram <<
"\n";
337 for (
int i = 0; i < histnumber; ++i) {
340 const EventList &el = eventInputWS->getSpectrum(i);
345 if (useUnsortingHistogram)
346 el.generateHistogram(rbParams[1], std::as_const(XValues_new), y_data, e_data);
348 el.generateHistogram(std::as_const(XValues_new), y_data, e_data);
351 outputWS->mutableY(i) = y_data;
352 outputWS->mutableE(i) = e_data;
373 ChildAlg->initialize();
374 ChildAlg->setProperty(
"InputWorkspace", inputWS);
376 inputWS = ChildAlg->getProperty(
"OutputWorkspace");
381 outputWS = DataObjects::create<API::HistoWorkspace>(*inputWS, histnumber, XValues_new);
385 Progress prog(
this, 0.0, 1.0, histnumber);
387 for (
int hist = 0; hist < histnumber; ++hist) {
391 outputWS->setHistogram(hist, HistogramData::rebin(inputWS->histogram(hist), XValues_new));
392 }
catch (InvalidBinEdgesError &) {
394 outputWS->setBinEdges(hist, XValues_new);
402 outputWS->setDistribution(dist);
407 for (
int i = 0; i < histnumber; ++i) {
408 if (inputWS->hasMaskedBins(i))
417 ChildAlg->initialize();
420 outputWS = ChildAlg->getProperty(
"OutputWorkspace");
439 const int hist,
const bool ignoreErrors) {
449 auto it = mask.cbegin();
450 auto &XValues = inputWS->x(hist);
451 masked_bins.emplace_back(XValues[(*it).first]);
452 weights.emplace_back((*it).second);
453 masked_bins.emplace_back(XValues[(*it).first + 1]);
454 for (++it; it != mask.end(); ++it) {
455 const double currentX = XValues[(*it).first];
458 if (masked_bins.back() != currentX) {
459 weights.emplace_back(0.0);
460 masked_bins.emplace_back(currentX);
462 weights.emplace_back((*it).second);
463 masked_bins.emplace_back(XValues[(*it).first + 1]);
467 auto errSize = weights.size();
468 Histogram oldHist(BinEdges(std::move(masked_bins)), Frequencies(std::move(weights)),
469 FrequencyStandardDeviations(errSize, 0));
474 auto newHist = HistogramData::rebin(oldHist, outputWS->binEdges(hist));
475 auto &newWeights = newHist.y();
479 if (newWeights[
index] > 0.0)
480 outputWS->flagMasked(hist,
index, newWeights[
index]);
482 }
catch (InvalidBinEdgesError &) {
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
#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_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.
bool existsProperty(const std::string &name) const override
Checks whether the named property is already in the list of managed property.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
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.
bool isDefault(const std::string &name) const
Base MatrixWorkspace Abstract Class.
std::map< size_t, double > MaskList
Masked bins for each spectrum are stored as a set of pairs containing <bin index, weight>
virtual void getXMinMax(double &xmin, double &xmax) const
Helper class for reporting progress from algorithms.
A property class for workspaces.
void exec() override
Executes the rebin algorithm.
void propagateMasks(const API::MatrixWorkspace_const_sptr &inputWS, const API::MatrixWorkspace_sptr &outputWS, const int hist, const bool IgnoreBinErrors=false)
Takes the masks in the input workspace and apportions the weights into the new bins that overlap with...
void init() override
Initialisation method.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
std::map< std::string, std::string > validateInputs() override
Validate that the input properties are sane.
static std::vector< double > rebinParamsFromInput(const std::vector< double > &inParams, const API::MatrixWorkspace &inputWS, Kernel::Logger &logger, const std::string &binModeName="Default")
Return the rebin parameters from a user input.
Support for a property that holds an array of values.
A concrete property based on user options of a finite list of strings.
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 information(const std::string &msg)
Logs at information level.
This class is responsible for memory statistics.
std::string checkAvailableMemory(std::size_t const requestedMemoryBytes) const
Check if there is enough space in memory to hold the requested amount of memory.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::size_t MANTID_KERNEL_DLL estimateNumberOfBins(std::vector< double > const ¶ms, double const power=-1)
Returns a size_t with the estimated number of bins that would be needed for a rebinning operation.
void MANTID_KERNEL_DLL validateRebinParameters(std::vector< double > const &, bool const =false)
Validate rebinning parameters, throwing an error if any assumptions are invalidated.
std::size_t MANTID_KERNEL_DLL createAxisFromRebinParams(const std::vector< double > ¶ms, std::vector< double > &xnew, const bool resize_xnew=true, const bool full_bins_only=false, const double xMinHint=std::nan(""), const double xMaxHint=std::nan(""), const bool useReverseLogarithmic=false, const double power=-1)
Creates a new output X array given a 'standard' set of rebinning parameters.
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.
const std::string IGNR_BIN_ERR("IgnoreBinErrors")
const std::string FULL_BIN_ONLY("FullBinsOnly")
const std::string PRSRV_EVENTS("PreserveEvents")
const std::string PARAMS("Params")
const std::string POWER("Power")
const std::string RVRS_LOG_BIN("UseReverseLogarithmic")
const std::string BINMODE("BinningMode")
const std::string OUTPUT_WKSP("OutputWorkspace")
const std::string INPUT_WKSP("InputWorkspace")
Helper class which provides the Collimation Length for SANS instruments.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
@ Output
An output workspace.