Mantid
Loading...
Searching...
No Matches
SelectCellWithForm.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 +
8#include "MantidAPI/Sample.h"
16
17namespace Mantid::Crystal {
18// Register the algorithm into the AlgorithmFactory
19DECLARE_ALGORITHM(SelectCellWithForm)
20
21using namespace Mantid::Kernel;
22using namespace Mantid::API;
23using namespace Mantid::DataObjects;
24using namespace Mantid::Geometry;
25
29 this->declareProperty(std::make_unique<WorkspaceProperty<IPeaksWorkspace>>("PeaksWorkspace", "", Direction::InOut),
30 "Input Peaks Workspace");
31
32 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
33 mustBePositive->setLower(1);
34
35 this->declareProperty(std::make_unique<PropertyWithValue<int>>("FormNumber", 0, mustBePositive, Direction::Input),
36 "Form number for the desired cell");
37 this->declareProperty("Apply", false, "Update UB and re-index the peaks");
38 this->declareProperty("Tolerance", 0.12, "Indexing Tolerance");
39
40 this->declareProperty(std::make_unique<PropertyWithValue<int>>("NumIndexed", 0, Direction::Output),
41 "The number of indexed peaks if apply==true.");
42
43 this->declareProperty(std::make_unique<PropertyWithValue<double>>("AverageError", 0.0, Direction::Output),
44 "The average HKL indexing error if apply==true.");
45
46 this->declareProperty("AllowPermutations", true, "Allow permutations of conventional cells");
47 this->declareProperty(std::make_unique<ArrayProperty<double>>("TransformationMatrix", Direction::Output),
48 "The transformation matrix");
49}
50
52 const Kernel::Matrix<double> &UB,
53 const Kernel::Matrix<double> &modUB,
54 const IPeaksWorkspace_sptr &ws, double tolerance) {
55
56 std::vector<V3D> miller_ind;
57 std::vector<V3D> q_vectors;
58 std::vector<V3D> q_vectors0;
59
60 int npeaks = ws->getNumberPeaks();
61 double fit_error;
62
63 miller_ind.reserve(npeaks);
64 q_vectors.reserve(npeaks);
65 q_vectors0.reserve(npeaks);
66
67 for (int i = 0; i < npeaks; i++)
68 q_vectors0.emplace_back(ws->getPeak(i).getQSampleFrame() - modUB * ws->getPeak(i).getIntMNP() * 2 * M_PI);
69
70 Kernel::Matrix<double> newUB1(3, 3);
71 IndexingUtils::GetIndexedPeaks(UB, q_vectors0, tolerance, miller_ind, q_vectors, fit_error);
72 IndexingUtils::Optimize_UB(newUB1, miller_ind, q_vectors, sigabc);
73
74 auto nindexed_old = static_cast<int>(q_vectors.size());
75 int nindexed_new = IndexingUtils::NumberIndexed(newUB1, q_vectors0, tolerance);
76 bool latErrorsValid = true;
77 if (nindexed_old < .8 * nindexed_new || .8 * nindexed_old > nindexed_new)
78 latErrorsValid = false;
79 else {
80 double maxDiff = 0;
81 double maxEntry = 0;
82 for (int row = 0; row < 3; row++)
83 for (int col = 0; col < 3; col++) {
84 double diff = fabs(UB[row][col] - newUB1[row][col]);
85 double V = std::max<double>(fabs(UB[row][col]), fabs(newUB1[row][col]));
86 if (diff > maxDiff)
87 maxDiff = diff;
88 if (V > maxEntry)
89 maxEntry = V;
90 }
91 if (maxEntry == 0 || maxDiff / maxEntry > .1)
92 latErrorsValid = false;
93 }
94
95 if (!latErrorsValid) {
96 std::fill(sigabc.begin(), sigabc.end(), 0.);
97 return UB;
98
99 } else
100
101 return newUB1;
102}
103
105 int &num_indexed, double &average_error) {
106 // Try to optimize(LSQ) to find lattice errors
107 // UB matrix may NOT have been found by unconstrained least squares optimization
108 std::vector<double> sigabc(6);
109 int n_peaks = ws->getNumberPeaks();
110
111 std::vector<V3D> miller_indices;
112 std::vector<V3D> q_vectors;
113
114 std::unique_ptr<Geometry::OrientedLattice> o_lattice =
115 std::make_unique<OrientedLattice>(ws->mutableSample().getOrientedLattice());
116 Matrix<double> UB = o_lattice->getUB();
117
118 DblMatrix UBinv = newUB;
119 UBinv.Invert();
120
121 DblMatrix Tref = UBinv * UB;
122
123 o_lattice->setUB(newUB);
124
125 DblMatrix modHKL = o_lattice->getModHKL();
126
127 DblMatrix modUB = UB * modHKL;
128
129 modHKL = Tref * modHKL;
130
131 o_lattice->setModHKL(modHKL);
132
133 for (int i = 0; i < n_peaks; i++) {
134 IPeak &peak = ws->getPeak(i);
135 q_vectors.emplace_back(peak.getQSampleFrame() - modUB * peak.getIntMNP() * 2 * M_PI);
136 }
137
138 num_indexed = IndexingUtils::CalculateMillerIndices(newUB, q_vectors, tolerance, miller_indices, average_error);
139
140 for (int i = 0; i < n_peaks; i++) {
141 IPeak &peak = ws->getPeak(i);
142 V3D hkl = miller_indices[i];
143 peak.setHKL(hkl + modHKL * peak.getIntMNP());
144 peak.setIntHKL(hkl);
145 }
146
147 SelectCellWithForm::DetermineErrors(sigabc, newUB, modUB, ws, tolerance);
148
149 o_lattice->setError(sigabc[0], sigabc[1], sigabc[2], sigabc[3], sigabc[4], sigabc[5]);
150
151 ws->mutableSample().setOrientedLattice(std::move(o_lattice));
152}
153
157 IPeaksWorkspace_sptr ws = this->getProperty("PeaksWorkspace");
158 if (!ws) {
159 throw std::runtime_error("Could not read the peaks workspace");
160 }
161
162 // copy current lattice
163 Matrix<double> UB = ws->sample().getOrientedLattice().getUB();
164
165 bool allowPermutations = this->getProperty("AllowPermutations");
166
167 if (!IndexingUtils::CheckUB(UB)) {
168 throw std::runtime_error("ERROR: The stored UB is not a valid orientation matrix");
169 }
170
171 int form_num = this->getProperty("FormNumber");
172 bool apply = this->getProperty("Apply");
173 double tolerance = this->getProperty("Tolerance");
174
175 ConventionalCell info = ScalarUtils::GetCellForForm(UB, form_num, allowPermutations);
176
177 DblMatrix newUB = info.GetNewUB();
178
179 std::string message = info.GetDescription() + " Lat Par:" + IndexingUtils::GetLatticeParameterString(newUB);
180
181 g_log.notice(std::string(message));
182
183 DblMatrix T = info.GetHKL_Tran();
184 g_log.notice() << "Reduced to Conventional Cell Transformation Matrix = " << T.str() << '\n';
185 this->setProperty("TransformationMatrix", T.getVector());
186
187 if (apply) {
188 int num_indexed;
189 double average_error = 0.0;
190
191 SelectCellWithForm::ApplyTransform(newUB, ws, tolerance, num_indexed, average_error);
192
193 // Tell the user what happened.
194 g_log.notice() << "Re-indexed the peaks with the new UB. \n";
195 g_log.notice() << "Now, " << num_indexed << " are indexed with average error " << average_error << '\n';
196
197 // Save output properties
198 this->setProperty("NumIndexed", num_indexed);
199 this->setProperty("AverageError", average_error);
200 }
201}
202
203} // namespace Mantid::Crystal
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
#define fabs(x)
Definition: Matrix.cpp:22
double tolerance
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
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
A property class for workspaces.
void exec() override
Run the algorithm.
static Kernel::Matrix< double > DetermineErrors(std::vector< double > &sigabc, const Kernel::Matrix< double > &UB, const Kernel::Matrix< double > &modUB, const API::IPeaksWorkspace_sptr &ws, double tolerance)
static void ApplyTransform(Kernel::Matrix< double > &newUB, API::IPeaksWorkspace_sptr &ws, double tolerance, int &num_indexed, double &average_error)
void init() override
Initialise the properties.
Instances of this class represent information about a selected conventional cell based on a specified...
std::string GetDescription() const
get string listing form number, error, cell type and centering
Kernel::DblMatrix GetNewUB() const
get the transformed orientation matrix for the conventional cell
Kernel::DblMatrix GetHKL_Tran() const
get the transform to change HKL to new conventional cell HKL
Structure describing a single-crystal peak.
Definition: IPeak.h:26
virtual void setHKL(double H, double K, double L)=0
virtual Mantid::Kernel::V3D getQSampleFrame() const =0
virtual void setIntHKL(const Mantid::Kernel::V3D &HKL)=0
virtual Mantid::Kernel::V3D getIntMNP() const =0
static int GetIndexedPeaks(const Kernel::DblMatrix &UB, const std::vector< Kernel::V3D > &q_vectors, double required_tolerance, std::vector< Kernel::V3D > &miller_indices, std::vector< Kernel::V3D > &indexed_qs, double &fit_error)
Get lists of indices and Qs for peaks indexed by the specified UB matrix.
static std::string GetLatticeParameterString(const Kernel::DblMatrix &UB)
Get a formatted string listing the lattice parameters and cell volume.
static bool CheckUB(const Kernel::DblMatrix &UB)
Check that the specified UB is reasonable for an orientation matrix.
static int NumberIndexed(const Kernel::DblMatrix &UB, const std::vector< Kernel::V3D > &q_vectors, double tolerance)
Calculate the number of Q vectors that are mapped to integer indices by UB.
static double Optimize_UB(Kernel::DblMatrix &UB, const std::vector< Kernel::V3D > &hkl_vectors, const std::vector< Kernel::V3D > &q_vectors, std::vector< double > &sigabc)
Find the UB matrix that most nearly maps hkl to qxyz for 3 or more peaks.
static int CalculateMillerIndices(const Kernel::DblMatrix &UB, const std::vector< Kernel::V3D > &q_vectors, double tolerance, std::vector< Kernel::V3D > &miller_indices, double &ave_error)
Given a UB, get list of Miller indices for specifed Qs and tolerance.
static ConventionalCell GetCellForForm(const Kernel::DblMatrix &UB, size_t form_num, bool allowPermutations=false)
Get the best conventional cell for the form number, using the specified UB, and three related "almost...
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
Numerical Matrix class.
Definition: Matrix.h:42
T Invert()
LU inversion routine.
Definition: Matrix.cpp:924
std::vector< T > getVector() const
Definition: Matrix.cpp:77
std::string str() const
Convert the matrix into a simple linear string expression.
Definition: Matrix.cpp:1564
The concrete, templated class for properties.
Class for 3D vectors.
Definition: V3D.h:34
std::shared_ptr< IPeaksWorkspace > IPeaksWorkspace_sptr
shared pointer to Mantid::API::IPeaksWorkspace
@ InOut
Both an input & output workspace.
Definition: Property.h:55
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54