Files
Jungfraujoch/image_analysis/indexing/AnalyzeIndexing.cpp
2025-09-21 19:27:51 +02:00

87 lines
3.0 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include <cstdint>
#include <vector>
#include "AnalyzeIndexing.h"
#include "FitProfileRadius.h"
inline bool ok(float x) {
if (!std::isfinite(x))
return false;
if (x < 0.0)
return false;
return true;
};
bool AnalyzeIndexing(DataMessage &message, const DiffractionExperiment &experiment, const CrystalLattice &latt) {
size_t nspots = message.spots.size();
uint64_t indexed_spot_count = 0;
std::vector<uint8_t> indexed_spots(nspots);
std::vector<float> distance_ewald_sphere(nspots);
// Check spots
const Coord a = latt.Vec0();
const Coord b = latt.Vec1();
const Coord c = latt.Vec2();
const Coord astar = latt.Astar();
const Coord bstar = latt.Bstar();
const Coord cstar = latt.Cstar();
const auto geom = experiment.GetDiffractionGeometry();
const auto indexing_tolerance = experiment.GetIndexingSettings().GetTolerance();
const auto viable_cell_min_spots = experiment.GetIndexingSettings().GetViableCellMinSpots();
// identify indexed spots
for (int i = 0; i < message.spots.size(); i++) {
auto recip = message.spots[i].ReciprocalCoord(geom);
float h_fp = recip * a;
float k_fp = recip * b;
float l_fp = recip * c;
float h_frac = h_fp - std::round(h_fp);
float k_frac = k_fp - std::round(k_fp);
float l_frac = l_fp - std::round(l_fp);
float norm_sq = h_frac * h_frac + k_frac * k_frac + l_frac * l_frac;
Coord recip_pred = std::round(h_fp) * astar + std::round(k_fp) * bstar + std::round(l_fp) * cstar;
// See indexing_peak_check() in peaks.c in CrystFEL
if (norm_sq < indexing_tolerance * indexing_tolerance) {
indexed_spot_count++;
indexed_spots[i] = 1;
message.spots[i].dist_ewald_sphere = geom.DistFromEwaldSphere(recip_pred);
message.spots[i].h = std::lround(h_fp);
message.spots[i].k = std::lround(k_fp);
message.spots[i].l = std::lround(l_fp);
}
}
auto spot_count_threshold = std::max<int64_t>(viable_cell_min_spots, std::lround(min_percentage_spots * nspots));
if (indexed_spot_count >= spot_count_threshold) {
auto uc = latt.GetUnitCell();
if (!ok(uc.a) || !ok(uc.b) || !ok(uc.c) || !ok(uc.alpha) || !ok(uc.beta) || !ok(uc.gamma))
return {};
message.indexing_result = true;
assert(indexed_spots.size() == message.spots.size());
for (int i = 0; i < message.spots.size(); i++)
message.spots[i].indexed = indexed_spots[i];
message.profile_radius = FitProfileRadius(message.spots);
message.spot_count_indexed = indexed_spot_count;
message.indexing_lattice = latt;
message.indexing_unit_cell = latt.GetUnitCell();
return true;
}
message.indexing_result = false;
return false;
}