Mantid
Loading...
Searching...
No Matches
CoordTransformDistance.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
11#include <boost/algorithm/string.hpp>
12#include <boost/format.hpp>
13
14using namespace Mantid::Geometry;
15using namespace Mantid::Kernel;
17
18namespace Mantid::DataObjects {
19
20//----------------------------------------------------------------------------------------------
32CoordTransformDistance::CoordTransformDistance(const size_t inD, const coord_t *center, const bool *dimensionsUsed,
33 const size_t outD, const std::vector<Kernel::V3D> &eigenvects,
34 const std::vector<double> &eigenvals)
35 : CoordTransform(inD, outD) {
36
37 m_center.reserve(inD);
38 m_dimensionsUsed.reserve(inD);
39 m_eigenvals.reserve(inD);
40 m_maxEigenval = 0.0;
41 for (size_t d = 0; d < inD; d++) {
42 m_center.push_back(center[d]);
43 m_dimensionsUsed.push_back(dimensionsUsed[d]);
44 if (eigenvals.size() == inD && eigenvects.size() == inD) {
45 // coord transform for n-ellipsoid specified
46 m_eigenvals.push_back(eigenvals[d]);
47 m_eigenvects.push_back(eigenvects[d]);
48 m_maxEigenval = std::max(m_maxEigenval, eigenvals[d]);
49 }
50 }
51}
52
53CoordTransformDistance::CoordTransformDistance(const size_t inD, const coord_t *center, const bool *dimensionsUsed,
54 const size_t outD, const std::array<Kernel::V3D, 3> &eigenvects,
55 const std::array<double, 3> &eigenvals)
56 : CoordTransform(inD, outD) {
57
58 m_center.reserve(inD);
59 m_dimensionsUsed.reserve(inD);
60 m_eigenvals.reserve(inD);
61 m_maxEigenval = 0.0;
62 for (size_t d = 0; d < inD; d++) {
63 m_center.push_back(center[d]);
64 m_dimensionsUsed.push_back(dimensionsUsed[d]);
65 // coord transform for n-ellipsoid specified
66 m_eigenvals.push_back(eigenvals[d]);
67 m_eigenvects.push_back(eigenvects[d]);
68 m_maxEigenval = std::max(m_maxEigenval, eigenvals[d]);
69 }
70}
71
72//----------------------------------------------------------------------------------------------
76
77//----------------------------------------------------------------------------------------------
87void CoordTransformDistance::apply(const coord_t *inputVector, coord_t *outVector) const {
88 if (outD == 1) {
89 coord_t distanceSquared = 0;
90 if (m_eigenvals.size() == 3) {
91 // ellipsoid transfrom with ratio of axes given by standard deviation
92 // i.e. sqrt(eigenvals)
93 for (size_t d = 0; d < inD; d++) {
94 // do dot prod with eigenvector
95 coord_t dist = 0.0;
96 // calculate the covariance of the delta vector using
97 // the three eigen vector as the new base
98 for (size_t dd = 0; dd < inD; dd++) {
99 dist += static_cast<coord_t>(m_eigenvects[d][dd]) * (inputVector[dd] - m_center[dd]);
100 }
101
102 distanceSquared += (dist * dist) * static_cast<coord_t>(m_maxEigenval / m_eigenvals[d]);
103 }
104 // debug output
105 // std::cout << "[CoordTransFormDistance]\n"
106 // << "eigenvals:" << m_eigenvals[0] << "," << m_eigenvals[1]
107 // << "," << m_eigenvals[2] << "\n"
108 // << "peak_center:" << m_center[0] << "," << m_center[1] << ","
109 // << m_center[2] << "\n"
110 // << "distanceSquared = " << distanceSquared << "\n\n";
111 } else {
112 // nd spherical transform
113 for (size_t d = 0; d < inD; d++) {
114 if (m_dimensionsUsed[d]) {
115 coord_t dist = inputVector[d] - m_center[d];
116 distanceSquared += (dist * dist);
117 }
118 }
119 }
121 outVector[0] = distanceSquared;
122 } else {
123 // Cylinder 2D output radius and length
124 coord_t lenQdata = 0.0;
125 coord_t lenQpeak = 0.0;
126 coord_t cosAng = 0.0;
127 for (size_t d = 0; d < inD; d++) {
128 lenQdata += inputVector[d] * inputVector[d];
129 lenQpeak += m_center[d] * m_center[d];
130 cosAng += m_center[d] * inputVector[d];
131 }
132 lenQdata = std::sqrt(lenQdata);
133 lenQpeak = std::sqrt(lenQpeak);
134 if (lenQpeak * lenQdata != 0.0)
135 cosAng /= (lenQpeak * lenQdata);
136 coord_t angle = std::acos(cosAng);
137 outVector[0] = lenQdata * std::sin(angle);
138 outVector[1] = lenQdata * cosAng - lenQpeak;
139 }
140}
141
142//----------------------------------------------------------------------------------------------
148 using namespace Poco::XML;
149
150 AutoPtr<Document> pDoc = new Document;
151 AutoPtr<Element> coordTransformElement = pDoc->createElement("CoordTransform");
152 pDoc->appendChild(coordTransformElement);
153
154 AutoPtr<Element> coordTransformTypeElement = pDoc->createElement("Type");
155 coordTransformTypeElement->appendChild(AutoPtr<Text>(pDoc->createTextNode("CoordTransformDistance")));
156 coordTransformElement->appendChild(coordTransformTypeElement);
157
158 AutoPtr<Element> paramListElement = pDoc->createElement("ParameterList");
159
160 AutoPtr<Text> formatText = pDoc->createTextNode("%s%s%s%s");
161 paramListElement->appendChild(formatText);
162 coordTransformElement->appendChild(paramListElement);
163
164 std::stringstream xmlstream;
165
166 DOMWriter writer;
167 writer.writeNode(xmlstream, pDoc);
168
169 // Convert the members to parameters
170 Mantid::API::InDimParameter inD_param(inD);
171 Mantid::API::OutDimParameter outD_param(outD);
172 CoordCenterVectorParam m_center_param(inD);
173 DimensionsUsedVectorParam m_dimensionsUsed_param(inD);
174
175 // Create and copy the arrays.
176 for (size_t d = 0; d < inD; d++) {
177 m_center_param.addValue(d, m_center[d]);
178 m_dimensionsUsed_param.addValue(d, m_dimensionsUsed[d]);
179 }
180
181 std::string formattedXMLString = boost::str(boost::format(xmlstream.str().c_str()) % inD_param.toXMLString().c_str() %
182 outD_param.toXMLString().c_str() % m_center_param.toXMLString().c_str() %
183 m_dimensionsUsed_param.toXMLString().c_str());
184
185 return formattedXMLString;
186}
187
192std::string CoordTransformDistance::id() const { return "CoordTransformDistance"; }
193
194} // namespace Mantid::DataObjects
Unique SingleValueParameter Declaration for InputNDimensions.
size_t inD
Input number of dimensions.
size_t outD
Output number of dimensions.
Unique CoordCenterVectorParam type declaration for ndimensional coordinate centers.
std::vector< coord_t > m_center
Coordinates at the center.
void apply(const coord_t *inputVector, coord_t *outVector) const override
Apply the coordinate transformation.
std::vector< bool > m_dimensionsUsed
Parmeter where True is set for those dimensions that are considered when calculating distance.
CoordTransform * clone() const override
Virtual cloner.
CoordTransformDistance(const size_t inD, const coord_t *center, const bool *dimensionsUsed, const size_t outD=1, const std::vector< Kernel::V3D > &eigenvects=std::vector< Kernel::V3D >(0), const std::vector< double > &eigenvals=std::vector< double >(0, 0.0))
Constructor.
std::string id() const override
Coordinate transform id.
std::string toXMLString() const override
Serialize the coordinate transform distance.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27