Refine: test the candidate cells on the refinement's threads
After the candidate cells are refined, each one is tested on its own - the reference match, StepDownToReference where it does not match, the angle and volume tests, and ComputeIndexedMask over the accumulated spots. That loop ran on one thread per scheme; on a re-index with a reference cell (the long-axis hypothesis) StepDownToReference and the mask took most of the call. The candidates now go over refine_threads with ParallelFor, each into its own slot, and are collected in candidate order before the ranking, so the ranking sees the same list. Results identical by construction. Rotation first pass, -N 28, 5950X + RTX 5080, machine shared with other jobs (median of 2, s): Step 3 / Step 6, after the DeAlias commit thau 1000 images: 2.46 / 1.06 -> 2.10 / 1.00 cytc: 1.65 -> 1.62 lyso: 1.73 / 0.85 -> 1.76 / 0.84 (noise) _report.txt (minus run-specific lines) and .hkl identical on all three. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK
This commit is contained in:
1 parent
9c8347031d
commit
388474ba4a
1 file changed
+18
-10
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "../../common/JFJochMath.h"
|
||||
#include "PostIndexingRefinement.h"
|
||||
#include "../../common/ParallelFor.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
@@ -335,7 +336,11 @@ std::vector<CrystalLattice> Refine(const std::vector<Coord> &in_spots,
|
||||
reference_cells.push_back(reference.NiggliReduce().GetUnitCell());
|
||||
}
|
||||
|
||||
for (int i = 0; i < scores.size(); i++) {
|
||||
// Each candidate is tested on its own - the step-down to the reference and the indexed mask are the
|
||||
// costly parts - so they are spread over the same threads as the refinement above, each into its own
|
||||
// slot, and kept in candidate order.
|
||||
std::vector<std::optional<RefinedCandidate>> tested(scores.size());
|
||||
ParallelFor(static_cast<int>(scores.size()), p.refine_threads, [&](int i) {
|
||||
Eigen::Matrix3f cell_rows = oCell.block(3u * i, 0u, 3u, 3u);
|
||||
Eigen::Matrix3f cell_cols = cell_rows.transpose();
|
||||
Eigen::Vector3f row_norms = cell_rows.rowwise().norm();
|
||||
@@ -343,18 +348,18 @@ std::vector<CrystalLattice> Refine(const std::vector<Coord> &in_spots,
|
||||
if (!reference_cells.empty()) {
|
||||
if (!MatchesReference(cell_rows, reference_cells, p.dist_tolerance_vs_reference)) {
|
||||
if (!p.step_down_to_reference)
|
||||
continue;
|
||||
return;
|
||||
const auto sub = StepDownToReference(cell_rows, reference_cells, p.dist_tolerance_vs_reference,
|
||||
spots.topRows(nspots), p.indexing_tolerance);
|
||||
if (!sub)
|
||||
continue;
|
||||
return;
|
||||
cell_rows = *sub;
|
||||
cell_cols = cell_rows.transpose();
|
||||
row_norms = cell_rows.rowwise().norm();
|
||||
}
|
||||
} else {
|
||||
if (row_norms.minCoeff() < p.min_length_A || row_norms.maxCoeff() > p.max_length_A)
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter for wrong angles. Compared as COSINES, not angles: acos is strictly decreasing on
|
||||
@@ -369,28 +374,31 @@ std::vector<CrystalLattice> Refine(const std::vector<Coord> &in_spots,
|
||||
if (cos_alpha > cos_min_angle || cos_alpha < cos_max_angle ||
|
||||
cos_beta > cos_min_angle || cos_beta < cos_max_angle ||
|
||||
cos_gamma > cos_min_angle || cos_gamma < cos_max_angle)
|
||||
continue;
|
||||
return;
|
||||
|
||||
// Three coplanar rows pass both tests above - 120 deg apart in one plane is inside any angle
|
||||
// window - and the refinement can walk a candidate there. Such a cell has no reciprocal basis,
|
||||
// so it is not a lattice: the same volume test as CrystalLattice::VolumeFraction().
|
||||
if (std::abs(cell_rows.determinant()) < MIN_BASIS_VOLUME_FRACTION * row_norms.prod())
|
||||
continue;
|
||||
return;
|
||||
|
||||
int64_t indexed_spot_count = 0;
|
||||
auto indexed_mask = ComputeIndexedMask(spots.topRows(nspots), cell_cols, p.indexing_tolerance, indexed_spot_count);
|
||||
|
||||
if (indexed_spot_count < p.viable_cell_min_spots)
|
||||
continue;
|
||||
return;
|
||||
|
||||
candidates.emplace_back(RefinedCandidate{
|
||||
tested[i] = RefinedCandidate{
|
||||
.cell = cell_rows,
|
||||
.score = scores(i),
|
||||
.volume = std::abs(cell_rows.determinant()),
|
||||
.indexed_spot_count = indexed_spot_count,
|
||||
.indexed_mask = std::move(indexed_mask)
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
for (auto &t : tested)
|
||||
if (t)
|
||||
candidates.push_back(std::move(*t));
|
||||
|
||||
std::sort(candidates.begin(), candidates.end(),
|
||||
[](const RefinedCandidate &a, const RefinedCandidate &b) {
|
||||
|
||||
Reference in new issue
Block a user