Mantid
Loading...
Searching...
No Matches
PeaksIntersection.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 +
13
14#include <boost/function.hpp>
15
16using namespace Mantid::API;
17using namespace Mantid::Geometry;
18using namespace Mantid::Kernel;
22
23namespace Mantid::Crystal {
24std::string PeaksIntersection::detectorSpaceFrame() { return "Detector space"; }
25
26std::string PeaksIntersection::qLabFrame() { return "Q (lab frame)"; }
27
28std::string PeaksIntersection::qSampleFrame() { return "Q (sample frame)"; }
29
30std::string PeaksIntersection::hklFrame() { return "HKL"; }
31
32//----------------------------------------------------------------------------------------------
36 declareProperty(std::make_unique<WorkspaceProperty<PeaksWorkspace>>("InputWorkspace", "", Direction::Input),
37 "An input peaks workspace.");
38
39 std::vector<std::string> propOptions;
40 propOptions.emplace_back(detectorSpaceFrame());
41 propOptions.emplace_back(qLabFrame());
42 propOptions.emplace_back(qSampleFrame());
43 propOptions.emplace_back(hklFrame());
44
45 declareProperty("CoordinateFrame", "DetectorSpace", std::make_shared<StringListValidator>(propOptions),
46 "What coordinate system to use for intersection criteria?\n"
47 " DetectorSpace: Real-space coordinates.\n"
48 " Q (lab frame): Wave-vector change of the lattice in the lab frame.\n"
49 " Q (sample frame): Momentum in the sample frame.\n"
50 " HKL");
51
52 declareProperty("PeakRadius", 0.0, "Effective peak radius in CoordinateFrame");
53
54 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>("OutputWorkspace", "", Direction::Output),
55 "An output table workspace. Two columns. Peak index into "
56 "input workspace, and boolean, where true is for positive "
57 "intersection.");
58}
59
64
70void PeaksIntersection::executePeaksIntersection(const bool checkPeakExtents) {
71 const std::string coordinateFrame = this->getPropertyValue("CoordinateFrame");
72 PeaksWorkspace_sptr ws = this->getProperty("InputWorkspace");
73
74 m_peakRadius = this->getProperty("PeakRadius");
75
76 boost::function<V3D(Peak *)> coordFrameFunc;
77 coordFrameFunc = &Peak::getHKL;
78 if (coordinateFrame == detectorSpaceFrame()) {
79 coordFrameFunc = &Peak::getDetectorPosition;
80 } else if (coordinateFrame == qLabFrame()) {
81 coordFrameFunc = &Peak::getQLabFrame;
82 } else if (coordinateFrame == qSampleFrame()) {
83 coordFrameFunc = &Peak::getQSampleFrame;
84 }
85
86 // Create the faces.
87 VecVecV3D faces = this->createFaces();
88
89 const int nPeaks = ws->getNumberPeaks();
90 const int numberOfFaces = this->numberOfFaces();
91
92 // Calculate the normals for each face.
93 VecV3D normals(numberOfFaces);
94 for (int i = 0; i < numberOfFaces; ++i) {
95 VecV3D face = faces[i];
96 normals[i] = (face[1] - face[0]).cross_prod((face[2] - face[0]));
97 const auto norm = normals[i].norm();
98 if (norm == 0) {
99 // Try to build a normal still perpendicular to the faces.
100 const auto v = face[1] - face[0];
101 const auto r = std::hypot(v.X(), v.Y());
102 if (r == 0.) {
103 normals[i] = V3D(1., 0., 0.);
104 } else {
105 const auto x = v.Y() / r;
106 const auto y = std::sqrt(1 - x * x);
107 normals[i] = V3D(x, y, 0.);
108 }
109 } else {
110 normals[i] /= norm;
111 }
112 }
113
115 std::make_shared<Mantid::DataObjects::TableWorkspace>(ws->rowCount());
116 outputWorkspace->addColumn("int", "PeakIndex");
117 outputWorkspace->addColumn("bool", "Intersecting");
118 outputWorkspace->addColumn("double", "Distance");
119
120 size_t frequency = nPeaks;
121 if (frequency > 100) {
122 frequency = nPeaks / 100;
123 }
124 Progress prog(this, 0.0, 1.0, 100);
125
126 PARALLEL_FOR_IF(Kernel::threadSafe(*ws, *outputWorkspace))
127 for (int i = 0; i < nPeaks; ++i) {
129 Peak *peak = dynamic_cast<Peak *>(ws->getPeakPtr(i));
130 V3D peakCenter = coordFrameFunc(peak);
131
132 if (i % frequency == 0)
133 prog.report();
134
135 bool doesIntersect = true;
136 double distance = 0;
137 if (pointOutsideAnyExtents(peakCenter)) {
138 // Out of bounds.
139 doesIntersect = false;
140
141 if (checkPeakExtents) {
142 // Take account of radius spherical extents.
143 for (int j = 0; j < numberOfFaces; ++j) {
144 distance = normals[j].scalar_prod(faces[j][0] - peakCenter); // Distance between plane and peak center.
145 if (m_peakRadius >= std::abs(distance)) // Sphere passes through one
146 // of the PLANES defined by
147 // the box faces.
148 {
149 // Check that it is actually within the face boundaries.
150 const V3D touchPoint = (normals[j] * distance) + peakCenter; // Vector equation of line give
151 // touch point on plane.
152
153 // checkTouchPoint(touchPoint, normals[i], faces[i][0]); //
154 // Debugging line.
155
156 if (pointInsideAllExtents(touchPoint, peakCenter)) {
157 doesIntersect = true;
158 break;
159 }
160 }
161 }
162 }
163 }
164
165 TableRow row = outputWorkspace->getRow(i);
166 row << i << doesIntersect << distance;
168 }
170
171 setProperty("OutputWorkspace", outputWorkspace);
172}
173
174} // namespace Mantid::Crystal
#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...
Definition: MultiThreaded.h:94
#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.
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
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
TableRow represents a row in a TableWorkspace.
Definition: TableRow.h:39
A property class for workspaces.
virtual VecVecV3D createFaces() const =0
Create all faces.
void executePeaksIntersection(const bool checkPeakExtents=true)
Run the algorithm.
double getPeakRadius() const
Get the peak radius.
virtual bool pointOutsideAnyExtents(const Mantid::Kernel::V3D &testPoint) const =0
Check that a point is outside any of the extents.
virtual bool pointInsideAllExtents(const Mantid::Kernel::V3D &testPoints, const Mantid::Kernel::V3D &peakCenter) const =0
Check that a point is inside ALL of the extents.
virtual int numberOfFaces() const =0
Number of surface faces that make up this object.
void initBaseProperties()
Initalize the common properties.
Structure describing a single-crystal peak.
Definition: Peak.h:34
Mantid::Kernel::V3D getDetectorPosition() const
Forwarding function.
Definition: Peak.cpp:753
Mantid::Kernel::V3D getQLabFrame() const override
Return the Q change (of the lattice, k_i - k_f) for this peak.
Definition: Peak.cpp:441
Mantid::Kernel::V3D getQSampleFrame() const override
Return the Q change (of the lattice, k_i - k_f) for this peak.
Definition: Peak.cpp:472
The class PeaksWorkspace stores information about a set of SCD peaks.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Definition: ProgressBase.h:51
Class for 3D vectors.
Definition: V3D.h:34
std::vector< VecV3D > VecVecV3D
std::vector< Mantid::Kernel::V3D > VecV3D
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
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.
Definition: MultiThreaded.h:22
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54