Files
Jungfraujoch/image_analysis/SpotAnalyze.cpp

129 lines
5.3 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "SpotAnalyze.h"
#include "geom_refinement/XtalOptimizer.h"
#include "spot_finding/SpotUtils.h"
#include "spot_finding/StrongPixelSet.h"
#include "bragg_integration/BraggIntegrate2D.h"
#include "indexing/AnalyzeIndexing.h"
#include "bragg_integration/CalcISigma.h"
#include "lattice_search/LatticeSearch.h"
void SpotAnalyze(const DiffractionExperiment &experiment,
const SpotFindingSettings &spot_finding_settings,
const std::vector<DiffractionSpot> &spots,
const CompressedImage &image,
BraggPrediction &prediction,
IndexerThreadPool *indexer,
DataMessage &output) {
auto geom = experiment.GetDiffractionGeometry();
SpotAnalyze(experiment, spot_finding_settings, spots, output);
if ((indexer != nullptr) && spot_finding_settings.indexing) {
std::vector<Coord> recip;
recip.reserve(output.spots.size());
bool index_ice_rings = experiment.GetIndexingSettings().GetIndexIceRings();
for (const auto &i: output.spots) {
if (index_ice_rings || !i.ice_ring)
recip.push_back(i.ReciprocalCoord(geom));
}
auto indexer_result = indexer->Run(experiment, recip).get();
output.indexing_time_s = indexer_result.indexing_time_s;
if (indexer_result.lattice.empty())
output.indexing_result = false;
else {
auto latt = indexer_result.lattice[0];
bool beam_center_updated = false;
auto sg = experiment.GetGemmiSpaceGroup();
LatticeMessage symmetry{
.centering = 'P',
.niggli_class = 0,
.crystal_system = gemmi::CrystalSystem::Triclinic
};
// If space group provided => always enforce symmetry in refinement
// If space group not provided => guess symmetry
if (sg) {
// If space group provided but no unit cell fixed, it is better to keep triclinic for now
if (experiment.GetUnitCell()) {
symmetry = LatticeMessage{
.centering = sg->centring_type(),
.niggli_class = 0,
.crystal_system = sg->crystal_system()
};
}
} else {
auto sym_result = LatticeSearch(latt);
symmetry = LatticeMessage{
.centering = sym_result.centering,
.niggli_class = sym_result.niggli_class,
.crystal_system = sym_result.system,
.primitive = sym_result.primitive_reduced
};
output.lattice_type = symmetry;
latt = sym_result.conventional;
}
DiffractionExperiment experiment_copy(experiment);
XtalOptimizerData data{
.geom = experiment_copy.GetDiffractionGeometry(),
.latt = latt,
.crystal_system = symmetry.crystal_system,
.min_spots = experiment.GetIndexingSettings().GetViableCellMinSpots(),
};
if (symmetry.crystal_system == gemmi::CrystalSystem::Trigonal)
data.crystal_system = gemmi::CrystalSystem::Hexagonal;
switch (experiment.GetIndexingSettings().GetGeomRefinementAlgorithm()) {
case GeomRefinementAlgorithmEnum::None:
break;
case GeomRefinementAlgorithmEnum::BeamCenter:
if (XtalOptimizer(data, output.spots)) {
experiment_copy.BeamX_pxl(data.geom.GetBeamX_pxl()).BeamY_pxl(data.geom.GetBeamY_pxl());
beam_center_updated = true;
latt = data.latt;
}
break;
}
if (AnalyzeIndexing(output, experiment_copy, latt)) {
float ewald_dist_cutoff = 0.001f;
if (output.profile_radius)
ewald_dist_cutoff = output.profile_radius.value() * 2.0f;
if (experiment.GetBraggIntegrationSettings().GetFixedProfileRadius_recipA())
ewald_dist_cutoff = experiment.GetBraggIntegrationSettings().GetFixedProfileRadius_recipA().value()
* 3.0f;
if (beam_center_updated) {
output.beam_corr_x = data.beam_corr_x;
output.beam_corr_y = data.beam_corr_y;
}
if (spot_finding_settings.quick_integration) {
auto res = BraggIntegrate2D(experiment_copy, image, latt,
prediction, ewald_dist_cutoff, output.number, symmetry.centering);
constexpr size_t kMaxReflections = 10000;
if (res.size() > kMaxReflections) {
output.reflections.assign(res.begin(), res.begin() + kMaxReflections);
} else
output.reflections = res;
CalcISigma(output);
CalcWilsonBFactor(output);
}
}
}
}
}