8#include "MantidHistogramData/Exception.h"
9#include "MantidHistogramData/Rebin.h"
36const std::string
POWER(
"Power");
41const std::vector<std::string> binningModeNames{
"Default",
"Linear",
"Logarithmic",
"ReverseLogarithmic",
"Power"};
42enum class BinningMode { DEFAULT,
LINEAR,
LOGARITHMIC, REVERSELOG, POWER, enum_count };
51using namespace Kernel;
53using DataObjects::EventList;
54using DataObjects::EventWorkspace;
57using HistogramData::BinEdges;
58using HistogramData::Frequencies;
59using HistogramData::FrequencyStandardDeviations;
60using HistogramData::Histogram;
61using HistogramData::Exception::InvalidBinEdgesError;
79 const std::string &binModeName) {
81 std::vector<double> rbParams;
83 if (inParams.size() >= 3) {
86 }
else if (inParams.size() == 1) {
91 logger.
information() <<
"Using the current min and max as default " << xmin <<
", " << xmax <<
'\n';
94 rbParams[1] = inParams[0];
100 BINMODE binMode = binModeName;
101 if (binMode != BinningMode::DEFAULT) {
102 logger.
information() <<
"Bin mode set, forcing bin parameters to match.";
103 for (
size_t i = 0; i < rbParams.size() - 2; i += 2) {
104 if (binMode == BinningMode::LINEAR || binMode == BinningMode::POWER) {
105 rbParams[i + 1] =
fabs(rbParams[i + 1]);
106 }
else if (binMode == BinningMode::LOGARITHMIC || binMode == BinningMode::REVERSELOG) {
107 rbParams[i + 1] = -
fabs(rbParams[i + 1]);
111 for (
size_t i = 0; i < rbParams.size() - 2; i += 2) {
113 if (rbParams[i] < 0 && rbParams[i + 1] < 0 && rbParams[i + 2] > 0) {
114 std::stringstream msg;
115 msg <<
"Cannot create logarithmic binning that changes sign (xmin=";
116 msg << rbParams[i] <<
", xmax=" << rbParams[i + 2] <<
")";
117 throw std::runtime_error(msg.str());
129 std::map<std::string, std::string> helpMessages;
141 const auto eventInputWS = std::dynamic_pointer_cast<const EventWorkspace>(inputWS);
143 std::vector<double> validParams;
144 bool paramsWereReset =
false;
145 if (inputWS ==
nullptr) {
150 if (!AnalysisDataService::Instance().doesExist(inputWsName)) {
157 if (binMode != BinningMode::DEFAULT) {
159 paramsWereReset =
true;
161 }
catch (std::exception &err) {
167 if (binMode == BinningMode::REVERSELOG) {
171 }
else if (binMode != BinningMode::DEFAULT) {
181 std::string msg =
"The binning mode was set to 'Power', but no power was given.";
186 if (binMode != BinningMode::DEFAULT && binMode != BinningMode::POWER) {
187 g_log.
information() <<
"Discarding input power for incompatible binning mode.";
194 if (inputWS && !validParams.empty()) {
197 if (power != 0. && numBins > 10'001) {
199 }
else if (!(eventInputWS && preserveEvents)) {
200 size_t numSpec = inputWS->getNumberHistograms();
201 std::size_t binSpaceInBytes = 2 * numSpec * numBins *
sizeof(double);
203 if (!memMsg.empty()) {
204 memMsg =
"This binning is expected to create " +
std::to_string(numBins * numSpec) +
" bins. " + memMsg +
205 " Consider grouping spectra before rebinning, or using a coarser binning.";
211 const auto ¶msToValidate = paramsWereReset ? validParams : rbParams;
213 }
catch (std::exception &err) {
226 "Workspace containing the input data");
228 "The name to give the output workspace");
232 "A comma separated list of first bin boundary, width, last bin boundary. "
233 "Optionally this can be followed by a comma and more widths and last boundary pairs. "
234 "Optionally this can also be a single number, which is the bin width. In this case, the boundary of "
235 "binning will be determined by minimum and maximum TOF values among all events, or previous binning "
236 "boundary, in case of event Workspace, or non-event Workspace, respectively. "
237 "Negative width values indicate logarithmic binning.");
240 "Keep the output workspace as an EventWorkspace, if the input has events. If the input and output "
241 "EventWorkspace names are the same, only the X bins are set, which is very quick. If false, then the "
242 "workspace gets converted to a Workspace2D histogram.");
247 "Ignore errors related to zero/negative bin widths in input/output workspaces. When ignored, the "
248 "signal and errors are set to zero");
252 "For logarithmic intervals, the splitting starts from the end and goes back to the start, ie the bins are bigger "
253 "at the start getting exponentially smaller until they reach the end. For these bins, the FullBinsOnly flag is "
256 auto powerValidator = std::make_shared<Mantid::Kernel::BoundedValidator<double>>();
257 powerValidator->setLower(0);
258 powerValidator->setUpper(1);
260 "Splits the interval in bins which actual width is equal to requested width / (i ^ power); default "
261 "is linear. Power must be between 0 and 1.");
266 "Binning behavior can be specified in the usual way through sign of binwidth and other properties ('Default'); "
267 "or can be set to one of the allowed binning modes. "
268 "This will override all other specification or default behavior.");
285 bool inPlace = (inputWS == outputWS);
289 const bool dist = inputWS->isDistribution();
290 const bool isHist = inputWS->isHistogramData();
293 const auto histnumber =
static_cast<int>(inputWS->getNumberHistograms());
301 inputWS->getXMinMax(xmin, xmax);
304 std::vector<double> xAxisTmp;
306 HistogramData::BinEdges XValues_new(std::move(xAxisTmp));
311 if (eventInputWS !=
nullptr) {
314 if (PreserveEvents) {
316 outputWS = inputWS->clone();
318 auto eventOutputWS = std::dynamic_pointer_cast<EventWorkspace>(outputWS);
321 eventOutputWS->setAllX(XValues_new);
324 g_log.
information() <<
"Creating a Workspace2D from the EventWorkspace " << eventInputWS->getName() <<
".\n";
325 outputWS = DataObjects::create<DataObjects::Workspace2D>(*inputWS, histnumber, XValues_new);
328 Progress prog(
this, 0.0, 1.0, histnumber);
330 bool useUnsortingHistogram = (rbParams.size() < 4) && !useReverseLog && power == 0.0;
331 g_log.
information() <<
"Generating histogram without sorting=" << useUnsortingHistogram <<
"\n";
335 for (
int i = 0; i < histnumber; ++i) {
338 const EventList &el = eventInputWS->getSpectrum(i);
341 if (useUnsortingHistogram)
342 el.generateHistogram(rbParams[1], XValues_new.rawData(), y_data, e_data);
344 el.generateHistogram(XValues_new.rawData(), y_data, e_data);
347 outputWS->mutableY(i) = y_data;
348 outputWS->mutableE(i) = e_data;
369 ChildAlg->initialize();
370 ChildAlg->setProperty(
"InputWorkspace", inputWS);
372 inputWS = ChildAlg->getProperty(
"OutputWorkspace");
377 outputWS = DataObjects::create<API::HistoWorkspace>(*inputWS, histnumber, XValues_new);
381 Progress prog(
this, 0.0, 1.0, histnumber);
383 for (
int hist = 0; hist < histnumber; ++hist) {
387 outputWS->setHistogram(hist, HistogramData::rebin(inputWS->histogram(hist), XValues_new));
388 }
catch (InvalidBinEdgesError &) {
390 outputWS->setBinEdges(hist, XValues_new);
398 outputWS->setDistribution(dist);
403 for (
int i = 0; i < histnumber; ++i) {
404 if (inputWS->hasMaskedBins(i))
413 ChildAlg->initialize();
416 outputWS = ChildAlg->getProperty(
"OutputWorkspace");
435 const int hist,
const bool ignoreErrors) {
445 auto it = mask.cbegin();
446 auto &XValues = inputWS->x(hist);
447 masked_bins.emplace_back(XValues[(*it).first]);
448 weights.emplace_back((*it).second);
449 masked_bins.emplace_back(XValues[(*it).first + 1]);
450 for (++it; it != mask.end(); ++it) {
451 const double currentX = XValues[(*it).first];
454 if (masked_bins.back() != currentX) {
455 weights.emplace_back(0.0);
456 masked_bins.emplace_back(currentX);
458 weights.emplace_back((*it).second);
459 masked_bins.emplace_back(XValues[(*it).first + 1]);
463 auto errSize = weights.size();
464 Histogram oldHist(BinEdges(std::move(masked_bins)), Frequencies(std::move(weights)),
465 FrequencyStandardDeviations(errSize, 0));
470 auto newHist = HistogramData::rebin(oldHist, outputWS->binEdges(hist));
471 auto &newWeights = newHist.y();
475 if (newWeights[
index] > 0.0)
476 outputWS->flagMasked(hist,
index, newWeights[
index]);
478 }
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.