Files
Jungfraujoch/image_analysis/indexing/FFTIndexer_refine.cpp
2025-06-10 18:14:04 +02:00

86 lines
2.9 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "FFTIndexer.h"
#include <ffbidx/refine.h>
std::vector<CrystalLattice> FFTIndexer::Refine(const std::vector<Coord> &in_spots, size_t nspots,
const std::vector<CrystalLattice> &lattices) const {
using M3x = Eigen::MatrixX3<float>;
std::vector<CrystalLattice> ret;
Eigen::MatrixX3<float> spots(in_spots.size(), 3u);
Eigen::MatrixX3<float> oCell(lattices.size() * 3u, 3u);
Eigen::VectorX<float> scores(lattices.size());
for (int i = 0; i < in_spots.size(); i++) {
spots(i, 0u) = in_spots[i].x;
spots(i, 1u) = in_spots[i].y;
spots(i, 2u) = in_spots[i].z;
}
for (int i = 0; i < lattices.size(); i++) {
oCell(i * 3u, 0u) = lattices[i].Vec0().x;
oCell(i * 3u, 1u) = lattices[i].Vec0().y;
oCell(i * 3u, 2u) = lattices[i].Vec0().z;
oCell(i * 3u + 1, 0u) = lattices[i].Vec1().x;
oCell(i * 3u + 1, 1u) = lattices[i].Vec1().y;
oCell(i * 3u + 1, 2u) = lattices[i].Vec1().z;
oCell(i * 3u + 2, 0u) = lattices[i].Vec2().x;
oCell(i * 3u + 2, 1u) = lattices[i].Vec2().y;
oCell(i * 3u + 2, 2u) = lattices[i].Vec2().z;
// Bootstrap score
scores(i) = 0.2;
}
fast_feedback::refine::config_ifssr<float> cifssr{
.min_spots = viable_cell_min_spots
};
fast_feedback::refine::indexer_ifssr<float>::refine(spots.topRows(nspots), oCell, scores, cifssr);
// Select cell that explains most spots
int64_t max_indexed_spot_count = 0;
float max_score = -1;
int64_t id = -1;
for (int i = 0; i < lattices.size(); i++) {
Eigen::Vector3f row_norms = oCell.block(3u * i, 0u, 3u, 3u).rowwise().norm();
if (row_norms.minCoeff() < min_length_A || row_norms.maxCoeff() > max_length_A)
scores(i) += 1000;
auto cell = oCell.block(3u * i, 0u, 3u, 3u);
M3x resid = spots.topRows(nspots) * cell.transpose();
const M3x miller = round(resid.array());
resid -= miller;
int64_t indexed_spot_count = (resid.rowwise().norm().array() < indexing_tolerance).count();
if (indexed_spot_count > max_indexed_spot_count) {
max_indexed_spot_count = indexed_spot_count;
max_score = scores(i);
id = i;
} if (indexed_spot_count == max_indexed_spot_count && scores(i) < max_score) {
max_score = scores(i);
id = i;
}
}
if (id == -1)
return {};
auto cell = oCell.block(3u * id, 0u, 3u, 3u);
fast_feedback::refine::make_right_handed(cell);
return { CrystalLattice(
Coord(cell(0,0), cell(0,1), cell(0,2)),
Coord(cell(1,0), cell(1,1), cell(1,2)),
Coord(cell(2,0), cell(2,1), cell(2,2))
)};
}