21#include <boost/pointer_cast.hpp>
59 throw std::invalid_argument(
"Cannot create non-orthogonal view for non-HKL coordinates");
63 throw std::invalid_argument(
"OrientedLattice is not present on workspace");
67 throw std::invalid_argument(
"W_MATRIX is not present on workspace");
72 const auto numberOfColumns = skewMatrix.
numCols();
73 const auto numberOfRows = skewMatrix.
numRows();
74 std::vector<double> bNorm;
75 bNorm.reserve(skewMatrix.
numCols());
76 for (
size_t column = 0; column < numberOfColumns; ++column) {
77 double sumOverRow(0.0);
78 for (
size_t row = 0; row < numberOfRows; ++row) {
79 sumOverRow += std::pow(skewMatrix[row][column], 2);
81 bNorm.emplace_back(std::sqrt(sumOverRow));
91 skewMatrix *= scaleMat;
95 std::size_t dim = matrix.
Ssize() - 1;
97 for (std::size_t i = 0; i < dim; i++) {
98 for (std::size_t j = 0; j < dim; j++) {
99 temp[i][j] = matrix[i][j];
110 const auto &sample =
workspace.getExperimentInfo(0)->sample();
111 const auto &run =
workspace.getExperimentInfo(0)->run();
112 auto specialCoordnateSystem =
workspace.getSpecialCoordinateSystem();
113 checkForSampleAndRunEntries(sample, run, specialCoordnateSystem);
118 auto const *transform =
workspace.getTransformToOriginal();
120 affineMatrix = transform->makeAffineMatrix();
123 std::size_t nDims =
workspace.getNumDims() + 1;
126 }
catch (std::runtime_error &) {
128 std::size_t nDims =
workspace.getNumDims() + 1;
134 auto wMatrixAsArray = run.template getPropertyValueAsType<std::vector<double>>(
"W_MATRIX");
147 unitCell.recalculateFromGstar(gStarMatrix);
148 skewMatrix = unitCell.getB();
151 normalizeColumns(skewMatrix);
154 std::vector<double> basisNormalization = {orientedLattice.astar(), orientedLattice.bstar(), orientedLattice.cstar()};
158 basisNormalization.emplace_back(1.0);
160 for (std::size_t i = 0; i < 3; i++) {
161 for (std::size_t j = 0; j < 3; j++) {
162 temp[i][j] = skewMatrix[i][j];
171 auto reducedDimension = affineMatrix.
Ssize() - 1;
173 for (std::size_t i = 0; i < reducedDimension; i++) {
174 for (std::size_t j = 0; j < reducedDimension; j++) {
175 affMat[i][j] = affineMatrix[i][j];
180 skewMatrix = affMat.
Tprime() * (skewMatrix * affMat);
183 stripMatrix(skewMatrix);
189template <
typename T>
bool doRequiresSkewMatrix(
const T &
workspace) {
190 auto requiresSkew(
true);
192 const auto &sample =
workspace.getExperimentInfo(0)->sample();
193 const auto &run =
workspace.getExperimentInfo(0)->run();
194 auto specialCoordnateSystem =
workspace.getSpecialCoordinateSystem();
195 checkForSampleAndRunEntries(sample, run, specialCoordnateSystem);
196 }
catch (std::invalid_argument &) {
197 requiresSkew =
false;
204std::array<Mantid::coord_t, N> getTransformedArray(
const std::array<Mantid::coord_t, N * N> &skewMatrix,
206 std::array<Mantid::coord_t, N> vec = {{0., 0., 0.}};
208 vec[
index] = skewMatrix[dimension +
index * N];
213template <
typename T,
size_t N>
void normalizeVector(std::array<T, N> &vector) {
214 auto sumOfSquares = [](T sum, T element) {
return sum + element * element; };
215 auto norm = std::accumulate(vector.begin(), vector.end(), 0.f, sumOfSquares);
216 norm = std::sqrt(norm);
217 for (
auto &element : vector) {
225std::array<Mantid::coord_t, 3> getNormalVector(std::array<Mantid::coord_t, 3> vector1,
226 std::array<Mantid::coord_t, 3> vector2) {
227 std::array<Mantid::coord_t, 3> normalVector;
229 normalVector[
index] =
230 vector1[(
index + 1) % 3] * vector2[(
index + 2) % 3] - vector1[(
index + 2) % 3] * vector2[(
index + 1) % 3];
234 normalizeVector<Mantid::coord_t, 3>(normalVector);
246std::array<Mantid::coord_t, 3> getNormalVector(
size_t dimX,
size_t dimY) {
247 std::array<Mantid::coord_t, 3> vector1 = {{0., 0., 0.}};
248 std::array<Mantid::coord_t, 3> vector2 = {{0., 0., 0.}};
252 std::array<Mantid::coord_t, 3> normalVector;
254 normalVector[
index] =
255 vector1[(
index + 1) % 3] * vector2[(
index + 2) % 3] - vector1[(
index + 2) % 3] * vector2[(
index + 1) % 3];
259 normalizeVector<Mantid::coord_t, 3>(normalVector);
268getAngleInRadian(std::array<Mantid::coord_t, N> orthogonalVector, std::array<Mantid::coord_t, N> nonOrthogonalVector,
269 const std::array<Mantid::coord_t, N> &normalVector,
size_t currentDimension,
size_t otherDimension) {
287 if (currentDimension == 0) {
290 }
else if (currentDimension == 1 && otherDimension == 2) {
293 }
else if (currentDimension == 2) {
295 normalizeVector<Mantid::coord_t, N>(orthogonalVector);
296 normalizeVector<Mantid::coord_t, N>(nonOrthogonalVector);
300 std::array<Mantid::coord_t, 3> temporaryNonOrthogonal{{0.f, 0.f, 0.f}};
301 temporaryNonOrthogonal[currentDimension] = nonOrthogonalVector[currentDimension];
302 temporaryNonOrthogonal[otherDimension] = nonOrthogonalVector[otherDimension];
303 nonOrthogonalVector = temporaryNonOrthogonal;
306 normalizeVector<Mantid::coord_t, N>(orthogonalVector);
307 normalizeVector<Mantid::coord_t, N>(nonOrthogonalVector);
310 std::inner_product(orthogonalVector.begin(), orthogonalVector.end(), nonOrthogonalVector.begin(), 0.f);
313 if (dotProduct == 1.) {
316 }
else if (dotProduct == -1.) {
317 angle =
static_cast<double>(M_PI);
320 angle = std::acos(dotProduct);
323 auto normalForDirection = getNormalVector(orthogonalVector, nonOrthogonalVector);
324 auto direction = std::inner_product(normalForDirection.begin(), normalForDirection.end(), normalVector.begin(), 0.f);
337 for (
size_t i = 0; i <
workspace->getNumDims(); ++i) {
338 auto dimension =
workspace->getDimension(i);
339 const auto &frame = dimension->getMDFrame();
344 return static_cast<size_t>(NULL);
349 doProvideSkewMatrix(skewMatrix, *mdew);
351 doProvideSkewMatrix(skewMatrix, *mdhw);
353 throw std::invalid_argument(
"NonOrthogonal: The provided workspace "
354 "must either be an IMDEvent or IMDHisto "
361 return doRequiresSkewMatrix(*mdew);
363 return doRequiresSkewMatrix(*mdhw);
373 return hklname(dimX) && hklname(dimY);
377 std::array<Mantid::coord_t, 9> &skewMatrixCoord) {
378 std::size_t
index = 0;
379 for (std::size_t i = 0; i < skewMatrix.
numRows(); ++i) {
380 for (std::size_t j = 0; j < skewMatrix.
numCols(); ++j) {
399 const size_t &dimX,
const size_t &dimY,
const size_t &dimSlice) {
401 auto sliceDimResult = (lookPoint[dimSlice] - skewMatrix[3 * dimSlice + dimX] * lookPoint[dimX] -
402 skewMatrix[3 * dimSlice + dimY] * lookPoint[dimY]) /
403 skewMatrix[3 * dimSlice + dimSlice];
405 auto OrigDimSliceValue = lookPoint[dimSlice];
406 lookPoint[dimSlice] = sliceDimResult;
408 auto v1 = lookPoint[0];
409 auto v2 = lookPoint[1];
410 auto v3 = lookPoint[2];
412 lookPoint[dimX] = v1 * skewMatrix[0 + 3 * dimX] + v2 * skewMatrix[1 + 3 * dimX] + v3 * skewMatrix[2 + 3 * dimX];
413 lookPoint[dimY] = v1 * skewMatrix[0 + 3 * dimY] + v2 * skewMatrix[1 + 3 * dimY] + v3 * skewMatrix[2 + 3 * dimY];
415 lookPoint[dimSlice] = OrigDimSliceValue;
445 std::array<Mantid::coord_t, 3> dimXOriginal = {{0., 0., 0.}};
446 std::array<Mantid::coord_t, 3> dimYOriginal = {{0., 0., 0.}};
447 dimXOriginal[dimX] = 1.0;
448 dimYOriginal[dimY] = 1.0;
449 auto dimXTransformed = getTransformedArray<3>(skewMatrixCoord, dimX);
450 auto dimYTransformed = getTransformedArray<3>(skewMatrixCoord, dimY);
453 auto normalVector = getNormalVector(dimX, dimY);
456 auto angleDimX = getAngleInRadian(dimXOriginal, dimXTransformed, normalVector, dimX, dimY);
457 auto angleDimY = getAngleInRadian(dimYOriginal, dimYTransformed, normalVector, dimY, dimX);
458 return std::make_pair(angleDimX, angleDimY);
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
Abstract base class for multi-dimension event workspaces (MDEventWorkspace).
Abstract interface to MDHistoWorkspace, for use in exposing to Python.
Basic MD Workspace Abstract Class.
bool hasProperty(const std::string &name) const
Does the property exist on the object.
This class stores information regarding an experimental run as a series of log entries.
This class stores information about the sample used in particular run.
const Geometry::OrientedLattice & getOrientedLattice() const
Get a reference to the sample's OrientedLattice.
bool hasOrientedLattice() const
static const std::string HKLName
Class to implement unit cell of crystals.
T Invert()
LU inversion routine.
size_t Ssize() const
Return the smallest matrix size.
Matrix< T > Tprime() const
Transpose the matrix.
size_t numRows() const
Return the number of rows in the matrix.
size_t numCols() const
Return the number of columns in the matrix.
std::pair< double, double > EXPORT_OPT_MANTIDQT_COMMON getGridLineAnglesInRadian(const std::array< Mantid::coord_t, 9 > &skewMatrixCoord, size_t dimX, size_t dimY)
We get the angles that are used for plotting of the grid lines.
void EXPORT_OPT_MANTIDQT_COMMON provideSkewMatrix(Mantid::Kernel::DblMatrix &skewMatrix, const Mantid::API::IMDWorkspace &workspace)
bool EXPORT_OPT_MANTIDQT_COMMON requiresSkewMatrix(const Mantid::API::IMDWorkspace &workspace)
bool EXPORT_OPT_MANTIDQT_COMMON isHKLDimensions(const Mantid::API::IMDWorkspace &workspace, size_t dimX, size_t dimY)
void transformLookpointToWorkspaceCoord(T &lookPoint, const std::array< Mantid::coord_t, 9 > &skewMatrix, const size_t &dimX, const size_t &dimY, const size_t &dimSlice)
void EXPORT_OPT_MANTIDQT_COMMON transformFromDoubleToCoordT(const Mantid::Kernel::DblMatrix &skewMatrix, std::array< Mantid::coord_t, 9 > &skewMatrixCoord)
size_t EXPORT_OPT_MANTIDQT_COMMON getMissingHKLDimensionIndex(const Mantid::API::IMDWorkspace_const_sptr &workspace, size_t dimX, size_t dimY)
The AlgorithmProgressDialogPresenter keeps track of the running algorithms and displays a progress ba...
std::shared_ptr< const IMDWorkspace > IMDWorkspace_const_sptr
Shared pointer to the IMDWorkspace base class (const version)
double dotProduct(const DoubleFortranVector &x, const DoubleFortranVector &y)
Dot product of two vectors.
std::vector< T > normalizeVector(const std::vector< T > &x)
Normalize a vector of any size to unity, using the sum of the squares of the components.
SpecialCoordinateSystem
Special coordinate systems for Q3D.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...