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 @@
#include "MantidAPI/Sample.h"
#include "MantidCrystal/IndexPeaks.h"
#include "MantidCrystal/IndexPeaksWithSatellites.h"
#include "MantidDataObjects/PeaksWorkspace.h"
#include "MantidGeometry/Crystal/IndexingUtils.h"
#include "MantidGeometry/Crystal/OrientedLattice.h"
......@@ -32,7 +33,8 @@ template <int NPeaks>
PeaksWorkspace_sptr
createPeaksWorkspace(const MinimalPeaksList<NPeaks> &testPeaksInfo,
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);
OrientedLattice lattice;
lattice.setUB(ub);
......@@ -49,6 +51,7 @@ createPeaksWorkspace(const MinimalPeaksList<NPeaks> &testPeaksInfo,
lattice.setModVec1(modVecOrDefault(0));
lattice.setModVec2(modVecOrDefault(1));
lattice.setModVec3(modVecOrDefault(2));
lattice.setCrossTerm(crossTerms);
}
peaksWS->mutableSample().setOrientedLattice(&lattice);
......@@ -71,28 +74,30 @@ PeaksWorkspace_sptr createTestPeaksWorkspaceMainReflOnly() {
// peaks from TOPAZ_3007.peaks: 0, 1, 2, 10, 42 with sign for Q swapped
// as we don't use the crystallographic convention
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(-3.04393, 3.05739, 2.03727)},
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);
}
PeaksWorkspace_sptr
createTestPeaksWorkspaceWithSatellites(const int maxOrder,
const std::vector<V3D> &modVectors) {
const std::vector<V3D> &modVectors,
const bool crossTerms = false) {
constexpr int npeaks{5};
const std::vector<double> ub = {0.269, -0.01, 0.033, 0.081, -0.191,
-0.039, 0.279, 0.347, -0.02};
constexpr std::array<MinimalPeak, npeaks> testPeaksInfo = {
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(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>
......@@ -132,9 +137,6 @@ public:
void test_no_commonUB_optimizes_UB_per_run_for_no_satellites() {
const auto ws = createTestPeaksWorkspaceMainReflOnly();
// Change some run numbers
ws->getPeak(0).setRunNumber(3008);
ws->getPeak(4).setRunNumber(3008);
auto alg = indexPeaks(
ws,
......@@ -175,15 +177,15 @@ public:
// Check the output properties
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
// fractional Miller indices
const V3D peak_0_hkl_d(4.00682, 0.97956, 5.99368); // first peak
const V3D peak_1_hkl_d(2.99838, -0.99760, 4.00141);
const V3D peak_2_hkl_d(3.99737, -0.99031, 5.00250);
const V3D peak_3_hkl_d(2.99419, 0.01736, 7.00538);
const V3D peak_4_hkl_d(2.00277, -4.00813, 6.99744); // last peak
const V3D peak_0_hkl_d(4.03064, 0.988507, 6.01094); // first peak
const V3D peak_1_hkl_d(3, -1, 4);
const V3D peak_2_hkl_d(4, -1, 5);
const V3D peak_3_hkl_d(3, -0, 7);
const V3D peak_4_hkl_d(1.97067, -4.02836, 6.97828); // last peak
const auto &peaks = ws->getPeaks();
V3D error = peak_0_hkl_d - peaks[0].getHKL();
......@@ -216,7 +218,7 @@ public:
// Check the output properties
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
// integer Miller indices
......@@ -253,10 +255,6 @@ public:
{"ToleranceForSatellite", sateTolerance}});
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,
{V3D(-1, 2, -9), V3D(0, 0, 0), V3D(-1, 1, -10),
V3D(0, 0, 0), V3D(0, 0, 0)});
......@@ -293,20 +291,139 @@ public:
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 =
createTestPeaksWorkspaceWithSatellites(1, {V3D(0.333, -0.667, 0.333)});
const auto sateTolerance{"1."};
const auto sateTolerance{"0.4"};
const auto alg =
indexPeaks(peaksWS, {{"CommonUBForAll", "1"},
{"ToleranceForSatellite", sateTolerance}});
assertNumberPeaksIndexed(*alg, 5, 2, 3);
assertIndexesAsExpected(*peaksWS,
{V3D(-1, 2, -9), V3D(0, 0, 0), V3D(-1, 1, -10),
V3D(0, 0, 0), V3D(0, 0, 0)});
assertErrorsAsExpected(*alg, 0.0140447, 0.0140447, 0.);
const std::vector<V3D> expectedHKL{V3D(-1, 2, -9), V3D(-0, 1, -3),
V3D(-1, 1, -10), V3D(1, 1, -1),
V3D(-0, 1, -5)};
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 -----------------------------
......@@ -328,12 +445,43 @@ public:
}
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,
const std::vector<V3D> &expectedIndexes) {
assert(static_cast<size_t>(peaksWS.getNumberPeaks()) ==
expectedIndexes.size());
for (auto i = 0u; i < expectedIndexes.size(); ++i) {
TS_ASSERT_EQUALS(expectedIndexes[i], peaksWS.getPeak(i).getHKL())
const std::vector<V3D> &expectedHKL,
const std::vector<V3D> &expectedIntHKL) {
assert(static_cast<size_t>(peaksWS.getNumberPeaks()) == expectedHKL.size());
assert(expectedIntHKL.size() == expectedHKL.size());
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:
void setBankName(std::string m_bankName);
void setHKL(double H, double K, double L) 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 setSamplePos(double samX, double samY, double samZ) override;
void setSamplePos(const Mantid::Kernel::V3D &XYZ) override;
......
......@@ -812,7 +812,7 @@ void Peak::setHKL(const Mantid::Kernel::V3D &HKL) {
*
* @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]));
}
......
......@@ -52,7 +52,7 @@ public:
virtual void setL(double m_L) = 0;
virtual void setHKL(double H, double K, double L) = 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(const Mantid::Kernel::V3D &XYZ) = 0;
virtual Mantid::Kernel::V3D getSamplePos() const = 0;
......@@ -95,7 +95,7 @@ public:
virtual void setPeakNumber(int m_PeakNumber) = 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 void setGoniometerMatrix(
......
......@@ -88,7 +88,7 @@ public:
/// Scan rotations to find UB that indexes peaks given lattice parameters
static double ScanFor_UB(Kernel::DblMatrix &UB,
const std::vector<Kernel::V3D> &q_vectors,
const UnitCell &lattice, double degrees_per_step,
const UnitCell &cell, double degrees_per_step,
double required_tolerance);
/// Get list of possible directions and lengths for real space unit cell
......@@ -187,7 +187,7 @@ public:
const std::vector<Kernel::V3D> &q_vectors,
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,
const std::vector<Kernel::V3D> &q_vectors,
double tolerance,
......@@ -200,6 +200,10 @@ public:
double tolerance,
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
static int GetIndexedPeaks_1D(const Kernel::V3D &direction,
const std::vector<Kernel::V3D> &q_vectors,
......
......@@ -2101,7 +2101,7 @@ void IndexingUtils::DiscardDuplicates(std::vector<V3D> &new_list,
/**
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) {
for (size_t i = 0; i < 3; i++) {
......@@ -2438,13 +2438,13 @@ int IndexingUtils::CalculateMillerIndices(const DblMatrix &UB,
}
/**
Calculate the Miller Indices for each of the specified Q vectors, using the
inverse of the specified UB matrix. If the peaks could not be indexed it is
Calculate the Miller Indices for the specified Q vector, using the
inverse of the specified UB matrix. If the peak could not be indexed it is
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
@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.
@param tolerance The maximum allowed distance between each component
of UB^(-1)*Q and the nearest integer value, required to
......@@ -2460,7 +2460,7 @@ bool IndexingUtils::CalculateMillerIndices(const DblMatrix &inverseUB,
const V3D &q_vector,
double tolerance,
V3D &miller_indices) {
miller_indices = inverseUB * q_vector / (2.0 * M_PI);
miller_indices = CalculateMillerIndices(inverseUB, q_vector);
if (ValidIndex(miller_indices, tolerance)) {
return true;
} else {
......@@ -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
reciprocal space, find the peaks that lie on these planes to within the
......
......@@ -653,6 +653,18 @@ public:
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);
}
void test_GetIndexedPeaks_1D() {
int correct_indices[] = {1, 4, 2, 0, 1, 3, 0, -1, 0, -1, -2, -3};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment