19#include <boost/math/special_functions/round.hpp>
40 "An input Sample MDHistoWorkspace or MDEventWorkspace in HKL.");
41 declareProperty(
"DeltaHKL", 0.5,
"Distance from integer HKL to integrate peak.");
42 declareProperty(
"GridPoints", 201,
"Number of grid points for each dimension of HKL box.");
43 declareProperty(
"NeighborPoints", 10,
44 "Number of points in 5^3 surrounding "
45 "points above intensity threshold for "
46 "point to be part of peak.");
47 auto fluxValidator = std::make_shared<CompositeValidator>();
51 auto solidAngleValidator = fluxValidator->
clone();
55 "An optional input workspace containing momentum dependent flux for "
59 "An optional input workspace containing momentum integrated "
60 "vanadium for normalization "
61 "(a measure of the solid angle).");
64 "A PeaksWorkspace containing the peaks to integrate.");
67 "The output PeaksWorkspace will be a copy of the input PeaksWorkspace "
68 "with the peaks' integrated intensities.");
70 "Optional:Inner radius to use to evaluate the background of the peak.\n"
71 "If omitted background is region of HKL box - peak. ");
74 "Optional:Outer radius to use to evaluate the background of the peak.\n"
75 "The signal density around the peak (BackgroundInnerRadius < r < "
76 "BackgroundOuterRadius) is used to estimate the background under the "
78 "If omitted background is region of HKL box - peak.");
88 boost::optional<Mantid::Kernel::SpecialCoordinateSystem> coordinateSystem = converter(m_inputWS.get());
90 std::stringstream errmsg;
91 errmsg <<
"Input MDWorkspace's coordinate system is not HKL.";
92 throw std::invalid_argument(errmsg.str());
99 const int neighborPts =
getProperty(
"NeighborPoints");
102 if (peakWS != inPeakWS)
103 peakWS = inPeakWS->clone();
110 int npeaks = peakWS->getNumberPeaks();
112 auto prog = std::make_unique<Progress>(
this, 0.3, 1.0, npeaks);
114 for (
int i = 0; i < npeaks; i++) {
117 IPeak &p = peakWS->getPeak(i);
119 int h =
static_cast<int>(boost::math::iround(p.getH()));
120 int k =
static_cast<int>(boost::math::iround(p.getK()));
121 int l =
static_cast<int>(boost::math::iround(p.getL()));
124 histoBox =
cropHisto(h, k, l, box, m_histoWS);
125 }
else if (sa && flux) {
126 histoBox =
normalize(h, k, l, box, gridPts, flux, sa, m_eventWS);
128 histoBox =
binEvent(h, k, l, box, gridPts, m_eventWS);
130 double intensity = 0.0;
131 double errorSquared = 0.0;
132 integratePeak(neighborPts, histoBox, intensity, errorSquared);
133 p.setIntensity(intensity);
134 p.setSigmaIntensity(sqrt(errorSquared));
147 normAlg->setProperty(
"InputWorkspace", ws);
148 normAlg->setProperty(
"AlignedDim0",
"[H,0,0]," + boost::lexical_cast<std::string>(h - box) +
"," +
149 boost::lexical_cast<std::string>(h + box) +
"," +
std::to_string(gridPts));
150 normAlg->setProperty(
"AlignedDim1",
"[0,K,0]," + boost::lexical_cast<std::string>(k - box) +
"," +
151 boost::lexical_cast<std::string>(k + box) +
"," +
std::to_string(gridPts));
152 normAlg->setProperty(
"AlignedDim2",
"[0,0,L]," + boost::lexical_cast<std::string>(l - box) +
"," +
153 boost::lexical_cast<std::string>(l + box) +
"," +
std::to_string(gridPts));
154 normAlg->setProperty(
"FluxWorkspace", flux);
155 normAlg->setProperty(
"SolidAngleWorkspace", sa);
156 normAlg->setProperty(
"OutputWorkspace",
"mdout");
157 normAlg->setProperty(
"OutputNormalizationWorkspace",
"mdnorm");
158 normAlg->executeAsChildAlg();
160 Workspace_sptr mdnorm = normAlg->getProperty(
"OutputNormalizationWorkspace");
163 alg->setProperty(
"LHSWorkspace", mdout);
164 alg->setProperty(
"RHSWorkspace", mdnorm);
165 alg->setPropertyValue(
"OutputWorkspace",
"out");
168 return std::dynamic_pointer_cast<MDHistoWorkspace>(out);
172 double &errorSquared) {
173 std::vector<int> gridPts;
175 double BackgroundOuterRadius2 =
getProperty(
"BackgroundOuterRadius");
176 if (BackgroundOuterRadius2 !=
EMPTY_DBL())
177 BackgroundOuterRadius2 = pow(BackgroundOuterRadius2, 2.0);
179 double BackgroundInnerRadius2 =
getProperty(
"BackgroundInnerRadius");
180 if (BackgroundInnerRadius2 !=
EMPTY_DBL())
181 BackgroundInnerRadius2 = pow(BackgroundInnerRadius2, 2.0);
182 const size_t dimensionality = out->getNumDims();
183 for (
size_t i = 0; i < dimensionality; ++i) {
184 gridPts.emplace_back(
static_cast<int>(out->getDimension(i)->getNBins()));
187 const auto F = out->getSignalArray();
189 double Fmin = std::numeric_limits<double>::max();
190 for (
int i = 0; i < gridPts[0] * gridPts[1] * gridPts[2]; i++) {
191 if (std::isnormal(F[i])) {
192 Fmin = std::min(Fmin, F[i]);
193 Fmax = std::max(Fmax, F[i]);
196 const auto SqError = out->getErrorSquaredArray();
198 double minIntensity = Fmin + 0.01 * (Fmax - Fmin);
199 int measuredPoints = 0;
201 double peakSum = 0.0;
202 double measuredSum = 0.0;
203 double errSqSum = 0.0;
204 double measuredErrSqSum = 0.0;
205 int backgroundPoints = 0;
206 double backgroundSum = 0.0;
207 double backgroundErrSqSum = 0.0;
208 double Hcenter = gridPts[0] * 0.5;
209 double Kcenter = gridPts[1] * 0.5;
210 double Lcenter = gridPts[2] * 0.5;
212 for (
int Hindex = 0; Hindex < gridPts[0]; Hindex++) {
213 for (
int Kindex = 0; Kindex < gridPts[1]; Kindex++) {
214 for (
int Lindex = 0; Lindex < gridPts[2]; Lindex++) {
215 int iHKL = Hindex + gridPts[0] * (Kindex + gridPts[1] * Lindex);
216 if (BackgroundOuterRadius2 !=
EMPTY_DBL()) {
217 double radius2 = pow((
double(Hindex) - Hcenter) / gridPts[0], 2) +
218 pow((
double(Kindex) - Kcenter) / gridPts[1], 2) +
219 pow((
double(Lindex) - Lcenter) / gridPts[2], 2);
220 if (radius2 < BackgroundOuterRadius2 && BackgroundInnerRadius2 < radius2) {
221 backgroundPoints = backgroundPoints + 1;
222 backgroundSum = backgroundSum + F[iHKL];
223 backgroundErrSqSum = backgroundErrSqSum + SqError[iHKL];
226 if (std::isfinite(F[iHKL])) {
227 measuredPoints = measuredPoints + 1;
228 measuredSum = measuredSum + F[iHKL];
229 measuredErrSqSum = measuredErrSqSum + SqError[iHKL];
230 if (F[iHKL] > minIntensity) {
231 int neighborPoints = 0;
232 for (
int Hj = -2; Hj < 3; Hj++) {
233 for (
int Kj = -2; Kj < 3; Kj++) {
234 for (
int Lj = -2; Lj < 3; Lj++) {
235 int jHKL = Hindex + Hj + gridPts[0] * (Kindex + Kj + gridPts[1] * (Lindex + Lj));
236 if (Lindex + Lj >= 0 && Lindex + Lj < gridPts[2] && Kindex + Kj >= 0 && Kindex + Kj < gridPts[1] &&
237 Hindex + Hj >= 0 && Hindex + Hj < gridPts[0] && F[jHKL] > minIntensity) {
238 neighborPoints = neighborPoints + 1;
243 if (neighborPoints >= neighborPts) {
244 peakPoints = peakPoints + 1;
245 peakSum = peakSum + F[iHKL];
246 errSqSum = errSqSum + SqError[iHKL];
250 double minR = sqrt(std::pow(
float(Hindex) /
float(gridPts[0]) - 0.5, 2) +
251 std::pow(
float(Kindex) /
float(gridPts[1]) - 0.5, 2) +
252 std::pow(
float(Lindex) /
float(gridPts[0]) - 0.5, 2));
262 if (BackgroundOuterRadius2 !=
EMPTY_DBL()) {
264 if (backgroundPoints > 0) {
265 ratio = float(peakPoints) / float(backgroundPoints);
267 intensity = peakSum - ratio * (backgroundSum);
268 errorSquared = errSqSum + ratio * ratio * (backgroundErrSqSum);
270 double ratio = float(peakPoints) / float(measuredPoints - peakPoints);
271 intensity = peakSum - ratio * (measuredSum - peakSum);
272 errorSquared = errSqSum + ratio * ratio * (measuredErrSqSum - errSqSum);
285 binMD->setProperty(
"InputWorkspace", ws);
286 binMD->setProperty(
"AlignedDim0",
"[H,0,0]," + boost::lexical_cast<std::string>(h - box) +
"," +
287 boost::lexical_cast<std::string>(h + box) +
"," +
std::to_string(gridPts));
288 binMD->setProperty(
"AlignedDim1",
"[0,K,0]," + boost::lexical_cast<std::string>(k - box) +
"," +
289 boost::lexical_cast<std::string>(k + box) +
"," +
std::to_string(gridPts));
290 binMD->setProperty(
"AlignedDim2",
"[0,0,L]," + boost::lexical_cast<std::string>(l - box) +
"," +
291 boost::lexical_cast<std::string>(l + box) +
"," +
std::to_string(gridPts));
292 binMD->setPropertyValue(
"AxisAligned",
"1");
293 binMD->setPropertyValue(
"OutputWorkspace",
"out");
294 binMD->executeAsChildAlg();
296 return std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
306 cropMD->setProperty(
"InputWorkspace", ws);
308 cropMD->setProperty(
"P1Bin",
309 boost::lexical_cast<std::string>(h - box) +
",0," + boost::lexical_cast<std::string>(h + box));
310 cropMD->setProperty(
"P2Bin",
311 boost::lexical_cast<std::string>(k - box) +
",0," + boost::lexical_cast<std::string>(k + box));
312 cropMD->setProperty(
"P3Bin",
313 boost::lexical_cast<std::string>(l - box) +
",0," + boost::lexical_cast<std::string>(l + box));
315 cropMD->setPropertyValue(
"OutputWorkspace",
"out");
316 cropMD->executeAsChildAlg();
318 return std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
#define DECLARE_ALGORITHM(classname)
#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.
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.
A validator which provides a TENTATIVE check that a workspace contains common bins in each spectrum.
Kernel::IValidator_sptr clone() const override
Clone the current state.
A validator which checks that a workspace has a valid instrument.
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
MDFrameFromMDWorkspace: Each dimension of the MDWorkspace contains an MDFrame.
Structure describing a single-crystal peak.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
The concrete, templated class for properties.
Integrate single-crystal peaks in reciprocal-space.
DataObjects::MDHistoWorkspace_sptr normalize(int h, int k, int l, double box, int gridPts, const API::MatrixWorkspace_sptr &flux, const API::MatrixWorkspace_sptr &sa, const API::IMDEventWorkspace_sptr &ws)
DataObjects::MDHistoWorkspace_sptr cropHisto(int h, int k, int l, double box, const API::IMDWorkspace_sptr &ws)
Runs the BinMD algorithm on the input to provide the output workspace All slicing algorithm propertie...
DataObjects::MDHistoWorkspace_sptr binEvent(int h, int k, int l, double box, int gridPts, const API::IMDWorkspace_sptr &ws)
Runs the BinMD algorithm on the input to provide the output workspace All slicing algorithm propertie...
void integratePeak(const int neighborPts, const DataObjects::MDHistoWorkspace_sptr &out, double &intensity, double &errorSquared)
void exec() override
Run the algorithm.
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< IMDHistoWorkspace > IMDHistoWorkspace_sptr
shared pointer to Mantid::API::IMDHistoWorkspace
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< MDHistoWorkspace > MDHistoWorkspace_sptr
A shared pointer to a MDHistoWorkspace.
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
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.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
std::string to_string(const wide_integer< Bits, Signed > &n)
Describes the direction (within an algorithm) of a Property.
@ Input
An input workspace.
@ Output
An output workspace.