8#include "MantidHistogramData/Exception.h"
9#include "MantidHistogramData/Rebin.h"
35const std::string
POWER(
"Power");
40const std::vector<std::string> binningModeNames{
"Default",
"Linear",
"Logarithmic",
"ReverseLogarithmic",
"Power"};
41enum class BinningMode { DEFAULT,
LINEAR,
LOGARITHMIC, REVERSELOG, POWER, enum_count };
50using namespace Kernel;
52using DataObjects::EventList;
53using DataObjects::EventWorkspace;
56using HistogramData::BinEdges;
57using HistogramData::Frequencies;
58using HistogramData::FrequencyStandardDeviations;
59using HistogramData::Histogram;
60using HistogramData::Exception::InvalidBinEdgesError;
78 const std::string &binModeName) {
80 std::vector<double> rbParams;
82 if (inParams.size() >= 3) {
85 }
else if (inParams.size() == 1) {
90 logger.
information() <<
"Using the current min and max as default " << xmin <<
", " << xmax <<
'\n';
93 rbParams[1] = inParams[0];
99 BINMODE binMode = binModeName;
100 if (binMode != BinningMode::DEFAULT) {
101 logger.
information() <<
"Bin mode set, forcing bin parameters to match.";
102 for (
size_t i = 0; i < rbParams.size() - 2; i += 2) {
103 if (binMode == BinningMode::LINEAR || binMode == BinningMode::POWER) {
104 rbParams[i + 1] =
fabs(rbParams[i + 1]);
105 }
else if (binMode == BinningMode::LOGARITHMIC || binMode == BinningMode::REVERSELOG) {
106 rbParams[i + 1] = -
fabs(rbParams[i + 1]);
110 for (
size_t i = 0; i < rbParams.size() - 2; i += 2) {
112 if (rbParams[i] < 0 && rbParams[i + 1] < 0 && rbParams[i + 2] > 0) {
113 std::stringstream msg;
114 msg <<
"Cannot create logarithmic binning that changes sign (xmin=";
115 msg << rbParams[i] <<
", xmax=" << rbParams[i + 2] <<
")";
116 throw std::runtime_error(msg.str());
128 std::map<std::string, std::string> helpMessages;
140 if (inputWS ==
nullptr) {
145 if (!AnalysisDataService::Instance().doesExist(inputWsName)) {
152 if (binMode != BinningMode::DEFAULT) {
154 rbParams = validParams;
156 }
catch (std::exception &err) {
162 if (binMode == BinningMode::REVERSELOG) {
166 }
else if (binMode != BinningMode::DEFAULT) {
176 std::string msg =
"The binning mode was set to 'Power', but no power was given.";
184 if (binMode != BinningMode::DEFAULT && binMode != BinningMode::POWER) {
185 g_log.
information() <<
"Discarding input power for incompatible binning mode.";
191 double roughEstimate = 0;
194 double eulerMascheroni = 0.57721;
197 for (
size_t i = 0; i < rbParams.size() - 2; i += 2) {
198 double upperLimit = rbParams[i + 2];
199 double lowerLimit = rbParams[i];
200 double factor = rbParams[i + 1];
205 helpMessages[
PropertyNames::PARAMS] =
"Provided width value cannot be negative for inverse power binning.";
209 roughEstimate += std::exp((upperLimit - lowerLimit) / factor - eulerMascheroni);
211 roughEstimate += std::pow(((upperLimit - lowerLimit) / factor) * (1 - power) + 1, 1 / (1 - power));
215 if (roughEstimate > 10000) {
229 "Workspace containing the input data");
231 "The name to give the output workspace");
235 "A comma separated list of first bin boundary, width, last bin boundary. "
236 "Optionally this can be followed by a comma and more widths and last boundary pairs. "
237 "Optionally this can also be a single number, which is the bin width. In this case, the boundary of "
238 "binning will be determined by minimum and maximum TOF values among all events, or previous binning "
239 "boundary, in case of event Workspace, or non-event Workspace, respectively. "
240 "Negative width values indicate logarithmic binning.");
243 "Keep the output workspace as an EventWorkspace, if the input has events. If the input and output "
244 "EventWorkspace names are the same, only the X bins are set, which is very quick. If false, then the "
245 "workspace gets converted to a Workspace2D histogram.");
250 "Ignore errors related to zero/negative bin widths in input/output workspaces. When ignored, the "
251 "signal and errors are set to zero");
255 "For logarithmic intervals, the splitting starts from the end and goes back to the start, ie the bins are bigger "
256 "at the start getting exponentially smaller until they reach the end. For these bins, the FullBinsOnly flag is "
259 auto powerValidator = std::make_shared<Mantid::Kernel::BoundedValidator<double>>();
260 powerValidator->setLower(0);
261 powerValidator->setUpper(1);
263 "Splits the interval in bins which actual width is equal to requested width / (i ^ power); default "
264 "is linear. Power must be between 0 and 1.");
269 "Binning behavior can be specified in the usual way through sign of binwidth and other properties ('Default'); "
270 "or can be set to one of the allowed binning modes. "
271 "This will override all other specification or default behavior.");
288 bool inPlace = (inputWS == outputWS);
292 const bool dist = inputWS->isDistribution();
293 const bool isHist = inputWS->isHistogramData();
296 const auto histnumber =
static_cast<int>(inputWS->getNumberHistograms());
304 inputWS->getXMinMax(xmin, xmax);
306 HistogramData::BinEdges XValues_new(0);
309 xmin, xmax, useReverseLog, power));
314 if (eventInputWS !=
nullptr) {
317 if (PreserveEvents) {
319 outputWS = inputWS->clone();
321 auto eventOutputWS = std::dynamic_pointer_cast<EventWorkspace>(outputWS);
324 eventOutputWS->setAllX(XValues_new);
327 g_log.
information() <<
"Creating a Workspace2D from the EventWorkspace " << eventInputWS->getName() <<
".\n";
328 outputWS = DataObjects::create<DataObjects::Workspace2D>(*inputWS, histnumber, XValues_new);
331 Progress prog(
this, 0.0, 1.0, histnumber);
333 bool useUnsortingHistogram = (rbParams.size() < 4) && !useReverseLog && power == 0.0;
334 g_log.
information() <<
"Generating histogram without sorting=" << useUnsortingHistogram <<
"\n";
338 for (
int i = 0; i < histnumber; ++i) {
341 const EventList &el = eventInputWS->getSpectrum(i);
344 if (useUnsortingHistogram)
345 el.generateHistogram(rbParams[1], XValues_new.rawData(), y_data, e_data);
347 el.generateHistogram(XValues_new.rawData(), y_data, e_data);
350 outputWS->mutableY(i) = y_data;
351 outputWS->mutableE(i) = e_data;
372 ChildAlg->initialize();
373 ChildAlg->setProperty(
"InputWorkspace", inputWS);
375 inputWS = ChildAlg->getProperty(
"OutputWorkspace");
380 outputWS = DataObjects::create<API::HistoWorkspace>(*inputWS, histnumber, XValues_new);
384 Progress prog(
this, 0.0, 1.0, histnumber);
386 for (
int hist = 0; hist < histnumber; ++hist) {
390 outputWS->setHistogram(hist, HistogramData::rebin(inputWS->histogram(hist), XValues_new));
391 }
catch (InvalidBinEdgesError &) {
393 outputWS->setBinEdges(hist, XValues_new);
401 outputWS->setDistribution(dist);
406 for (
int i = 0; i < histnumber; ++i) {
407 if (inputWS->hasMaskedBins(i))
416 ChildAlg->initialize();
419 outputWS = ChildAlg->getProperty(
"OutputWorkspace");
438 const int hist,
const bool ignoreErrors) {
448 auto it = mask.cbegin();
449 auto &XValues = inputWS->x(hist);
450 masked_bins.emplace_back(XValues[(*it).first]);
451 weights.emplace_back((*it).second);
452 masked_bins.emplace_back(XValues[(*it).first + 1]);
453 for (++it; it != mask.end(); ++it) {
454 const double currentX = XValues[(*it).first];
457 if (masked_bins.back() != currentX) {
458 weights.emplace_back(0.0);
459 masked_bins.emplace_back(currentX);
461 weights.emplace_back((*it).second);
462 masked_bins.emplace_back(XValues[(*it).first + 1]);
466 auto errSize = weights.size();
467 Histogram oldHist(BinEdges(std::move(masked_bins)), Frequencies(std::move(weights)),
468 FrequencyStandardDeviations(errSize, 0));
473 auto newHist = HistogramData::rebin(oldHist, outputWS->binEdges(hist));
474 auto &newWeights = newHist.y();
478 if (newWeights[
index] > 0.0)
479 outputWS->flagMasked(hist,
index, newWeights[
index]);
481 }
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.
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
int 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
@ Input
An input workspace.
@ Output
An output workspace.