The severity took theta_max from the still's own spot resolution - the 95th percentile of |q| - so a weak, attenuated grid still reaching 3 A scored a row at an 11 deg miss-angle as exactly 0, while the real sweep collected afterwards at the detector's 1.8 A loses a fifth of a cone that wide. The number exists to decide whether that sweep needs a second orientation, so the cone it must describe is the sweep's, and the still's spot list systematically understates it in the one direction that produces silent misses. theta_max is now asin(lambda/2d) at the geometric resolution of the setup - the detector corner at the recorded distance and wavelength. That is an upper bound on any sweep collected without moving the detector, it is available on every frame however weak, and where it overstates what the sweep will reach it errs towards reporting loss, which is the cheap error. Computed once per Setup in the Indexer base rather than per frame in the FFT implementation, because nothing about it is specific to either the frame or the indexer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
36 lines
1.5 KiB
C++
36 lines
1.5 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include "Indexer.h"
|
|
|
|
void Indexer::Setup(const DiffractionExperiment& experiment) {
|
|
geom = experiment.GetDiffractionGeometry();
|
|
indexing_tolerance = experiment.GetIndexingSettings().GetTolerance();
|
|
dist_tolerance_vs_reference = experiment.GetIndexingSettings().GetUnitCellDistTolerance();
|
|
viable_cell_min_spots = experiment.GetIndexingSettings().GetViableCellMinSpots();
|
|
index_ice_rings = experiment.GetIndexingSettings().GetIndexIceRings();
|
|
wavelength_A = experiment.GetWavelength_A();
|
|
spindle_axis = {};
|
|
if (const auto goniometer = experiment.GetGoniometer())
|
|
spindle_axis = goniometer->GetAxis();
|
|
spindle_theta_max_deg = SpindleThetaMax_deg(wavelength_A, experiment.GetDetectorMaxResolution_A());
|
|
SetupUnitCell(experiment.GetUnitCell());
|
|
}
|
|
|
|
IndexerResult Indexer::Run(const std::vector<Coord> &coord) {
|
|
IndexerResult ret;
|
|
auto start = std::chrono::steady_clock::now();
|
|
ret.lattice = RunInternal(coord, coord.size());
|
|
|
|
auto end = std::chrono::steady_clock::now();
|
|
std::chrono::duration<float> duration = end - start;
|
|
ret.indexing_time_s = duration.count();
|
|
ret.executed = true;
|
|
if (const auto severity = GetSpindleSeverity()) {
|
|
ret.spindle_blind_fraction = severity->score;
|
|
ret.spindle_row_length_A = severity->row_length_A;
|
|
ret.spindle_miss_angle_deg = severity->miss_angle_deg;
|
|
}
|
|
return ret;
|
|
}
|