AnalyzeIndexing: Move mosaicity to a dedicated function + for rotation indexing always consider as indexed
Some checks failed
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 12m10s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m5s
Build Packages / Generate python client (push) Successful in 30s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m59s
Build Packages / build:rpm (rocky8) (push) Successful in 13m57s
Build Packages / Create release (push) Has been skipped
Build Packages / Build documentation (push) Successful in 34s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m19s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 14m20s
Build Packages / build:rpm (rocky9) (push) Successful in 14m32s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m47s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 7m13s
Build Packages / Unit tests (push) Has been cancelled

This commit is contained in:
2025-12-18 12:39:19 +01:00
parent 1e48de453d
commit 068416c470
3 changed files with 55 additions and 49 deletions

View File

@@ -188,7 +188,8 @@ void IndexAndRefine::ProcessImage(DataMessage &msg,
if (!outcome.lattice_candidate)
return;
if (!AnalyzeIndexing(msg, outcome.experiment, *outcome.lattice_candidate, outcome.experiment.GetGoniometer()))
if (!AnalyzeIndexing(msg, outcome.experiment, *outcome.lattice_candidate,
outcome.experiment.GetGoniometer(), rotation_indexer.get() != nullptr))
return;
msg.lattice_type = outcome.symmetry;

View File

@@ -116,12 +116,58 @@ namespace {
return rad_to_deg(best_phi);
}
std::optional<float> CalcMosaicity(const DiffractionExperiment& experiment,
const std::vector<SpotToSave> &spots,
const Coord &astar, const Coord &bstar, const Coord &cstar) {
const auto &axis = experiment.GetGoniometer();
if (axis.has_value()) {
const Coord w = axis->GetAxis().Normalize();
const Coord S0 = experiment.GetScatteringVector();
const float wedge_deg = axis->GetWedge_deg();
const float start_deg = axis->GetStart_deg();
const float inc_deg = axis->GetIncrement_deg();
double sum_sq = 0.0;
int count = 0;
for (const auto &s: spots) {
if (!s.indexed)
continue;
// Observed angle: use frame center
const float image_center = static_cast<float>(s.image) + 0.5f;
const float phi_obs_deg = start_deg + inc_deg * image_center;
// g0 at phi=0 assumption
const Coord g0 = astar * static_cast<float>(s.h)
+ bstar * static_cast<float>(s.k)
+ cstar * static_cast<float>(s.l);
// Local solve window: +/- 1 wedge (easy/robust first try)
const auto phi_pred_deg_opt = predict_phi_deg_local(g0, S0, w, phi_obs_deg, wedge_deg);
if (!phi_pred_deg_opt.has_value())
continue;
float dphi = wrap_deg_pm180(phi_obs_deg - phi_pred_deg_opt.value());
sum_sq += static_cast<double>(dphi) * static_cast<double>(dphi);
count++;
}
if (count > 0) {
return static_cast<float>(std::sqrt(sum_sq / static_cast<double>(count)));
}
}
return std::nullopt;
}
} // namespace
bool AnalyzeIndexing(DataMessage &message,
const DiffractionExperiment &experiment,
const CrystalLattice &latt,
const std::optional<GoniometerAxis> &rotation_axis) {
const std::optional<GoniometerAxis> &rotation_axis,
bool rotation_indexed) {
std::vector<uint8_t> indexed_spots(message.spots.size());
// Check spots
@@ -172,8 +218,9 @@ bool AnalyzeIndexing(DataMessage &message,
nspots_ref++;
}
if (nspots_indexed >= viable_cell_min_spots
&& nspots_indexed >= std::lround(min_percentage_spots * nspots_ref)) {
if (rotation_indexed
|| (nspots_indexed >= viable_cell_min_spots
&& nspots_indexed >= std::lround(min_percentage_spots * nspots_ref))) {
auto uc = latt.GetUnitCell();
if (!ok(uc.a) || !ok(uc.b) || !ok(uc.c) || !ok(uc.alpha) || !ok(uc.beta) || !ok(uc.gamma))
return false;
@@ -187,50 +234,7 @@ bool AnalyzeIndexing(DataMessage &message,
message.spot_count_indexed = nspots_indexed;
message.indexing_lattice = latt;
message.indexing_unit_cell = latt.GetUnitCell();
message.mosaicity_deg = std::nullopt;
if (rotation_axis.has_value()) {
const auto gon_opt = experiment.GetGoniometer();
if (gon_opt.has_value()) {
const auto &gon = *gon_opt;
const Coord w = rotation_axis->GetAxis().Normalize();
const Coord S0 = geom.GetScatteringVector();
const float wedge_deg = gon.GetWedge_deg();
const float start_deg = gon.GetStart_deg();
const float inc_deg = gon.GetIncrement_deg();
double sum_sq = 0.0;
int count = 0;
for (const auto &s: message.spots) {
if (!s.indexed)
continue;
// Observed angle: use frame center
const float image_center = static_cast<float>(s.image) + 0.5f;
const float phi_obs_deg = start_deg + inc_deg * image_center;
// g0 at phi=0 assumption
const Coord g0 = astar * static_cast<float>(s.h)
+ bstar * static_cast<float>(s.k)
+ cstar * static_cast<float>(s.l);
// Local solve window: +/- 1 wedge (easy/robust first try)
const auto phi_pred_deg_opt = predict_phi_deg_local(g0, S0, w, phi_obs_deg, wedge_deg);
if (!phi_pred_deg_opt.has_value())
continue;
float dphi = wrap_deg_pm180(phi_obs_deg - phi_pred_deg_opt.value());
sum_sq += static_cast<double>(dphi) * static_cast<double>(dphi);
count++;
}
if (count > 0) {
message.mosaicity_deg = static_cast<float>(std::sqrt(sum_sq / static_cast<double>(count)));
}
}
}
message.mosaicity_deg = CalcMosaicity(experiment, message.spots, astar, bstar, cstar);
return true;
}

View File

@@ -13,7 +13,8 @@ constexpr static float min_percentage_spots = 0.20f;
bool AnalyzeIndexing(DataMessage &message,
const DiffractionExperiment &experiment,
const CrystalLattice &latt,
const std::optional<GoniometerAxis> &rotation_axis);
const std::optional<GoniometerAxis> &rotation_axis,
bool rotation_indexed);
#endif //JFJOCH_ANALYZEINDEXING_H