Mantid
Loading...
Searching...
No Matches
FFTDerivative.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
10#include "MantidHistogramData/Histogram.h"
11#include "MantidHistogramData/HistogramBuilder.h"
13
14#include <algorithm>
15#include <functional>
16
17using Mantid::HistogramData::HistogramX;
18using Mantid::HistogramData::HistogramY;
19
20namespace Mantid::Algorithms {
21
22// Register the algorithm into the AlgorithmFactory
23DECLARE_ALGORITHM(FFTDerivative)
24
25using namespace Mantid::Kernel;
26using namespace Mantid::API;
27using namespace Mantid::DataObjects;
28using namespace Mantid::HistogramData;
29
31 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input),
32 "Input workspace for differentiation");
33 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
34 "Workspace with result derivatives");
35 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
36 mustBePositive->setLower(1);
37 declareProperty("Order", 1, mustBePositive, "The order of the derivative");
38 // declareProperty("Transform",false,"Output the transform workspace");
39}
40
42
44 MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
46
47 size_t n = inWS->getNumberHistograms();
48 API::Progress progress(this, 0.0, 1.0, n);
49
50 size_t ny = inWS->y(0).size();
51 size_t nx = inWS->x(0).size();
52
53 // Workspace for holding a copy of a spectrum. Each spectrum is symmetrized to
54 // minimize
55 // possible edge effects.
56
57 HistogramBuilder builder;
58 builder.setX(nx + ny);
59 builder.setY(ny + ny);
60 builder.setDistribution(inWS->isDistribution());
61 MatrixWorkspace_sptr copyWS = create<MatrixWorkspace>(*inWS, 1, builder.build());
62
63 for (size_t spec = 0; spec < n; ++spec) {
64 symmetriseSpectrum(inWS->histogram(spec), copyWS->mutableX(0), copyWS->mutableY(0), nx, ny);
65
66 // Transform symmetrized spectrum
67 const bool isHisto = copyWS->isHistogramData();
68 auto fft = createChildAlgorithm("FFT");
69 fft->setProperty("InputWorkspace", copyWS);
70 fft->setProperty("Real", 0);
71 fft->setProperty("Transform", "Forward");
72 fft->execute();
73
74 MatrixWorkspace_sptr transWS = fft->getProperty("OutputWorkspace");
75
76 multiplyTransform(transWS->mutableX(3), transWS->mutableY(3), transWS->mutableY(4));
77
78 // Inverse transform
79 fft = createChildAlgorithm("FFT");
80 fft->setProperty("InputWorkspace", transWS);
81 fft->setProperty("Real", 3);
82 fft->setProperty("Imaginary", 4);
83 fft->setProperty("Transform", "Backward");
84 fft->execute();
85
86 transWS = fft->getProperty("OutputWorkspace");
87
88 // If the input was histogram data, convert the output to histogram data too
89 if (isHisto) {
90 auto toHisto = createChildAlgorithm("ConvertToHistogram");
91 toHisto->setProperty("InputWorkspace", transWS);
92 toHisto->execute();
93 transWS = toHisto->getProperty("OutputWorkspace");
94 }
95
96 if (!outWS) {
97 outWS = create<MatrixWorkspace>(*inWS);
98 }
99
100 // Save the upper half of the inverse transform for output
101 size_t m2 = transWS->y(0).size() / 2;
102 double dx = copyWS->x(0)[m2];
103
104 outWS->mutableX(spec).assign(transWS->x(0).cbegin() + m2, transWS->x(0).cend());
105 outWS->mutableX(spec) += dx;
106 outWS->mutableY(spec).assign(transWS->y(0).cbegin() + m2, transWS->y(0).cend());
107
108 progress.report();
109 }
110
111 setProperty("OutputWorkspace", outWS);
112}
113
114void FFTDerivative::symmetriseSpectrum(const HistogramData::Histogram &in, HistogramData::HistogramX &symX,
115 HistogramData::HistogramY &symY, const size_t nx, const size_t ny) {
116 const auto &inX = in.x();
117 const auto &inY = in.y();
118
119 const double xx = 2 * inX[0];
120
121 symX[ny] = inX[0];
122 symY[ny] = inY[0];
123
124 for (size_t i = 1; i < ny; ++i) {
125 size_t j1 = ny - i;
126 size_t j2 = ny + i;
127 symX[j1] = xx - inX[i];
128 symX[j2] = inX[i];
129 symY[j1] = symY[j2] = inY[i];
130 }
131
132 symX[0] = 2 * symX[1] - symX[2];
133 symY[0] = inY.back();
134
135 const bool isHist = (nx != ny);
136
137 if (isHist) {
138 symX[symY.size()] = inX[ny];
139 }
140}
141
150void FFTDerivative::multiplyTransform(const HistogramX &nu, HistogramY &re, HistogramY &im) {
151 int dn = getProperty("Order");
152 bool swap_re_im = dn % 2 != 0;
153 int sign_re = 1;
154 int sign_im = -1;
155 switch (dn % 4) {
156 case 1:
157 sign_re = 1;
158 sign_im = -1;
159 break;
160 case 2:
161 sign_re = -1;
162 sign_im = -1;
163 break;
164 case 3:
165 sign_re = -1;
166 sign_im = 1;
167 break;
168 }
169 // Multiply the transform by (2*pi*i*w)**dn
170 for (size_t j = 0; j < re.size(); ++j) {
171 double w = 2 * M_PI * nu[j];
172 double ww = w;
173 for (int k = dn; k > 1; --k) {
174 ww *= w;
175 }
176 double a = sign_re * re[j] * ww;
177 double b = sign_im * im[j] * ww;
178 if (swap_re_im) {
179 re[j] = b;
180 im[j] = a;
181 } else {
182 re[j] = a;
183 im[j] = b;
184 }
185 }
186}
187
188} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
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.
Definition: Algorithm.cpp:842
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
A property class for workspaces.
void symmetriseSpectrum(const HistogramData::Histogram &in, HistogramData::HistogramX &symX, HistogramData::HistogramY &symY, const size_t nx, const size_t ny)
void multiplyTransform(const HistogramData::HistogramX &nu, HistogramData::HistogramY &re, HistogramData::HistogramY &im)
A Fourier transform of a derivative of order n has a factor of i^n where i is the imaginary unit.
void init() override
Initialisation code.
void exec() override
Execution code.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54