// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include "SpotAnalyze.h" #include "geom_refinement/XtalOptimizer.h" #include "spot_finding/SpotAnalysis.h" #include "spot_finding/StrongPixelSet.h" #include "bragg_integration/BraggIntegrate2D.h" #include "indexing/AnalyzeIndexing.h" void SpotAnalyze(const DiffractionExperiment &experiment, const SpotFindingSettings &spot_finding_settings, const std::vector &spots, const CompressedImage &image, IndexerThreadPool *indexer, DataMessage &output) { std::vector spots_out; auto geom = experiment.GetDiffractionGeometry(); for (const auto &spot: spots) spots_out.push_back(spot.Export(geom)); CountSpots(output, spots_out, spot_finding_settings.cutoff_spot_count_low_res); FilterSpotsByCount(experiment.GetMaxSpotCount(), spots_out, output.spots); if ((indexer != nullptr) && spot_finding_settings.indexing) { auto latt_f = indexer->Run(experiment, output); auto latt = latt_f.get(); if (!latt) output.indexing_result = false; else { bool beam_center_updated = false; DiffractionExperiment experiment_copy(experiment); XtalOptimizerData data{ .geom = experiment_copy.GetDiffractionGeometry(), .latt = latt.value(), .crystal_system = experiment.GetCrystalSystem(), .centering = experiment.GetCentering(), .min_spots = experiment.GetIndexingSettings().GetViableCellMinSpots() }; switch (experiment.GetIndexingSettings().GetGeomRefinementAlgorithm()) { case GeomRefinementAlgorithmEnum::None: break; case GeomRefinementAlgorithmEnum::BeamCenter: // Settings below ensure that symmetry is not "touched" by the refinement routine data.crystal_system = gemmi::CrystalSystem::Triclinic; data.centering = 'P'; // Fall through! case GeomRefinementAlgorithmEnum::BeamCenterSymmetry: if (XtalOptimizer(data, output.spots)) { experiment_copy.BeamX_pxl(data.geom.GetBeamX_pxl()).BeamY_pxl(data.geom.GetBeamY_pxl()); beam_center_updated = true; } break; } if (AnalyzeIndexing(output, experiment_copy, data.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, data.latt, ewald_dist_cutoff, output.number); float res_estimate = sqrtf((res.b_factor.value_or(12.0f) - 12.0f) / 4.0f); if (res_estimate > 1.0 && res_estimate < 4.0) output.resolution_estimate = res_estimate; constexpr size_t kMaxReflections = 10000; if (res.reflections.size() > kMaxReflections) { output.reflections.assign(res.reflections.begin(), res.reflections.begin() + kMaxReflections); } else output.reflections = res.reflections; output.b_factor = res.b_factor; } } } } }