ScaleAndMerge: Fix still case (though it doesn't really work at the moment)
Some checks failed
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 12m35s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m34s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m49s
Build Packages / Generate python client (push) Successful in 14s
Build Packages / build:rpm (rocky8) (push) Successful in 14m13s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m27s
Build Packages / Create release (push) Has been skipped
Build Packages / Build documentation (push) Successful in 36s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m56s
Build Packages / build:rpm (rocky9) (push) Successful in 14m59s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 15m9s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 7m34s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 8m37s
Build Packages / Unit tests (push) Has been cancelled

This commit is contained in:
2026-02-20 13:40:51 +01:00
parent c33366f3d6
commit ff6e02046a
3 changed files with 22 additions and 20 deletions

View File

@@ -258,7 +258,7 @@ std::optional<ScaleMergeResult> IndexAndRefine::ScaleRotationData(const ScaleMer
ScaleMergeOptions options = opts;
// If the experiment provides a wedge, propagate it
if (experiment.GetGoniometer().has_value()) {
if (experiment.GetGoniometer().has_value() && rotation_indexer) {
options.wedge_deg = experiment.GetGoniometer()->GetWedge_deg();
options.mosaicity_init_deg_vec = mosaicity;
}

View File

@@ -192,7 +192,8 @@ ScaleMergeResult ScaleAndMergeReflectionsCeres(const std::vector<std::vector<Ref
if (opt.image_cluster <= 0)
throw std::invalid_argument("image_cluster must be positive");
const bool refine_partiality = opt.wedge_deg > 0.0;
const bool rotation_crystallography = opt.wedge_deg.has_value();
ceres::Problem problem;
struct ObsRef {
@@ -298,7 +299,7 @@ ScaleMergeResult ScaleAndMergeReflectionsCeres(const std::vector<std::vector<Ref
for (const auto &o: obs) {
auto *cost = new ceres::AutoDiffCostFunction<IntensityResidual, 1, 1, 1, 1>(
new IntensityResidual(*o.r, o.sigma, opt.wedge_deg, refine_partiality));
new IntensityResidual(*o.r, o.sigma, opt.wedge_deg.value_or(0.0), rotation_crystallography));
problem.AddResidualBlock(cost,
nullptr,
&g[o.img_id],
@@ -315,25 +316,26 @@ ScaleMergeResult ScaleAndMergeReflectionsCeres(const std::vector<std::vector<Ref
}
}
if (rotation_crystallography) {
if (opt.smoothen_g) {
for (int i = 0; i < g.size() - 2; ++i) {
if (image_slot_used[i] && image_slot_used[i + 1] && image_slot_used[i + 2]) {
auto *cost = new ceres::AutoDiffCostFunction<SmoothnessRegularizationResidual, 1, 1, 1, 1>(
new SmoothnessRegularizationResidual(0.05));
if (opt.smoothen_g) {
for (int i = 0; i < g.size() - 2; ++i) {
if (image_slot_used[i] && image_slot_used[i + 1] && image_slot_used[i + 2]) {
auto *cost = new ceres::AutoDiffCostFunction<SmoothnessRegularizationResidual, 1, 1, 1, 1>(
new SmoothnessRegularizationResidual(0.05));
problem.AddResidualBlock(cost, nullptr, &g[i], &g[i + 1], &g[i + 2]);
problem.AddResidualBlock(cost, nullptr, &g[i], &g[i + 1], &g[i + 2]);
}
}
}
}
if (opt.smoothen_mos && opt.refine_mosaicity) {
for (int i = 0; i < mosaicity.size() - 2; ++i) {
if (image_slot_used[i] && image_slot_used[i + 1] && image_slot_used[i + 2]) {
auto *cost = new ceres::AutoDiffCostFunction<SmoothnessRegularizationResidual, 1, 1, 1, 1>(
new SmoothnessRegularizationResidual(0.05));
if (opt.smoothen_mos && opt.refine_mosaicity) {
for (int i = 0; i < mosaicity.size() - 2; ++i) {
if (image_slot_used[i] && image_slot_used[i + 1] && image_slot_used[i + 2]) {
auto *cost = new ceres::AutoDiffCostFunction<SmoothnessRegularizationResidual, 1, 1, 1, 1>(
new SmoothnessRegularizationResidual(0.05));
problem.AddResidualBlock(cost, nullptr, &mosaicity[i], &mosaicity[i + 1], &mosaicity[i + 2]);
problem.AddResidualBlock(cost, nullptr, &mosaicity[i], &mosaicity[i + 1], &mosaicity[i + 2]);
}
}
}
}
@@ -430,7 +432,7 @@ ScaleMergeResult ScaleAndMergeReflectionsCeres(const std::vector<std::vector<Ref
corr_obs.reserve(obs.size());
{
const double half_wedge = opt.wedge_deg / 2.0;
const double half_wedge = opt.wedge_deg.value_or(0.0) / 2.0;
for (const auto &o: obs) {
const Reflection &r = *o.r;
@@ -439,7 +441,7 @@ ScaleMergeResult ScaleAndMergeReflectionsCeres(const std::vector<std::vector<Ref
// Compute partiality with refined mosaicity
double partiality;
if (refine_partiality && mosaicity[o.img_id] > 0.0) {
if (rotation_crystallography && mosaicity[o.img_id] > 0.0) {
const double c1 = r.zeta / std::sqrt(2.0);
const double arg_plus = (r.delta_phi_deg + half_wedge) * c1 / mosaicity[o.img_id];
const double arg_minus = (r.delta_phi_deg - half_wedge) * c1 / mosaicity[o.img_id];

View File

@@ -28,7 +28,7 @@ struct ScaleMergeOptions {
// --- Kabsch(XDS)-style partiality model ---
// Rotation range (wedge) used in partiality calculation.
// Set to 0 to disable partiality correction.
double wedge_deg = 1.0;
std::optional<double> wedge_deg;
// --- Mosaicity (user input in degrees; internally converted to radians) ---
bool refine_mosaicity = true;