Add possible reflection and completeness to MergeStatistics
Build Packages / Unit tests (push) Failing after 7m12s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Failing after 8m58s
Build Packages / build:rpm (rocky8_nocuda) (push) Failing after 9m10s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Failing after 10m19s
Build Packages / build:rpm (rocky9_nocuda) (push) Failing after 10m24s
Build Packages / build:rpm (rocky8_sls9) (push) Failing after 11m47s
Build Packages / build:rpm (rocky9_sls9) (push) Failing after 12m11s
Build Packages / build:rpm (rocky8) (push) Failing after 12m9s
Build Packages / Generate python client (push) Successful in 1m33s
Build Packages / build:rpm (rocky9) (push) Failing after 7m35s
Build Packages / Create release (push) Skipped
Build Packages / Build documentation (push) Successful in 2m8s
Build Packages / build:rpm (ubuntu2404) (push) Failing after 9m13s
Build Packages / build:rpm (ubuntu2204) (push) Failing after 9m28s
Build Packages / XDS test (JFJoch plugin) (push) Failing after 8m44s
Build Packages / XDS test (durin plugin) (push) Successful in 10m26s
Build Packages / XDS test (neggia plugin) (push) Successful in 9m10s
Build Packages / DIALS test (push) Successful in 13m37s

This commit is contained in:
2026-05-17 20:00:32 +02:00
parent 39fef1bcef
commit 1d3ccdaa00
7 changed files with 153 additions and 28 deletions
+81 -24
View File
@@ -9,6 +9,8 @@
#include <random>
#include <unordered_map>
#include <gemmi/reciproc.hpp>
#include "../../common/ResolutionShells.h"
#include "HKLKey.h"
@@ -165,11 +167,58 @@ std::vector<MergedReflection> MergeAll(const DiffractionExperiment &x,
return out;
}
struct ShellAccum {
int total_obs = 0;
int unique = 0;
int possible = 0;
double sum_i_over_sigma = 0.0;
int n_i_over_sigma = 0;
double sum_x = 0.0;
double sum_y = 0.0;
double sum_x2 = 0.0;
double sum_y2 = 0.0;
double sum_xy = 0.0;
int n_cc_half = 0;
};
void CalcPossibleReflections(const DiffractionExperiment &x,
const UnitCell &cell,
double d_min,
double d_max,
const ResolutionShells &shells,
std::vector<ShellAccum> &acc) {
gemmi::UnitCell gemmi_cell = cell;
const gemmi::SpaceGroup *sg = gemmi::find_spacegroup_by_number(x.GetSpaceGroupNumber().value_or(1));
// Generate unique reflections
std::vector<gemmi::Miller> possible_hkls = gemmi::make_miller_vector(gemmi_cell, sg, d_min, d_max, true);
CrystalLattice lattice(cell);
const auto astar = lattice.Astar();
const auto bstar = lattice.Bstar();
const auto cstar = lattice.Cstar();
for (const auto& hkl: possible_hkls) {
const auto q = hkl[0] * astar + hkl[1] * bstar + hkl[2] * cstar;
const auto qlen = q.Length();
if (qlen < 1e-6)
continue;
const auto d = 1.0 / qlen;
const auto shell = shells.GetShell(d);
if (!shell.has_value())
continue;
const int s = *shell;
if (s >= 0 && s < acc.size())
acc[s].possible++;
}
}
MergeStatistics MergeStats(const DiffractionExperiment &x,
const std::vector<MergedReflection> &merged,
const std::vector<std::vector<Reflection> > &reflections,
const UnitCell &cell,
const std::vector<uint8_t> &merge_mask) {
if (!merge_mask.empty() && merge_mask.size() != reflections.size())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Merge mask size mismatch");
@@ -204,22 +253,10 @@ MergeStatistics MergeStats(const DiffractionExperiment &x,
const auto shell_mean_1_d2 = shells.GetShellMeanOneOverResSq();
const auto shell_min_res = shells.GetShellMinRes();
struct ShellAccum {
int total_obs = 0;
int unique = 0;
double sum_i_over_sigma = 0.0;
int n_i_over_sigma = 0;
double sum_x = 0.0;
double sum_y = 0.0;
double sum_x2 = 0.0;
double sum_y2 = 0.0;
double sum_xy = 0.0;
int n_cc_half = 0;
};
std::vector<ShellAccum> acc(n_shells);
CalcPossibleReflections(x, cell, d_min_pad, d_max_pad, shells, acc);
for (const auto &m: merged) {
const auto shell = shells.GetShell(m.d);
if (!shell.has_value())
@@ -283,6 +320,7 @@ MergeStatistics MergeStats(const DiffractionExperiment &x,
ss.d_max = s == 0 ? d_max_pad : shell_min_res[s - 1];
ss.total_observations = sa.total_obs;
ss.unique_reflections = sa.unique;
ss.possible_unique_reflections = sa.possible;
ss.mean_i_over_sigma = sa.n_i_over_sigma > 0
? sa.sum_i_over_sigma / sa.n_i_over_sigma
: 0.0;
@@ -305,6 +343,7 @@ MergeStatistics MergeStats(const DiffractionExperiment &x,
overall.d_min = d_min;
overall.d_max = d_max;
int all_possible = 0;
int all_unique = 0;
double sum_i_over_sigma = 0.0;
int n_i_over_sigma = 0;
@@ -319,6 +358,7 @@ MergeStatistics MergeStats(const DiffractionExperiment &x,
for (const auto &sa: acc) {
overall.total_observations += sa.total_obs;
all_unique += sa.unique;
all_possible += sa.possible;
sum_i_over_sigma += sa.sum_i_over_sigma;
n_i_over_sigma += sa.n_i_over_sigma;
@@ -330,6 +370,7 @@ MergeStatistics MergeStats(const DiffractionExperiment &x,
all_n_cc_half += sa.n_cc_half;
}
overall.possible_unique_reflections = all_possible;
overall.unique_reflections = all_unique;
overall.mean_i_over_sigma = n_i_over_sigma > 0 ? sum_i_over_sigma / n_i_over_sigma : 0.0;
@@ -351,21 +392,37 @@ MergeStatistics MergeStats(const DiffractionExperiment &x,
void MergeStatistics::Print(Logger &logger) const {
logger.Info("");
logger.Info(" {:>8s} {:>8s} {:>8s} {:>8s} {:>8s}", "d_min", "N_obs", "N_uniq", "<I/sig>", "CC1/2");
logger.Info(" {:->8s} {:->8s} {:->8s} {:->8s} {:->8s}", "", "", "", "", "");
logger.Info(" {:>8s} {:>8s} {:>8s} {:>8s} {:>8s} {:>8s} {:>8s}", "d_min", "N_obs", "N_uniq", "N_possib", "Compl","<I/sig>", "CC1/2");
logger.Info(" {:->8s} {:->8s} {:->8s} {:->8s} {:->8s} {:->8s} {:->8s}", "", "", "", "", "", "", "");
for (const auto &sh: shells) {
if (sh.unique_reflections == 0)
continue;
logger.Info(" {:8.2f} {:8d} {:8d} {:8.1f} {:8.3f}",
sh.d_min, sh.total_observations, sh.unique_reflections,
sh.mean_i_over_sigma, sh.cc_half*100.0);
double completeness = sh.possible_unique_reflections > 0
? static_cast<double>(sh.unique_reflections) / sh.possible_unique_reflections * 100.0 : 0.0;
logger.Info(" {:8.2f} {:8d} {:8d} {:8d} {:7.1f}% {:8.1f} {:7.1f}%",
sh.d_min,
sh.total_observations,
sh.unique_reflections,
sh.possible_unique_reflections,
completeness,
sh.mean_i_over_sigma,
sh.cc_half*100.0);
}
{
const auto &ov = overall;
logger.Info(" {:->8s} {:->8s} {:->8s} {:->8s} {:->8s}", "", "", "", "", "");
logger.Info(" {:>8s} {:8d} {:8d} {:8.1f} {:8.3f}",
"Overall", ov.total_observations, ov.unique_reflections,
ov.mean_i_over_sigma, ov.cc_half*100.0);
double completeness = ov.possible_unique_reflections > 0
? static_cast<double>(ov.unique_reflections) / ov.possible_unique_reflections * 100.0 : 0.0;
logger.Info(" {:->8s} {:->8s} {:->8s} {:->8s} {:->8s} {:->8s} {:->8s}", "", "", "", "", "", "", "");
logger.Info(" {:>8s} {:8d} {:8d} {:8d} {:7.1f}% {:8.1f} {:7.1f}%",
"Overall",
ov.total_observations,
ov.unique_reflections,
ov.possible_unique_reflections,
completeness,
ov.mean_i_over_sigma,
ov.cc_half*100.0);
}
logger.Info("");
}