Mantid
Loading...
Searching...
No Matches
EstimateScatteringVolumeCentreOfMass.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2025 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 "MantidAPI/Run.h"
11#include "MantidAPI/Sample.h"
18#include "MantidKernel/V3D.h"
19#include <unordered_map>
20
21namespace Mantid::Algorithms {
22
23using namespace API;
24using namespace Geometry;
25using namespace Kernel;
26
27namespace {
28const std::string UNIT_M = "m";
29const std::string UNIT_CM = "cm";
30const std::string UNIT_MM = "mm";
31static const std::unordered_map<std::string, double> unitToMeters{{UNIT_M, 1.0}, {UNIT_CM, 0.01}, {UNIT_MM, 0.001}};
32} // namespace
33
34// Register the algorithm into the AlgorithmFactory
35DECLARE_ALGORITHM(EstimateScatteringVolumeCentreOfMass)
36
39
41
42 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input,
43 std::make_shared<InstrumentValidator>()),
44 "Input Workspace");
45 declareProperty(std::make_unique<PropertyWithValue<std::vector<double>>>("CentreOfMass", V3D(), Direction::Output),
46 "Estimated centre of mass of illuminated sample volume");
47
48 auto moreThanZero = std::make_shared<BoundedValidator<double>>();
49 moreThanZero->setLower(1e-6);
50 declareProperty("ElementSize", 1.0, moreThanZero,
51 "The size of one side of an integration element cube in {ElementUnits}");
52
53 declareProperty("ElementUnits", UNIT_MM,
54 std::make_shared<StringListValidator>(std::vector<std::string>{UNIT_M, UNIT_CM, UNIT_MM}),
55 "The units which ElementSize has been provided in");
56}
57
59 // Retrieve the input workspace
60 m_inputWS = getProperty("InputWorkspace");
61 // Cache the beam direction
62 const V3D beamDirection = m_inputWS->getInstrument()->getBeamDirection();
63 // Calculate the element size
64 m_cubeSide = getProperty("ElementSize"); // in units
65 const std::string elementUnits = getProperty("ElementUnits");
66
67 auto it = unitToMeters.find(elementUnits);
68 if (it == unitToMeters.end()) {
69 throw std::invalid_argument("Supported units for ElementUnits are (m, cm, mm), not: " + elementUnits);
70 }
71 m_cubeSide *= it->second; // now in m
72
73 // Retrieve the Sample Shape Geometry
74 const Geometry::IObject_sptr sampleObject = extractValidSampleObject(m_inputWS->mutableSample());
75
76 // Retrieve the illumination volume (we assume the sample is fully illuminated hence the volume is the same as the
77 // sample, unless a Gauge Volume has been defined)
78 //
79 // NB: here we expect the gauge volume object to be the illumination volume in the lab frame, as such,
80 // it is not required to be wholly within the sample shape (this will likely be the main use case for this alg)
81 const Geometry::IObject_sptr integrationVolume =
82 m_inputWS->run().hasProperty("GaugeVolume") ? getGaugeVolumeObject() : sampleObject;
83
84 const V3D averagePos =
85 rasterizeGaugeVolumeAndCalculateMeanElementPosition(beamDirection, integrationVolume, sampleObject);
86 setProperty("CentreOfMass", std::vector<double>(averagePos));
87}
88
92 const V3D beamDirection, const Geometry::IObject_sptr integrationVolume,
93 const Geometry::IObject_sptr sampleObject) {
94 const auto raster = Geometry::Rasterize::calculate(beamDirection, *integrationVolume, *sampleObject, m_cubeSide);
95 if (raster.l1.size() == 0) {
96 // most errors should be caught by the rasterise function, but just in case
97 const std::string mess("Failed to find any points in the rasterized illumination volume within the sample shape - "
98 "Check sample shape and gauge volume are defined correctly or try reducing the ElementSize");
99 g_log.error(mess);
100 throw std::runtime_error(mess);
101 }
102 // calculate mean element position
103 const V3D meanPos = calcAveragePosition(raster.position);
104 return meanPos;
105}
106
109 // Check there is one, and fail if not
110 if (!sample.getShape().hasValidShape()) {
111 const std::string mess("No shape has been defined for the sample in the input workspace");
112 g_log.error(mess);
113 throw std::invalid_argument(mess);
114 } else {
115 g_log.information("Successfully extracted the sample object");
116 return sample.getShapePtr();
117 }
118}
119
121 g_log.information("Calculating scattering within the gauge volume defined on "
122 "the input workspace");
123
124 // Retrieve and create the gauge volume shape
125 const Geometry::IObject_sptr volume =
126 ShapeFactory().createShape(m_inputWS->run().getProperty("GaugeVolume")->value());
127
128 return volume;
129}
130
132 if (!pos.empty()) {
133 V3D sum = std::accumulate(pos.begin(), pos.end(), V3D(0.0, 0.0, 0.0));
134 sum /= static_cast<double>(pos.size());
135 return sum;
136 } else {
137 // shouldn't be able to reach this point anyway
138 const std::string mess("No intersection points found between illumination volume and sample shape - "
139 "Check sample shape and gauge volume are defined correctly or try reducing the ElementSize");
140 g_log.error(mess);
141 throw std::runtime_error(mess);
142 }
143}
144
145} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
Base class from which all concrete algorithm classes should be derived.
Definition Algorithm.h:76
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.
Kernel::Logger & g_log
Definition Algorithm.h:422
This class stores information about the sample used in particular run.
Definition Sample.h:33
const Geometry::IObject & getShape() const
Return the sample shape.
Definition Sample.cpp:101
const Geometry::IObject_sptr getShapePtr() const
Return a pointer to the sample shape.
Definition Sample.cpp:109
A property class for workspaces.
const Geometry::IObject_sptr extractValidSampleObject(const API::Sample &sample)
Create the sample object using the Geometry classes, or use the existing one.
const Kernel::V3D rasterizeGaugeVolumeAndCalculateMeanElementPosition(const Kernel::V3D beamDirection, const Geometry::IObject_sptr integrationVolume, const Geometry::IObject_sptr sampleObject)
Calculate as raster of the illumination volume, evaluating which points are within the sample geometr...
const Kernel::V3D calcAveragePosition(const std::vector< Kernel::V3D > &pos)
API::MatrixWorkspace_sptr m_inputWS
A pointer to the input workspace.
virtual bool hasValidShape() const =0
Class originally intended to be used with the DataHandling 'LoadInstrument' algorithm.
std::shared_ptr< CSGObject > createShape(Poco::XML::Element *pElem)
Creates a geometric object from a DOM-element-node pointing to an element whose child nodes contain t...
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.
Definition Logger.cpp:108
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
The concrete, templated class for properties.
Class for 3D vectors.
Definition V3D.h:34
MANTID_GEOMETRY_DLL Raster calculate(const Kernel::V3D &beamDirection, const IObject &integShape, const IObject &sampleShape, const double cubeSizeInMetre)
std::shared_ptr< IObject > IObject_sptr
Typdef for a shared pointer.
Definition IObject.h:93
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54