22using namespace DataObjects;
23using namespace Kernel;
24using HistogramData::BinEdges;
27using std::stringstream;
48 "An output workspace.");
51 "A comma separated list of the XMin for every spectrum. (Optional)");
53 "A comma separated list of the XMax for every spectrum. (Optional)");
55 auto min = std::make_shared<BoundedValidator<int>>();
57 declareProperty(
"NumberBins", 0, min,
"Number of bins to split up each spectrum into.");
58 declareProperty(
"LogBinning",
false,
"Use logarithmic binning. If false use constant step sizes.");
61 "Keep the output workspace as an EventWorkspace, if the "
62 "input has events (default).\n"
63 "If the input and output EventWorkspace names are the same, "
64 "only the X bins are set, which is very quick.\n"
65 "If false, then the workspace gets converted to a "
66 "Workspace2D histogram.");
73 map<string, string> errors;
76 if ((!xmins.empty()) && (!xmaxs.empty())) {
77 if (xmins.size() != xmaxs.size()) {
79 msg <<
"XMin and XMax do not define same number of spectra (" << xmins.size() <<
" != " << xmaxs.size() <<
")";
80 errors.emplace(
"XMax", msg.str());
82 size_t size = xmins.size();
83 for (
size_t i = 0; i < size; ++i) {
84 if (xmins[i] >= xmaxs[i]) {
86 msg <<
"XMin (" << xmins[i] <<
") cannot be greater than XMax (" << xmaxs[i] <<
")";
87 errors.emplace(
"XMax", msg.str());
109 const size_t numSpectra = inputWS->getNumberHistograms();
112 if (xmins.size() == 1 && numSpectra > xmins.size()) {
113 const double value = xmins.front();
114 xmins.insert(xmins.end(), numSpectra - xmins.size(),
value);
116 if (xmaxs.size() == 1 && numSpectra > xmaxs.size()) {
117 const double value = xmaxs.front();
118 xmaxs.insert(xmaxs.end(), numSpectra - xmaxs.size(),
value);
122 const bool updateXMins = xmins.empty();
123 const bool updateXMaxs = xmaxs.empty();
128 double xmin_wksp = inputWS->getXMin();
129 double xmax_wksp = inputWS->getXMax();
131 if (inputEventWS !=
nullptr && inputEventWS->getNumberEvents() > 0) {
132 xmin_wksp = inputEventWS->getTofMin();
133 xmax_wksp = inputEventWS->getTofMax();
136 for (
size_t i = 0; i < numSpectra; ++i) {
138 if (updateXMins || updateXMaxs) {
139 const auto &xvalues = inputWS->x(i);
141 const auto minimum = xvalues.front();
142 if (std::isnan(minimum) || minimum >= xmax_wksp) {
143 xmins.emplace_back(xmin_wksp);
145 xmins.emplace_back(minimum);
149 const auto maximum = xvalues.back();
150 if (std::isnan(maximum) || maximum <= xmin_wksp) {
151 xmaxs.emplace_back(xmax_wksp);
153 xmaxs.emplace_back(maximum);
159 if (xmins[i] >= xmaxs[i]) {
160 if (!msg.str().empty())
162 msg <<
"at wksp_index=" << i <<
" XMin >= XMax (" << xmins[i] <<
" >= " << xmaxs[i] <<
")";
195 size_t numBoundaries(0);
199 reqNumBoundaries -= 1;
201 expNumBoundaries += 1;
203 vector<double> params;
204 params.emplace_back(xmin);
205 params.emplace_back(0.);
206 params.emplace_back(xmax);
211 throw std::invalid_argument(
"Cannot calculate log of xmin=0");
213 throw std::invalid_argument(
"Cannot calculate log of xmax=0");
214 if (xmin < 0. && xmax > 0.) {
215 std::stringstream msg;
216 msg <<
"Cannot calculate logorithmic binning that changes sign (xmin=" << xmin <<
", xmax=" << xmax <<
")";
217 throw std::invalid_argument(msg.str());
220 const int MAX_ITER(100);
223 double delta = (log(xmax) - log(xmin)) /
static_cast<double>(
m_numBins);
226 for (
int numIter = 0; numIter < MAX_ITER; ++numIter) {
227 params[1] = -1. *
delta;
229 params[2] = xmax +
delta;
232 if (numBoundaries == expNumBoundaries) {
233 double diff = (xmax - xValues.back());
235 g_log.
debug() <<
"Didn't get the exact xmax value: [xmax - xValues.back()=" << diff
236 <<
"] [relative diff = " <<
fabs(100. * diff / xmax) <<
"%]\n";
237 g_log.
debug() <<
"Resetting final x-value to xmax\n";
238 *(xValues.rbegin()) = xmax;
241 }
else if (numBoundaries > expNumBoundaries)
243 delta *= (1. + shift);
249 delta *= (1. - shift);
256 params[1] = (xmax - xmin) /
static_cast<double>(reqNumBoundaries);
260 if (numBoundaries != expNumBoundaries) {
261 g_log.
warning() <<
"Did not generate the requested number of bins: generated " << numBoundaries <<
" requested "
262 << expNumBoundaries <<
"(xmin=" << xmin <<
", xmax=" << xmax <<
")\n";
276 bool inPlace = (inputWS == outputWS);
279 const auto numSpectra =
static_cast<int>(inputWS->getNumberHistograms());
291 throw std::runtime_error(
error);
293 bool common_limits =
true;
295 double xmin_common = xmins[0];
296 double xmax_common = xmaxs[0];
297 for (
size_t i = 1; i < xmins.size(); ++i) {
298 if (xmins[i] != xmin_common) {
299 common_limits =
false;
302 if (xmaxs[i] != xmax_common) {
303 common_limits =
false;
309 g_log.
debug() <<
"Common limits between all spectra\n";
311 g_log.
debug() <<
"Does not have common limits between all spectra\n";
316 if (inputEventWS !=
nullptr) {
319 g_log.
debug() <<
"Rebinning event workspace in place\n";
321 g_log.
debug() <<
"Rebinning event workspace out of place\n";
322 outputWS = inputWS->clone();
324 auto outputEventWS = std::dynamic_pointer_cast<EventWorkspace>(outputWS);
328 std::vector<double> xAxisTmp;
330 BinEdges xValues(std::move(xAxisTmp));
332 outputEventWS->setAllX(xValues);
335 Progress prog(
this, 0.0, 1.0, numSpectra);
339 for (
int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
341 std::vector<double> xAxisTmp;
343 BinEdges xValues(std::move(xAxisTmp));
344 g_log.
debug() <<
"delta[wkspindex=" << wkspIndex <<
"] = " <<
delta <<
" xmin=" << xmins[wkspIndex]
345 <<
" xmax=" << xmaxs[wkspIndex] <<
"\n";
346 outputEventWS->setHistogram(wkspIndex, xValues);
356 g_log.
information() <<
"Creating a Workspace2D from the EventWorkspace " << inputEventWS->getName() <<
".\n";
357 outputWS = create<DataObjects::Workspace2D>(*inputWS, numSpectra, HistogramData::BinEdges(
m_numBins + 1));
360 Progress prog(
this, 0.0, 1.0, numSpectra);
364 for (
int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
370 g_log.
debug() <<
"delta[wkspindex=" << wkspIndex <<
"] = " <<
delta <<
"\n";
371 outputWS->setBinEdges(wkspIndex, xValues);
374 const EventList &el = inputEventWS->getSpectrum(wkspIndex);
380 outputWS->mutableY(wkspIndex) = y_data;
381 outputWS->mutableE(wkspIndex) = e_data;
390 for (
int i = 1; i < inputWS->axes(); i++) {
391 outputWS->replaceAxis(i, std::unique_ptr<Axis>(inputWS->getAxis(i)->clone(outputWS.get())));
392 outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
396 for (
int i = 0; i < outputWS->axes(); ++i) {
397 outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
399 outputWS->setYUnit(inputEventWS->YUnit());
400 outputWS->setYUnitLabel(inputEventWS->YUnitLabel());
411 ChildAlg->initialize();
412 ChildAlg->setProperty(
"InputWorkspace", inputWS);
414 inputWS = ChildAlg->getProperty(
"OutputWorkspace");
422 if (inputWS->axes() > 1)
423 outputWS->replaceAxis(1, std::unique_ptr<Axis>(inputWS->getAxis(1)->clone(outputWS.get())));
425 Progress prog(
this, 0.0, 1.0, numSpectra);
427 for (
int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
430 Mantid::HistogramData::HistogramX
const &XValues = inputWS->x(wkspIndex);
431 Mantid::HistogramData::HistogramY
const &YValues = inputWS->y(wkspIndex);
432 Mantid::HistogramData::HistogramE
const &YErrors = inputWS->e(wkspIndex);
435 std::span<double>
const YValues_new{outputWS->mutableY(wkspIndex)};
436 std::span<double>
const YErrors_new{outputWS->mutableE(wkspIndex)};
441 g_log.
debug() <<
"delta[wkspindex=" << wkspIndex <<
"] = " <<
delta <<
"\n";
446 }
catch (std::exception &ex) {
447 g_log.
error() <<
"Error in rebin function: " << ex.what() <<
'\n';
452 outputWS->setBinEdges(wkspIndex, XValues_new);
463 for (
int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
464 if (inputWS->hasMaskedBins(wkspIndex))
470 for (
int i = 0; i < outputWS->axes(); ++i) {
471 outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
477 ChildAlg->initialize();
480 outputWS = ChildAlg->getProperty(
"OutputWorkspace");
#define DECLARE_ALGORITHM(classname)
double value
The value of the point.
#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.
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.
Helper class for reporting progress from algorithms.
A property class for workspaces.
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...
ResampleX : TODO: DESCRIPTION.
void setOptions(const int numBins, const bool useLogBins, const bool isDist)
MADE PUBLIC FOR TESTING ONLY - DO NOT USE.
void exec() override
Execute the algorithm.
const std::string name() const override
Algorithm's name for identification.
std::map< std::string, std::string > validateInputs() override
More complicated checks of parameters and their relations.
const std::string alias() const override
Algorithm's aliases.
double determineBinning(MantidVec &xValues, const double xmin, const double xmax)
MADE PUBLIC FOR TESTING ONLY - DO NOT USE.
void init() override
Initialize the algorithm's properties.
int version() const override
Algorithm's version for identification.
void generateHistogram(std::span< double const > X, MantidVec &Y, MantidVec &E, bool skipError=false) const override
Generates both the Y and E (error) histograms w.r.t TOF for an EventList with or without WeightedEven...
Support for a property that holds an array of values.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
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.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
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
Kernel::Logger g_log("DetermineSpinStateOrder")
string determineXMinMax(const MatrixWorkspace_sptr &inputWS, vector< double > &xmins, vector< double > &xmaxs)
Determine the min and max x-values for each spectrum and error check the pairs.
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
void MANTID_KERNEL_DLL rebin(std::span< double const > xold, std::span< double const > yold, std::span< double const > eold, std::span< double const > xnew, std::span< double > ynew, std::span< double > enew, bool distribution, bool addition=false)
The input and output ranges are taken as spans so that the size-checked histogram data types,...
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.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
@ Input
An input workspace.
@ Output
An output workspace.