Mantid
Loading...
Searching...
No Matches
FindUBUsingIndexedPeaks.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 +
9#include "MantidAPI/Sample.h"
15
16namespace Mantid::Crystal {
17// Register the algorithm into the AlgorithmFactory
18DECLARE_ALGORITHM(FindUBUsingIndexedPeaks)
19
20using namespace Mantid::Kernel;
21using namespace Mantid::API;
22using namespace Mantid::DataObjects;
23using namespace Mantid::Geometry;
24
25const int MIN_INDEXED_PEAKS = 3;
29 declareProperty(std::make_unique<WorkspaceProperty<IPeaksWorkspace>>("PeaksWorkspace", "", Direction::InOut),
30 "Input Peaks Workspace");
31 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
32 mustBePositive->setLower(0.0);
33 declareProperty("Tolerance", 0.1, mustBePositive, "Indexing Tolerance (0.1)");
34 declareProperty("ToleranceForSatellite", 0.1, mustBePositive, "Indexing Tolerance for satellite (0.1)");
35 declareProperty("CommonUBForAll", false, "Used when evaluating the uncertainty of modHKL");
36}
37
41 IPeaksWorkspace_sptr ws = getProperty("PeaksWorkspace");
42 const int n_peaks = ws->getNumberPeaks();
43
44 std::vector<V3D> q_vectors;
45 std::vector<V3D> hkl_vectors;
46 std::vector<V3D> mnp_vectors;
47
48 double tolerance = getProperty("Tolerance");
49 bool commonUB = getProperty("CommonUBForAll");
50
51 int ModDim = 0;
52 int MaxOrder = 0;
53 bool CrossTerm = false;
54 DblMatrix errorHKL(3, 3);
55
56 q_vectors.reserve(n_peaks);
57 hkl_vectors.reserve(n_peaks);
58 mnp_vectors.reserve(n_peaks);
59
60 size_t indexed_count = 0;
61 std::unordered_set<int> run_numbers;
62 for (int i = 0; i < n_peaks; i++) {
63 const IPeak &peak = ws->getPeak(i);
64 run_numbers.insert(peak.getRunNumber());
65 V3D hkl(peak.getIntHKL());
66 V3D mnp(peak.getIntMNP());
67 int maxOrder = mnp.maxCoeff();
68 if (maxOrder > MaxOrder)
69 MaxOrder = maxOrder;
70
71 if (mnp[0] != 0 && ModDim == 0)
72 ModDim = 1;
73 if (mnp[1] != 0 && ModDim == 1)
74 ModDim = 2;
75 if (mnp[2] != 0 && ModDim == 2)
76 ModDim = 3;
77 if (mnp[0] * mnp[1] != 0 || mnp[1] * mnp[2] != 0 || mnp[2] * mnp[0] != 0)
78 CrossTerm = true;
79
80 if (isPeakIndexed(peak)) {
81 q_vectors.emplace_back(peak.getQSampleFrame());
82 hkl_vectors.emplace_back(hkl);
83 mnp_vectors.emplace_back(mnp);
84 indexed_count++;
85 }
86 }
87
88 // too few indexed peaks to work with
89 if (indexed_count < MIN_INDEXED_PEAKS) {
90 throw std::runtime_error("At least three linearly independent indexed peaks are needed.");
91 }
92
93 Matrix<double> UB(3, 3, false);
94 Matrix<double> modUB(3, 3, false);
95 std::vector<double> sigabc(7);
96 std::vector<double> sigq(3);
97
98 IndexingUtils::Optimize_6dUB(UB, modUB, hkl_vectors, mnp_vectors, ModDim, q_vectors, sigabc, sigq);
99
100 if (!IndexingUtils::CheckUB(UB)) // UB not found correctly
101 {
102 g_log.notice(std::string("Found Invalid UB...peaks used might not be linearly independent"));
103 g_log.notice(std::string("UB NOT SAVED."));
104 } else // tell user how many would be indexed
105 { // from the full list of peaks, and
106 q_vectors.clear(); // save the UB in the sample
107 q_vectors.reserve(n_peaks);
108
109 for (int i = 0; i < n_peaks; i++) {
110 q_vectors.emplace_back(ws->getPeak(i).getQSampleFrame());
111 }
112
113 int num_indexed = IndexingUtils::NumberIndexed(UB, q_vectors, tolerance);
114 int sate_indexed = 0;
115 double satetolerance = getProperty("ToleranceForSatellite");
116
117 if (ModDim > 0) {
118 for (int run : run_numbers) {
119 std::vector<V3D> run_q_vectors;
120 std::vector<V3D> run_fhkl_vectors;
121 std::vector<V3D> run_hkl_vectors;
122 std::vector<V3D> run_mnp_vectors;
123 size_t run_indexed = 0;
124
125 for (int i = 0; i < n_peaks; i++) {
126 const IPeak &peak = ws->getPeak(i);
127 if (peak.getRunNumber() == run) {
128 if (isPeakIndexed(peak))
129 run_indexed++;
130 }
131 }
132
133 g_log.notice() << "Number of Indexed Peaks in Run " << run << " is " << run_indexed << "\n";
134
135 run_q_vectors.reserve(run_indexed);
136 run_hkl_vectors.reserve(run_indexed);
137 run_mnp_vectors.reserve(run_indexed);
138 run_fhkl_vectors.reserve(run_indexed);
139
140 for (int i = 0; i < n_peaks; i++) {
141 const IPeak &peak = ws->getPeak(i);
142 if (peak.getRunNumber() == run) {
143 V3D hkl(peak.getIntHKL());
144 V3D mnp(peak.getIntMNP());
145 if (isPeakIndexed(peak)) {
146 run_q_vectors.emplace_back(peak.getQSampleFrame());
147 run_hkl_vectors.emplace_back(hkl);
148 run_mnp_vectors.emplace_back(mnp);
149 }
150 }
151 }
152
153 if (run_indexed < 3)
154 continue;
155
156 OrientedLattice run_lattice;
157
158 if (commonUB) {
159 run_lattice.setUB(UB);
160 run_lattice.setModUB(modUB);
161 run_lattice.setError(sigabc[0], sigabc[1], sigabc[2], sigabc[3], sigabc[4], sigabc[5]);
162 } else {
163 Matrix<double> run_UB(3, 3, false);
164 Matrix<double> run_modUB(3, 3, false);
165 std::vector<double> run_sigabc(7);
166 std::vector<double> run_sigq(3);
167 IndexingUtils::Optimize_6dUB(run_UB, run_modUB, run_hkl_vectors, run_mnp_vectors, ModDim, run_q_vectors,
168 run_sigabc, run_sigq);
169 run_lattice.setUB(run_UB);
170 run_lattice.setModUB(run_modUB);
171 run_lattice.setError(run_sigabc[0], run_sigabc[1], run_sigabc[2], run_sigabc[3], run_sigabc[4],
172 run_sigabc[5]);
173 }
174 g_log.notice() << run_lattice << "\n";
175
176 double average_error = 0.;
177 IndexingUtils::CalculateMillerIndices(run_lattice.getUB(), run_q_vectors, 1.0, run_fhkl_vectors, average_error);
178 for (size_t i = 0; i < run_indexed; i++) {
179 if (IndexingUtils::ValidIndex(run_fhkl_vectors[i], tolerance))
180 continue;
181
182 V3D fhkl(run_fhkl_vectors[i]);
183 for (int j = 0; j < 3; j++) {
184 if (run_mnp_vectors[i][j] != 0) {
185 fhkl -= run_lattice.getModVec(j) * run_mnp_vectors[i][j];
186 if (IndexingUtils::ValidIndex(fhkl, satetolerance)) {
187 sate_indexed++;
188 V3D errhkl = fhkl - run_hkl_vectors[i];
189 errhkl = errhkl.absoluteValue();
190 for (int k = 0; k < 3; k++)
191 errorHKL[k][j] += errhkl[k];
192 }
193 }
194 }
195 }
196 }
197 }
198
199 std::stringstream stream;
200 stream << "New UB will index " << num_indexed << " main Peaks with tolerance " << tolerance << " and "
201 << sate_indexed << " Satellite Peaks with tolerance " << satetolerance << " ,out of " << n_peaks
202 << " Peaks \n";
203 g_log.notice(stream.str());
204
205 auto o_lattice = std::make_unique<OrientedLattice>();
206 o_lattice->setUB(UB);
207 o_lattice->setModUB(modUB);
208 o_lattice->setError(sigabc[0], sigabc[1], sigabc[2], sigabc[3], sigabc[4], sigabc[5]);
209 double ind_count_inv = 1. / static_cast<double>(indexed_count);
210 errorHKL *= ind_count_inv;
211 o_lattice->setErrorModHKL(errorHKL);
212
213 o_lattice->setMaxOrder(MaxOrder);
214 o_lattice->setCrossTerm(CrossTerm);
215
216 // Show the modified lattice parameters
217 logLattice(*o_lattice, ModDim);
218
219 ws->mutableSample().setOrientedLattice(std::move(o_lattice));
220 }
221}
222void FindUBUsingIndexedPeaks::logLattice(const OrientedLattice &o_lattice, const int &ModDim) {
223 // Show the modified lattice parameters
224 g_log.notice() << o_lattice << "\n";
225 g_log.notice() << "Modulation Dimension is: " << ModDim << "\n";
226 for (int i = 0; i < ModDim; i++) {
227 g_log.notice() << "Modulation Vector " << i + 1 << ": " << o_lattice.getModVec(i) << "\n";
228 g_log.notice() << "Modulation Vector " << i + 1 << " error: " << o_lattice.getVecErr(i) << "\n";
229 }
230}
232 const V3D hkl(peak.getIntHKL());
233 const V3D mnp(peak.getIntMNP());
234 return (IndexingUtils::ValidIndex(hkl, 1.0) || IndexingUtils::ValidIndex(mnp, 1.0));
235}
236} // namespace Mantid::Crystal
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
const bool commonUB
Definition: IndexPeaks.cpp:117
const int maxOrder
Definition: IndexPeaks.cpp:55
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 logLattice(const Geometry::OrientedLattice &o_lattice, const int &ModDim)
bool isPeakIndexed(const Geometry::IPeak &peak)
void init() override
Initialise the properties.
Structure describing a single-crystal peak.
Definition: IPeak.h:26
virtual Mantid::Kernel::V3D getIntHKL() const =0
virtual int getRunNumber() const =0
virtual Mantid::Kernel::V3D getQSampleFrame() const =0
virtual Mantid::Kernel::V3D getIntMNP() const =0
static double Optimize_6dUB(Kernel::DblMatrix &UB, Kernel::DblMatrix &ModUB, const std::vector< Kernel::V3D > &hkl_vectors, const std::vector< Kernel::V3D > &mnp_vectors, const int &ModDim, const std::vector< Kernel::V3D > &q_vectors, std::vector< double > &sigabc, std::vector< double > &sigq)
STATIC method Optimize_UB: Calculates the matrix that most nearly maps the specified hkl_vectors to t...
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 bool ValidIndex(const Kernel::V3D &hkl, double tolerance)
Check is hkl is within tolerance of integer (h,k,l) non-zero values.
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.
Class to implement UB matrix.
void setModUB(const Kernel::DblMatrix &newModUB)
Sets the Modulation UB matrix.
void setUB(const Kernel::DblMatrix &newUB)
Sets the UB matrix and recalculates lattice parameters.
const Kernel::DblMatrix & getUB() const
Get the UB matrix.
const Kernel::V3D getVecErr(int j) const
Get errors for modulation vectors for satellites.
Definition: UnitCell.cpp:542
void setError(double _aerr, double _berr, double _cerr, double _alphaerr, double _betaerr, double _gammaerr, const int angleunit=angDegrees)
Set lattice parameter errors.
Definition: UnitCell.cpp:325
const Kernel::V3D getModVec(int j) const
Get modulation vectors for satellites.
Definition: UnitCell.cpp:535
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
Class for 3D vectors.
Definition: V3D.h:34
V3D absoluteValue() const
Absolute value.
Definition: V3D.cpp:524
int maxCoeff()
Maximum absolute integer value.
Definition: V3D.cpp:509
std::shared_ptr< IPeaksWorkspace > IPeaksWorkspace_sptr
shared pointer to Mantid::API::IPeaksWorkspace
@ InOut
Both an input & output workspace.
Definition: Property.h:55