16#include <gsl/gsl_bspline.h>
17#include <gsl/gsl_multifit.h>
18#include <gsl/gsl_statistics.h>
24using namespace Kernel;
28void SplineBackground::init() {
30 "The name of the input workspace.");
32 "The name to use for the output workspace.");
33 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
34 mustBePositive->setLower(0);
35 declareProperty(
"WorkspaceIndex", 0, mustBePositive,
"The index of the spectrum for fitting.");
37 declareProperty(
"EndWorkspaceIndex", 0, mustBePositive,
"The end index of the spectrum range for fitting.");
43void SplineBackground::exec() {
51 if (specEnd >=
static_cast<int>(inWS->getNumberHistograms()))
52 throw std::out_of_range(
"EndWorkspaceIndex is out of range.");
57 if (spec >=
static_cast<int>(inWS->getNumberHistograms()))
58 throw std::out_of_range(
"WorkspaceIndex is out of range.");
63 for (
int wsIndex = spec; wsIndex < (specEnd + 1); wsIndex++) {
67 if (numBins < ncoeffs) {
68 throw std::out_of_range(
"Too many basis functions (NCoeff)");
74 const auto &xVals = inWS->x(wsIndex);
75 setupSpline(xVals.front(), xVals.back(), numBins, ncoeffs);
102size_t SplineBackground::calculateNumBinsToProcess(
const API::MatrixWorkspace *ws,
const size_t currentWSIndex) {
103 const auto &yInputVals = ws->
y(currentWSIndex);
104 size_t ySize = yInputVals.size();
109 ySize -=
static_cast<int>(ws->
maskedBins(currentWSIndex).size());
122void SplineBackground::addWsDataToSpline(
const API::MatrixWorkspace *ws,
const size_t specNum,
int expectedNumBins) {
123 const auto xPointData = ws->
points(specNum);
124 const auto &yInputVals = ws->
y(specNum);
125 const auto &eInputVals = ws->
e(specNum);
129 std::vector<bool> masked(yInputVals.size(),
false);
131 const auto &maskedBinsMap = ws->
maskedBins(specNum);
132 for (
const auto &maskedBin : maskedBinsMap) {
133 masked[maskedBin.first] =
true;
137 int numUnmaskedBins = 0;
138 for (
size_t i = 0; i < yInputVals.size(); ++i) {
139 if (hasMaskedBins && masked[i])
148 if (expectedNumBins != numUnmaskedBins) {
150 throw std::runtime_error(
"Assertion failed: number of unmasked bins found was"
151 " not equal to the number that was calculated");
162void SplineBackground::allocateBSplinePointers(
int numBins,
int ncoeffs) {
164 const int nbreak = ncoeffs - (k - 2);
167 throw std::out_of_range(
"Too low NCoeff");
175 sp.
xData = gsl_vector_alloc(numBins);
176 sp.
yData = gsl_vector_alloc(numBins);
177 sp.
fittedWs = gsl_matrix_alloc(numBins, ncoeffs);
180 sp.
covariance = gsl_matrix_alloc(ncoeffs, ncoeffs);
193double SplineBackground::calculateBinWeight(
double errValue) {
194 double outBinWeight = -1;
195 if (errValue <= 0 || !std::isfinite(errValue)) {
199 if (
g_log.
is(Kernel::Logger::Priority::PRIO_WARNING)) {
201 g_log.
warning(
"Spline background found an error value of 0 or less on an unmasked"
202 " bin. This bin will have no weight during the fitting process");
205 g_log.
warning(
"Spline background found an error value of nan or inf on an"
206 " unmasked bin. This bin will have no weight during the fitting"
212 outBinWeight = 1. / (errValue * errValue);
220void SplineBackground::freeBSplinePointers() {
228 gsl_vector_free(sp.
xData);
230 gsl_vector_free(sp.
yData);
254 const size_t startWSIndex,
const size_t currentIndexOfInputWS) {
256 const auto &xInputVals = inputWS->x(currentIndexOfInputWS);
257 size_t currentIndexOfOutputWS = currentIndexOfInputWS - startWSIndex;
259 outputWS->getSpectrum(currentIndexOfOutputWS)
260 .setSpectrumNo(inputWS->getSpectrum(currentIndexOfInputWS).getSpectrumNo());
263 auto &yVals = outputWS->mutableY(currentIndexOfOutputWS);
264 auto &eVals = outputWS->mutableE(currentIndexOfOutputWS);
266 for (
size_t i = 0; i < inputWS->y(currentIndexOfInputWS).size(); i++) {
267 double xi = xInputVals[i];
274 outputWS->setSharedX(currentIndexOfOutputWS, inputWS->sharedX(currentIndexOfInputWS));
285void SplineBackground::setupSpline(
double xMin,
double xMax,
int numBins,
int ncoeff) {
290 for (
int i = 0; i < numBins; ++i) {
297 for (
int j = 0; j < ncoeff; ++j) {
#define DECLARE_ALGORITHM(classname)
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.
Base MatrixWorkspace Abstract Class.
const MaskList & maskedBins(const size_t &workspaceIndex) const
Returns the list of masked bins for a spectrum.
const HistogramData::HistogramE & e(const size_t index) const
HistogramData::Points points(const size_t index) const
bool hasMaskedBins(const size_t &workspaceIndex) const
Does this spectrum contain any masked bins.
const HistogramData::HistogramY & y(const size_t index) const
A property class for workspaces.
void addWsDataToSpline(const API::MatrixWorkspace *ws, const size_t specNum, int expectedNumBins)
Adds data from the workspace to the GSL vectors for later processing.
void allocateBSplinePointers(int numBins, int ncoeffs)
Allocates various pointers used within GSL.
void freeBSplinePointers()
Deallocates various pointers within GSL.
bSplinePointers m_splinePointers
void updateSplineOutput(const API::MatrixWorkspace_sptr &inputWS, API::MatrixWorkspace_sptr &outputWS, const size_t spec, const size_t wsIndex)
Gets the values from the fitted GSL, and creates a clone of input workspace with new values.
void setupSpline(double xMin, double xMax, int numBins, int ncoeff)
Sets up the splines for later fitting.
size_t calculateNumBinsToProcess(const API::MatrixWorkspace *ws, const size_t currentWSIndex)
Calculates the number on unmasked bins to process.
double calculateBinWeight(double errValue)
Calculates the bin weight using the error values in the WS.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void warning(const std::string &msg)
Logs at warning level.
bool is(int level) const
Returns true if at least the given log level is set.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
Struct holding various pointers required by GSL.
gsl_vector * coefficients
gsl_bspline_workspace * splineToProcess
gsl_multifit_linear_workspace * weightedLinearFitWs
gsl_vector * inputSplineWs
@ Input
An input workspace.
@ Output
An output workspace.