// 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/SpotUtils.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)); if (experiment.GetDatasetSettings().IsDetectIceRings() && spot_finding_settings.ice_ring_width_Q_recipA > 0.0f) MarkIceRings(spots_out, spot_finding_settings.ice_ring_width_Q_recipA); CountSpots(output, spots_out, spot_finding_settings.cutoff_spot_count_low_res); FilterSpotsByCount(spots_out, experiment.GetMaxSpotCount()); output.spots = spots_out; output.resolution_estimate = GetResolution(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); 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; output.integration_Isigma = res.Isigma; output.integration_logI = res.logI; output.integration_one_over_d = res.one_over_d; } } } } }