Commit dd41b6a7 authored by Martyn Gigg's avatar Martyn Gigg
Browse files

Add satellite indexing if main indexing fails

Refs #26829
parent 6a23a9f1
This diff is collapsed.
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "MantidAPI/Sample.h" #include "MantidAPI/Sample.h"
#include "MantidCrystal/IndexPeaks.h" #include "MantidCrystal/IndexPeaks.h"
#include "MantidCrystal/IndexPeaksWithSatellites.h"
#include "MantidDataObjects/PeaksWorkspace.h" #include "MantidDataObjects/PeaksWorkspace.h"
#include "MantidGeometry/Crystal/IndexingUtils.h" #include "MantidGeometry/Crystal/IndexingUtils.h"
#include "MantidGeometry/Crystal/OrientedLattice.h" #include "MantidGeometry/Crystal/OrientedLattice.h"
...@@ -32,7 +33,8 @@ template <int NPeaks> ...@@ -32,7 +33,8 @@ template <int NPeaks>
PeaksWorkspace_sptr PeaksWorkspace_sptr
createPeaksWorkspace(const MinimalPeaksList<NPeaks> &testPeaksInfo, createPeaksWorkspace(const MinimalPeaksList<NPeaks> &testPeaksInfo,
const std::vector<double> &ub, const int maxOrder = -1, const std::vector<double> &ub, const int maxOrder = -1,
const std::vector<V3D> &modVectors = std::vector<V3D>()) { const std::vector<V3D> &modVectors = std::vector<V3D>(),
const bool crossTerms = false) {
auto peaksWS = WorkspaceCreationHelper::createPeaksWorkspace(NPeaks); auto peaksWS = WorkspaceCreationHelper::createPeaksWorkspace(NPeaks);
OrientedLattice lattice; OrientedLattice lattice;
lattice.setUB(ub); lattice.setUB(ub);
...@@ -49,6 +51,7 @@ createPeaksWorkspace(const MinimalPeaksList<NPeaks> &testPeaksInfo, ...@@ -49,6 +51,7 @@ createPeaksWorkspace(const MinimalPeaksList<NPeaks> &testPeaksInfo,
lattice.setModVec1(modVecOrDefault(0)); lattice.setModVec1(modVecOrDefault(0));
lattice.setModVec2(modVecOrDefault(1)); lattice.setModVec2(modVecOrDefault(1));
lattice.setModVec3(modVecOrDefault(2)); lattice.setModVec3(modVecOrDefault(2));
lattice.setCrossTerm(crossTerms);
} }
peaksWS->mutableSample().setOrientedLattice(&lattice); peaksWS->mutableSample().setOrientedLattice(&lattice);
...@@ -71,28 +74,30 @@ PeaksWorkspace_sptr createTestPeaksWorkspaceMainReflOnly() { ...@@ -71,28 +74,30 @@ PeaksWorkspace_sptr createTestPeaksWorkspaceMainReflOnly() {
// peaks from TOPAZ_3007.peaks: 0, 1, 2, 10, 42 with sign for Q swapped // peaks from TOPAZ_3007.peaks: 0, 1, 2, 10, 42 with sign for Q swapped
// as we don't use the crystallographic convention // as we don't use the crystallographic convention
constexpr std::array<MinimalPeak, npeaks> testPeaksInfo = { constexpr std::array<MinimalPeak, npeaks> testPeaksInfo = {
MinimalPeak{3007, V3D(-3.52961, 3.13589, 1.0899)}, MinimalPeak{3008, V3D(-3.52961, 3.13589, 1.0899)},
MinimalPeak{3007, V3D(-2.42456, 2.29581, 1.71147)}, MinimalPeak{3007, V3D(-2.42456, 2.29581, 1.71147)},
MinimalPeak{3007, V3D(-3.04393, 3.05739, 2.03727)}, MinimalPeak{3007, V3D(-3.04393, 3.05739, 2.03727)},
MinimalPeak{3007, V3D(-4.02271, 2.4073, 1.62228)}, MinimalPeak{3007, V3D(-4.02271, 2.4073, 1.62228)},
MinimalPeak{3007, V3D(-4.04552, 1.59916, 3.71776)}}; MinimalPeak{3008, V3D(-4.04552, 1.59916, 3.71776)}};
return createPeaksWorkspace<npeaks>(testPeaksInfo, ub); return createPeaksWorkspace<npeaks>(testPeaksInfo, ub);
} }
PeaksWorkspace_sptr PeaksWorkspace_sptr
createTestPeaksWorkspaceWithSatellites(const int maxOrder, createTestPeaksWorkspaceWithSatellites(const int maxOrder,
const std::vector<V3D> &modVectors) { const std::vector<V3D> &modVectors,
const bool crossTerms = false) {
constexpr int npeaks{5}; constexpr int npeaks{5};
const std::vector<double> ub = {0.269, -0.01, 0.033, 0.081, -0.191, const std::vector<double> ub = {0.269, -0.01, 0.033, 0.081, -0.191,
-0.039, 0.279, 0.347, -0.02}; -0.039, 0.279, 0.347, -0.02};
constexpr std::array<MinimalPeak, npeaks> testPeaksInfo = { constexpr std::array<MinimalPeak, npeaks> testPeaksInfo = {
MinimalPeak{1, V3D(-3.691, -0.694, 3.762)}, // main MinimalPeak{1, V3D(-3.691, -0.694, 3.762)}, // main
MinimalPeak{1, V3D(-1.234, -0.225, 1.25212)}, // satellite MinimalPeak{2, V3D(-1.234, -0.225, 1.25212)}, // satellite
MinimalPeak{1, V3D(-3.824, 0.728, 1.711)}, // main MinimalPeak{1, V3D(-3.824, 0.728, 1.711)}, // main
MinimalPeak{1, V3D(0.872, -0.1998, 2.7476)}, // satellite MinimalPeak{1, V3D(0.872, -0.1998, 2.7476)}, // satellite
MinimalPeak{1, V3D(-1.54093, 0.129343, 1.445)}, // satellite MinimalPeak{2, V3D(-1.54093, 0.129343, 1.445)}, // satellite
}; };
return createPeaksWorkspace<npeaks>(testPeaksInfo, ub, maxOrder, modVectors); return createPeaksWorkspace<npeaks>(testPeaksInfo, ub, maxOrder, modVectors,
crossTerms);
} }
std::unique_ptr<IndexPeaks> std::unique_ptr<IndexPeaks>
...@@ -132,9 +137,6 @@ public: ...@@ -132,9 +137,6 @@ public:
void test_no_commonUB_optimizes_UB_per_run_for_no_satellites() { void test_no_commonUB_optimizes_UB_per_run_for_no_satellites() {
const auto ws = createTestPeaksWorkspaceMainReflOnly(); const auto ws = createTestPeaksWorkspaceMainReflOnly();
// Change some run numbers
ws->getPeak(0).setRunNumber(3008);
ws->getPeak(4).setRunNumber(3008);
auto alg = indexPeaks( auto alg = indexPeaks(
ws, ws,
...@@ -175,15 +177,15 @@ public: ...@@ -175,15 +177,15 @@ public:
// Check the output properties // Check the output properties
assertNumberPeaksIndexed(*alg, 5, 5, 0); assertNumberPeaksIndexed(*alg, 5, 5, 0);
assertErrorsAsExpected(*alg, 0.00639, 0.00639, 0.); assertErrorsAsExpected(*alg, 0.0088322, 0.0088322, 0.);
// spot check a few peaks for // spot check a few peaks for
// fractional Miller indices // fractional Miller indices
const V3D peak_0_hkl_d(4.00682, 0.97956, 5.99368); // first peak const V3D peak_0_hkl_d(4.03064, 0.988507, 6.01094); // first peak
const V3D peak_1_hkl_d(2.99838, -0.99760, 4.00141); const V3D peak_1_hkl_d(3, -1, 4);
const V3D peak_2_hkl_d(3.99737, -0.99031, 5.00250); const V3D peak_2_hkl_d(4, -1, 5);
const V3D peak_3_hkl_d(2.99419, 0.01736, 7.00538); const V3D peak_3_hkl_d(3, -0, 7);
const V3D peak_4_hkl_d(2.00277, -4.00813, 6.99744); // last peak const V3D peak_4_hkl_d(1.97067, -4.02836, 6.97828); // last peak
const auto &peaks = ws->getPeaks(); const auto &peaks = ws->getPeaks();
V3D error = peak_0_hkl_d - peaks[0].getHKL(); V3D error = peak_0_hkl_d - peaks[0].getHKL();
...@@ -216,7 +218,7 @@ public: ...@@ -216,7 +218,7 @@ public:
// Check the output properties // Check the output properties
assertNumberPeaksIndexed(*alg, 5, 5, 0); assertNumberPeaksIndexed(*alg, 5, 5, 0);
assertErrorsAsExpected(*alg, 0.00639, 0.00639, 0.); assertErrorsAsExpected(*alg, 0.0088322, 0.0088322, 0.);
// spot check a few peaks for // spot check a few peaks for
// integer Miller indices // integer Miller indices
...@@ -253,10 +255,6 @@ public: ...@@ -253,10 +255,6 @@ public:
{"ToleranceForSatellite", sateTolerance}}); {"ToleranceForSatellite", sateTolerance}});
assertNumberPeaksIndexed(*alg, 2, 2, 0); assertNumberPeaksIndexed(*alg, 2, 2, 0);
std::cerr << "\n";
for (int i = 0; i < peaksWS->getNumberPeaks(); ++i) {
std::cerr << peaksWS->getPeak(i).getHKL() << "\n";
}
assertIndexesAsExpected(*peaksWS, assertIndexesAsExpected(*peaksWS,
{V3D(-1, 2, -9), V3D(0, 0, 0), V3D(-1, 1, -10), {V3D(-1, 2, -9), V3D(0, 0, 0), V3D(-1, 1, -10),
V3D(0, 0, 0), V3D(0, 0, 0)}); V3D(0, 0, 0), V3D(0, 0, 0)});
...@@ -293,20 +291,139 @@ public: ...@@ -293,20 +291,139 @@ public:
assertErrorsAsExpected(*alg, 0.0140447, 0.0140447, 0.); assertErrorsAsExpected(*alg, 0.0140447, 0.0140447, 0.);
} }
void xtest_exec_with_common_ub_and_non_zero_mod_vectors_indexes_both() { void
test_exec_with_common_ub_and_non_zero_mod_vectors_indexes_both_with_roundhkl() {
const auto peaksWS = const auto peaksWS =
createTestPeaksWorkspaceWithSatellites(1, {V3D(0.333, -0.667, 0.333)}); createTestPeaksWorkspaceWithSatellites(1, {V3D(0.333, -0.667, 0.333)});
const auto sateTolerance{"1."}; const auto sateTolerance{"0.4"};
const auto alg = const auto alg =
indexPeaks(peaksWS, {{"CommonUBForAll", "1"}, indexPeaks(peaksWS, {{"CommonUBForAll", "1"},
{"ToleranceForSatellite", sateTolerance}}); {"ToleranceForSatellite", sateTolerance}});
assertNumberPeaksIndexed(*alg, 5, 2, 3); assertNumberPeaksIndexed(*alg, 5, 2, 3);
assertIndexesAsExpected(*peaksWS, const std::vector<V3D> expectedHKL{V3D(-1, 2, -9), V3D(-0, 1, -3),
{V3D(-1, 2, -9), V3D(0, 0, 0), V3D(-1, 1, -10), V3D(-1, 1, -10), V3D(1, 1, -1),
V3D(0, 0, 0), V3D(0, 0, 0)}); V3D(-0, 1, -5)};
assertErrorsAsExpected(*alg, 0.0140447, 0.0140447, 0.); const std::vector<V3D> expectedIntHKL{V3D(-1, 2, -9), V3D(-1, 1, -3),
V3D(-1, 1, -10), V3D(0, 1, -1),
V3D(-1, 1, -5)};
assertIndexesAsExpected(*peaksWS, expectedHKL, expectedIntHKL);
assertErrorsAsExpected(*alg, 0.1995736054, 0.0140447, 0.32325956);
// const auto peaksWS2 =
// createTestPeaksWorkspaceWithSatellites(1, {V3D(0.333, -0.667,
// 0.333)});
// Mantid::Crystal::IndexPeaksWithSatellites indexer;
// indexer.initialize();
// indexer.setProperty("PeaksWorkspace", peaksWS2);
// indexer.setProperty("CommonUBForAll", "1");
// indexer.setProperty("Tolerance", "0.15");
// indexer.setProperty("ToleranceForSatellite", "0.4");
// indexer.setProperty("RoundHKLs", "0");
// indexer.setProperty("MaxOrder", 1);
// indexer.setProperty("ModVector1", "0.333,-0.667,0.333");
// indexer.execute();
// std::cerr << "\n"
// << indexer.getPropertyValue("MainNumIndexed") << " "
// << indexer.getPropertyValue("MainError") << " "
// << indexer.getPropertyValue("SateNumIndexed") << " "
// << indexer.getPropertyValue("SatelliteError") << " "
// << indexer.getPropertyValue("AverageError") << "\n";
}
void
test_exec_with_common_ub_and_non_zero_mod_vectors_indexes_both_no_roundhkl() {
const auto peaksWS =
createTestPeaksWorkspaceWithSatellites(1, {V3D(0.333, -0.667, 0.333)});
const auto sateTolerance{"0.4"};
const auto alg =
indexPeaks(peaksWS, {{"CommonUBForAll", "1"},
{"ToleranceForSatellite", sateTolerance},
{"RoundHKLs", "0"}});
assertNumberPeaksIndexed(*alg, 5, 2, 3);
const std::vector<V3D> expectedHKL{
V3D(-0.997659, 2.00538, -9.06112), V3D(-0.332659, 0.666681, -3.03773),
V3D(-0.998436, 1.01132, -9.99745), V3D(0.668401, 0.662732, -1.04211),
V3D(-0.333695, 0.671228, -4.50819)};
const std::vector<V3D> expectedIntHKL{V3D(-1, 2, -9), V3D(-1, 1, -3),
V3D(-1, 1, -10), V3D(0, 1, -1),
V3D(-1, 1, -5)};
assertIndexesAsExpected(*peaksWS, expectedHKL, expectedIntHKL);
assertErrorsAsExpected(*alg, 0.1995736054, 0.0140447, 0.3232596);
}
void
test_exec_no_common_ub_and_non_zero_mod_vectors_indexes_both_no_roundhkl() {
const auto peaksWS =
createTestPeaksWorkspaceWithSatellites(1, {V3D(0.333, -0.667, 0.333)});
const auto sateTolerance{"0.4"};
const auto alg =
indexPeaks(peaksWS, {{"CommonUBForAll", "0"},
{"Tolerance", "0.15"},
{"ToleranceForSatellite", sateTolerance},
{"RoundHKLs", "0"}});
assertNumberPeaksIndexed(*alg, 5, 2, 3);
const std::vector<V3D> expectedHKL{
V3D(-0.997659, 2.00538, -9.06112), V3D(-0.332659, 0.666681, -3.03773),
V3D(-0.998436, 1.01132, -9.99745), V3D(0.668401, 0.662732, -1.04211),
V3D(-0.333695, 0.671228, -4.50819)};
const std::vector<V3D> expectedIntHKL{V3D(-1, 2, -9), V3D(-1, 1, -3),
V3D(-1, 1, -10), V3D(0, 1, -1),
V3D(-1, 1, -5)};
assertIndexesAsExpected(*peaksWS, expectedHKL, expectedIntHKL);
assertErrorsAsExpected(*alg, 0.1995736, 0.0140447, 0.323256);
}
void test_exec_with_three_mod_vectors_no_cross_terms() {
const auto peaksWS = createTestPeaksWorkspaceWithSatellites(
1,
{V3D(-0.1, 0.1, 0.1), V3D(0.1, 0.2, -0.3), V3D(0.333, 0.667, -0.333)});
const auto alg = indexPeaks(peaksWS, {{"CommonUBForAll", "0"},
{"ToleranceForSatellite", "0.4"},
{"RoundHKLs", "0"}});
assertNumberPeaksIndexed(*alg, 5, 2, 3);
const std::vector<V3D> expectedHKL{
V3D(-0.997659, 2.00538, -9.06112), V3D(-0.332659, 0.666681, -3.03773),
V3D(-0.998436, 1.01132, -9.99745), V3D(0.668401, 0.662732, -1.04211),
V3D(-0.333695, 0.671228, -4.50819)};
const std::vector<V3D> expectedIntHKL{V3D(-1, 2, -9), V3D(-1, -0, -3),
V3D(-1, 1, -10), V3D(0, -0, -1),
V3D(-1, 0, -4)};
assertIndexesAsExpected(*peaksWS, expectedHKL, expectedIntHKL);
assertErrorsAsExpected(*alg, 0.12383213164, 0.0140447, 0.1970237718);
}
void test_exec_with_three_mod_vectors_and_cross_terms() {
const auto peaksWS = createTestPeaksWorkspaceWithSatellites(
1,
{V3D(0.333, 0.667, -0.333), V3D(-0.333, 0.667, 0.333),
V3D(0.333, -0.667, 0.333)},
true);
const auto alg = indexPeaks(peaksWS, {{"CommonUBForAll", "0"},
{"ToleranceForSatellite", "0.2"},
{"RoundHKLs", "0"}});
assertNumberPeaksIndexed(*alg, 5, 2, 3);
const std::vector<V3D> expectedHKL{
V3D(-0.997659, 2.00538, -9.06112), V3D(-0.332659, 0.666681, -3.03773),
V3D(-0.998436, 1.01132, -9.99745), V3D(0.668401, 0.662732, -1.04211),
V3D(-0.333695, 0.671228, -4.50819)};
const std::vector<V3D> expectedIntHKL{V3D(-1, 2, -9), V3D(-1, 2, -3),
V3D(-1, 1, -10), V3D(0, 2, -1),
V3D(-0, 0, -5)};
assertIndexesAsExpected(*peaksWS, expectedHKL, expectedIntHKL);
assertErrorsAsExpected(*alg, 0.02236871, 0.0140447, 0.027918076);
} }
// --------------------------- Failure tests ----------------------------- // --------------------------- Failure tests -----------------------------
...@@ -328,12 +445,43 @@ public: ...@@ -328,12 +445,43 @@ public:
} }
private: private:
// Check that all main indexed peaks match as expected
void assertIndexesAsExpected(const PeaksWorkspace_sptr::element_type &peaksWS,
const std::vector<V3D> &expectedHKL) {
assert(static_cast<size_t>(peaksWS.getNumberPeaks()) == expectedHKL.size());
for (auto i = 0u; i < expectedHKL.size(); ++i) {
const auto &expectedIndex = expectedHKL[i];
TSM_ASSERT_DELTA("Unexpected index for HKL at index " + std::to_string(i),
expectedIndex.norm(), peaksWS.getPeak(i).getHKL().norm(),
1e-5)
const V3D expectedIntHKL{std::round(expectedIndex[0]),
std::round(expectedIndex[1]),
std::round(expectedIndex[2])};
TSM_ASSERT_EQUALS("Unexpected index "
"for IntHKL at "
"index " +
std::to_string(i),
expectedIntHKL, peaksWS.getPeak(i).getIntHKL())
}
}
// Check that all main/satellite indexed peaks match as expected
void assertIndexesAsExpected(const PeaksWorkspace_sptr::element_type &peaksWS, void assertIndexesAsExpected(const PeaksWorkspace_sptr::element_type &peaksWS,
const std::vector<V3D> &expectedIndexes) { const std::vector<V3D> &expectedHKL,
assert(static_cast<size_t>(peaksWS.getNumberPeaks()) == const std::vector<V3D> &expectedIntHKL) {
expectedIndexes.size()); assert(static_cast<size_t>(peaksWS.getNumberPeaks()) == expectedHKL.size());
for (auto i = 0u; i < expectedIndexes.size(); ++i) { assert(expectedIntHKL.size() == expectedHKL.size());
TS_ASSERT_EQUALS(expectedIndexes[i], peaksWS.getPeak(i).getHKL())
for (auto i = 0u; i < expectedHKL.size(); ++i) {
TSM_ASSERT_DELTA("Unexpected index for HKL at index " + std::to_string(i),
expectedHKL[i].norm(),
peaksWS.getPeak(i).getHKL().norm(), 1e-5)
TSM_ASSERT_DELTA("Unexpected index "
"for IntHKL at "
"index " +
std::to_string(i),
expectedIntHKL[i].norm(),
peaksWS.getPeak(i).getIntHKL().norm(), 1e-8)
} }
} }
......
...@@ -113,7 +113,7 @@ public: ...@@ -113,7 +113,7 @@ public:
void setBankName(std::string m_bankName); void setBankName(std::string m_bankName);
void setHKL(double H, double K, double L) override; void setHKL(double H, double K, double L) override;
void setHKL(const Mantid::Kernel::V3D &HKL) override; void setHKL(const Mantid::Kernel::V3D &HKL) override;
void setIntHKL(const Mantid::Kernel::V3D HKL) override; void setIntHKL(const Kernel::V3D &HKL) override;
void setIntMNP(const Mantid::Kernel::V3D &MNP) override; void setIntMNP(const Mantid::Kernel::V3D &MNP) override;
void setSamplePos(double samX, double samY, double samZ) override; void setSamplePos(double samX, double samY, double samZ) override;
void setSamplePos(const Mantid::Kernel::V3D &XYZ) override; void setSamplePos(const Mantid::Kernel::V3D &XYZ) override;
......
...@@ -812,7 +812,7 @@ void Peak::setHKL(const Mantid::Kernel::V3D &HKL) { ...@@ -812,7 +812,7 @@ void Peak::setHKL(const Mantid::Kernel::V3D &HKL) {
* *
* @param HKL :: vector with integer x,y,z -> h,k,l * @param HKL :: vector with integer x,y,z -> h,k,l
*/ */
void Peak::setIntHKL(V3D HKL) { void Peak::setIntHKL(const V3D &HKL) {
m_intHKL = V3D(std::round(HKL[0]), std::round(HKL[1]), std::round(HKL[2])); m_intHKL = V3D(std::round(HKL[0]), std::round(HKL[1]), std::round(HKL[2]));
} }
......
...@@ -52,7 +52,7 @@ public: ...@@ -52,7 +52,7 @@ public:
virtual void setL(double m_L) = 0; virtual void setL(double m_L) = 0;
virtual void setHKL(double H, double K, double L) = 0; virtual void setHKL(double H, double K, double L) = 0;
virtual void setHKL(const Mantid::Kernel::V3D &HKL) = 0; virtual void setHKL(const Mantid::Kernel::V3D &HKL) = 0;
virtual void setIntHKL(const Mantid::Kernel::V3D HKL) = 0; virtual void setIntHKL(const Mantid::Kernel::V3D &HKL) = 0;
virtual void setSamplePos(double samX, double samY, double samZ) = 0; virtual void setSamplePos(double samX, double samY, double samZ) = 0;
virtual void setSamplePos(const Mantid::Kernel::V3D &XYZ) = 0; virtual void setSamplePos(const Mantid::Kernel::V3D &XYZ) = 0;
virtual Mantid::Kernel::V3D getSamplePos() const = 0; virtual Mantid::Kernel::V3D getSamplePos() const = 0;
...@@ -95,7 +95,7 @@ public: ...@@ -95,7 +95,7 @@ public:
virtual void setPeakNumber(int m_PeakNumber) = 0; virtual void setPeakNumber(int m_PeakNumber) = 0;
virtual Mantid::Kernel::V3D getIntMNP() const = 0; virtual Mantid::Kernel::V3D getIntMNP() const = 0;
virtual void setIntMNP(const Mantid::Kernel::V3D & MNP) = 0; virtual void setIntMNP(const Mantid::Kernel::V3D &MNP) = 0;
virtual Mantid::Kernel::Matrix<double> getGoniometerMatrix() const = 0; virtual Mantid::Kernel::Matrix<double> getGoniometerMatrix() const = 0;
virtual void setGoniometerMatrix( virtual void setGoniometerMatrix(
......
...@@ -88,7 +88,7 @@ public: ...@@ -88,7 +88,7 @@ public:
/// Scan rotations to find UB that indexes peaks given lattice parameters /// Scan rotations to find UB that indexes peaks given lattice parameters
static double ScanFor_UB(Kernel::DblMatrix &UB, static double ScanFor_UB(Kernel::DblMatrix &UB,
const std::vector<Kernel::V3D> &q_vectors, const std::vector<Kernel::V3D> &q_vectors,
const UnitCell &lattice, double degrees_per_step, const UnitCell &cell, double degrees_per_step,
double required_tolerance); double required_tolerance);
/// Get list of possible directions and lengths for real space unit cell /// Get list of possible directions and lengths for real space unit cell
...@@ -187,7 +187,7 @@ public: ...@@ -187,7 +187,7 @@ public:
const std::vector<Kernel::V3D> &q_vectors, const std::vector<Kernel::V3D> &q_vectors,
double tolerance); double tolerance);
/// Given a UB, get list of Miller indices for specifed Qs /// Given a UB, get list of Miller indices for specifed Qs and tolerance
static int CalculateMillerIndices(const Kernel::DblMatrix &UB, static int CalculateMillerIndices(const Kernel::DblMatrix &UB,
const std::vector<Kernel::V3D> &q_vectors, const std::vector<Kernel::V3D> &q_vectors,
double tolerance, double tolerance,
...@@ -200,6 +200,10 @@ public: ...@@ -200,6 +200,10 @@ public:
double tolerance, double tolerance,
Kernel::V3D &miller_indices); Kernel::V3D &miller_indices);
/// Given a UB, calculate the miller indices for given q vector
static Kernel::V3D CalculateMillerIndices(const Kernel::DblMatrix &inverseUB,
const Kernel::V3D &q_vector);
/// Get lists of indices and Qs for peaks indexed in the specified direction /// Get lists of indices and Qs for peaks indexed in the specified direction
static int GetIndexedPeaks_1D(const Kernel::V3D &direction, static int GetIndexedPeaks_1D(const Kernel::V3D &direction,
const std::vector<Kernel::V3D> &q_vectors, const std::vector<Kernel::V3D> &q_vectors,
......
...@@ -2101,7 +2101,7 @@ void IndexingUtils::DiscardDuplicates(std::vector<V3D> &new_list, ...@@ -2101,7 +2101,7 @@ void IndexingUtils::DiscardDuplicates(std::vector<V3D> &new_list,
/** /**
Round all of the components of the V3D to the nearest integer. Round all of the components of the V3D to the nearest integer.
@param hkl_list Vector of V3D objects whose components will be rounded. @param hkl V3D object whose components will be rounded.
*/ */
void IndexingUtils::RoundHKL(Mantid::Kernel::V3D &hkl) { void IndexingUtils::RoundHKL(Mantid::Kernel::V3D &hkl) {
for (size_t i = 0; i < 3; i++) { for (size_t i = 0; i < 3; i++) {
...@@ -2438,17 +2438,17 @@ int IndexingUtils::CalculateMillerIndices(const DblMatrix &UB, ...@@ -2438,17 +2438,17 @@ int IndexingUtils::CalculateMillerIndices(const DblMatrix &UB,
} }
/** /**
Calculate the Miller Indices for each of the specified Q vectors, using the Calculate the Miller Indices for the specified Q vector, using the
inverse of the specified UB matrix. If the peaks could not be indexed it is inverse of the specified UB matrix. If the peak could not be indexed it is
set to (0,0,0) set to (0,0,0)
@param UB A 3x3 matrix of doubles holding the inverse UB matrix. @param inverseUB A 3x3 matrix of doubles holding the inverse UB matrix.
The matrix is not checked for validity The matrix is not checked for validity
@param q_vectors std::vector of V3D objects that contains the list of @param q_vector std::vector of V3D objects that contains the list of
q_vectors that are to be indexed. q_vectors that are to be indexed.
@param tolerance The maximum allowed distance between each component @param tolerance The maximum allowed distance between each component
of UB^(-1)*Q and the nearest integer value, required to of UB^(-1)*Q and the nearest integer value, required to
to count the peak as indexed by UB. to count the peak as indexed by UB.
@param miller_indices This vector returns a list of Miller Indices, with @param miller_indices This vector returns a list of Miller Indices, with
one entry for each given Q vector. one entry for each given Q vector.
...@@ -2460,7 +2460,7 @@ bool IndexingUtils::CalculateMillerIndices(const DblMatrix &inverseUB, ...@@ -2460,7 +2460,7 @@ bool IndexingUtils::CalculateMillerIndices(const DblMatrix &inverseUB,
const V3D &q_vector, const V3D &q_vector,
double tolerance, double tolerance,
V3D &miller_indices) { V3D &miller_indices) {
miller_indices = inverseUB * q_vector / (2.0 * M_PI); miller_indices = CalculateMillerIndices(inverseUB, q_vector);
if (ValidIndex(miller_indices, tolerance)) { if (ValidIndex(miller_indices, tolerance)) {
return true; return true;
} else { } else {
...@@ -2469,6 +2469,22 @@ bool IndexingUtils::CalculateMillerIndices(const DblMatrix &inverseUB, ...@@ -2469,6 +2469,22 @@ bool IndexingUtils::CalculateMillerIndices(const DblMatrix &inverseUB,
} }
} }
/**
Calculate the Miller Indices for the specified Q vector, using the
inverse of the specified UB matrix.
@param inverseUB A 3x3 matrix of doubles holding the inverse UB matrix.
The matrix is not checked for validity
@param q_vector V3D object containing Q vector in sample frame
@return The indexes of the given peak. They have not been tested for validity
*/
V3D IndexingUtils::CalculateMillerIndices(const DblMatrix &inverseUB,
const V3D &q_vector) {
return inverseUB * q_vector / (2.0 * M_PI);
}
/** /**
Given one plane normal direction for a family of parallel planes in Given one plane normal direction for a family of parallel planes in
reciprocal space, find the peaks that lie on these planes to within the reciprocal space, find the peaks that lie on these planes to within the
......
...@@ -653,6 +653,18 @@ public: ...@@ -653,6 +653,18 @@ public:
TS_ASSERT_DELTA(diff, 0, 0.1); TS_ASSERT_DELTA(diff, 0, 0.1);
} }
void test_CalculateMillerIndicesSingleQ_No_Tolerance() {
const auto q_vectors = getNatroliteQs();
const auto indices = getNatroliteIndices();
auto UB = getNatroliteUB();
UB.Invert();
const V3D millerIndices =
IndexingUtils::CalculateMillerIndices(UB, q_vectors[0]);
const auto diff = (indices[0] - millerIndices).norm();
TS_ASSERT_DELTA(diff, 0, 0.1);
}