XtalOptimizer: Accept std::vector<std::vector<SpotToSave>> for spots input, to distinguish spots between different images

This commit is contained in:
2026-05-29 14:19:47 +02:00
parent 8660558341
commit 07d7174eff
6 changed files with 74 additions and 89 deletions
@@ -504,7 +504,7 @@ CrystalLattice AngleAxisAndLengthsToLattice(const double rod[3], const double le
}
bool XtalOptimizerInternal(XtalOptimizerData &data,
const std::vector<SpotToSave> &spots,
const std::vector<std::vector<SpotToSave>> &spots,
const float tolerance) {
try {
Coord vec0 = data.latt.Vec0();
@@ -565,50 +565,60 @@ bool XtalOptimizerInternal(XtalOptimizerData &data,
const float tolerance_sq = tolerance * tolerance;
// Add residuals for each point
for (const auto &pt: spots) {
if (!data.index_ice_rings && pt.ice_ring)
for (int i = 0; i < spots.size(); i++) {
if (spots[i].empty())
continue;
float angle_rad = 0.0;
Coord recip = pt.ReciprocalCoord(data.geom);
double angle_rad = 0.0;
std::optional<RotMatrix> rot_matr;
if (data.axis) {
recip = data.axis->GetTransformationAngle(pt.phi) * recip;
angle_rad = pt.phi * M_PI / 180.0;
const float angle_deg = data.axis->GetAngle_deg(i) + data.axis->GetWedge_deg() / 2.0;
angle_rad = angle_deg * M_PI / 180.0;
rot_matr = data.axis->GetTransformationAngle(angle_deg);
}
double h_fp = recip * vec0;
double k_fp = recip * vec1;
double l_fp = recip * vec2;
// Add residuals for each point
for (const auto &pt: spots[i]) {
if (!data.index_ice_rings && pt.ice_ring)
continue;
double h = std::round(h_fp);
double k = std::round(k_fp);
double l = std::round(l_fp);
Coord recip = pt.ReciprocalCoord(data.geom);
double norm_sq = (h - h_fp) * (h - h_fp) + (k - k_fp) * (k - k_fp) + (l - l_fp) * (l - l_fp);
if (rot_matr)
recip = rot_matr.value() * recip;
if (norm_sq > tolerance_sq)
continue;
double h_fp = recip * vec0;
double k_fp = recip * vec1;
double l_fp = recip * vec2;
problem.AddResidualBlock(
new ceres::AutoDiffCostFunction<XtalResidual, 3, 2, 1, 2, 3, 3, 3, 3>(
new XtalResidual(pt.x, pt.y,
data.geom.GetWavelength_A(),
data.geom.GetPixelSize_mm(),
angle_rad,
h, k, l,
data.crystal_system)),
nullptr,
beam,
&distance_mm,
detector_rot,
rot_vec,
latt_vec0,
latt_vec1,
latt_vec2
);
double h = std::round(h_fp);
double k = std::round(k_fp);
double l = std::round(l_fp);
double norm_sq = (h - h_fp) * (h - h_fp) + (k - k_fp) * (k - k_fp) + (l - l_fp) * (l - l_fp);
if (norm_sq > tolerance_sq)
continue;
problem.AddResidualBlock(
new ceres::AutoDiffCostFunction<XtalResidual, 3, 2, 1, 2, 3, 3, 3, 3>(
new XtalResidual(pt.x, pt.y,
data.geom.GetWavelength_A(),
data.geom.GetPixelSize_mm(),
angle_rad,
h, k, l,
data.crystal_system)),
nullptr,
beam,
&distance_mm,
detector_rot,
rot_vec,
latt_vec0,
latt_vec1,
latt_vec2
);
}
}
if (problem.NumResidualBlocks() < data.min_spots)
@@ -722,7 +732,7 @@ bool XtalOptimizerInternal(XtalOptimizerData &data,
}
}
bool XtalOptimizer(XtalOptimizerData &data, const std::vector<SpotToSave> &spots) {
bool XtalOptimizer(XtalOptimizerData &data, const std::vector<std::vector<SpotToSave>> &spots) {
if (!XtalOptimizerInternal(data, spots, 0.3))
return false;
XtalOptimizerInternal(data, spots, 0.2);