15#include <boost/algorithm/string/detail/classification.hpp>
16#include <boost/algorithm/string/split.hpp>
23using namespace Kernel;
29 "The name of the input workspace.");
31 "The name of the output workspace.");
33 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
34 mustBePositive->setLower(0);
35 declareProperty(
"WorkspaceIndex", 0, mustBePositive,
"Workspace index for smoothing");
37 std::vector<std::string> type{
"Zeroing",
"Butterworth"};
38 declareProperty(
"Filter",
"Zeroing", std::make_shared<StringListValidator>(type),
"The type of the applied filter");
40 "The filter parameters:\n"
41 "For Zeroing, 1 parameter: 'n' - an integer greater than 1 "
42 "meaning that the Fourier coefficients with frequencies "
43 "outside the 1/n of the original range will be set to zero.\n"
44 "For Butterworth, 2 parameters: 'n' and 'order', giving the "
45 "1/n truncation and the smoothing order.\n");
48 "Ignores the requirement that X bins be linear and of the same size.\n"
49 "Set this to true if you are using log binning.\n"
50 "The output X axis will be the same as the input either way.");
67 send =
static_cast<int>(inWS->getNumberHistograms());
74 auto dn =
static_cast<int>(inWS->y(0).size());
80 for (
int spec = s0; spec < send; spec++) {
82 double x0 = inWS->x(spec)[0];
84 double dx = (inWS->x(spec).back() - inWS->x(spec).front()) / (
static_cast<double>(inWS->x(spec).size()) - 1.0);
88 auto &symX = symmWS->mutableX(0);
89 auto &symY = symmWS->mutableY(0);
91 for (
int i = 0; i < dn; i++) {
92 symX[dn + i] = inWS->x(spec)[i];
93 symY[dn + i] = inWS->y(spec)[i];
95 symX[dn - i] = x0 - dx * i;
96 symY[dn - i] = inWS->y(spec)[i];
98 symY.front() = inWS->y(spec).back();
99 symX.front() = x0 - dx * dn;
100 if (inWS->isHistogramData())
101 symX.back() = inWS->x(spec).back();
108 fft->setProperty(
"InputWorkspace", symmWS);
109 fft->setProperty(
"WorkspaceIndex", 0);
110 fft->setProperty(
"IgnoreXBins", ignoreXBins);
124 if (type ==
"Zeroing") {
132 throw std::invalid_argument(
"Truncation parameter must be an integer > 1");
136 zero(
n, unfilteredWS, filteredWS);
137 }
else if (type ==
"Butterworth") {
141 std::vector<std::string> params;
142 boost::split(params, string_params, boost::algorithm::detail::is_any_ofF<char>(
" ,:;\t"));
143 if (params.size() != 2) {
147 std::string param0 = params.at(0);
148 std::string param1 = params.at(1);
149 n = std::stoi(param0);
150 order = std::stoi(param1);
153 throw std::invalid_argument(
"Truncation parameter must be an integer > 1");
155 throw std::invalid_argument(
"Butterworth filter order must be an integer >= 1");
157 progress.report(
"ButterWorth Filter");
161 progress.report(
"Backward Transformation");
164 fft->setProperty(
"InputWorkspace", filteredWS);
165 fft->setProperty(
"Transform",
"Backward");
166 fft->setProperty(
"IgnoreXBins", ignoreXBins);
170 g_log.
error(
"Error in inverse FFT algorithm");
178 dn =
static_cast<int>(tmpWS->blocksize()) / 2;
181 outWS->setSharedX(spec, inWS->sharedX(spec));
182 outWS->mutableY(spec).assign(tmpWS->y(0).cbegin() + dn, tmpWS->y(0).cend());
184 outWS->setSharedX(0, inWS->sharedX(spec));
185 outWS->mutableY(0).assign(tmpWS->y(0).cbegin() + dn, tmpWS->y(0).cend());
199 auto mx =
static_cast<int>(unfilteredWS->x(0).size());
200 auto my =
static_cast<int>(unfilteredWS->y(0).size());
208 filteredWS->setSharedX(0, unfilteredWS->sharedX(0));
209 filteredWS->setSharedX(1, unfilteredWS->sharedX(0));
211 std::copy(unfilteredWS->y(0).cbegin(), unfilteredWS->y(0).begin() + ny, filteredWS->mutableY(0).begin());
213 std::copy(unfilteredWS->y(1).cbegin(), unfilteredWS->y(1).begin() + ny, filteredWS->mutableY(1).begin());
231 auto mx =
static_cast<int>(unfilteredWS->x(0).size());
232 auto my =
static_cast<int>(unfilteredWS->y(0).size());
240 filteredWS->setSharedX(0, unfilteredWS->sharedX(0));
241 filteredWS->setSharedX(1, unfilteredWS->sharedX(0));
243 auto &Yr = unfilteredWS->y(0);
244 auto &Yi = unfilteredWS->y(1);
245 auto &yr = filteredWS->mutableY(0);
246 auto &yi = filteredWS->mutableY(1);
250 for (
int i = 0; i < my; i++) {
251 double scale = 1.0 / (1.0 + pow(
static_cast<double>(i) / cutoff, 2 * order));
252 yr[i] = scale * Yr[i];
253 yi[i] = scale * Yi[i];
#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.
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.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Helper class for reporting progress from algorithms.
A property class for workspaces.
void exec() override
Executes the algorithm.
void init() override
Initialisation method. Declares properties to be used in algorithm.
void zero(int n, API::MatrixWorkspace_sptr &unfilteredWS, API::MatrixWorkspace_sptr &filteredWS)
Smoothing by zeroing.
void Butterworth(int n, int order, API::MatrixWorkspace_sptr &unfilteredWS, API::MatrixWorkspace_sptr &filteredWS)
Smoothing using Butterworth filter.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void error(const std::string &msg)
Logs at error level.
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
@ Input
An input workspace.
@ Output
An output workspace.