104 lines
3.4 KiB
C++
104 lines
3.4 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#pragma once
|
|
|
|
#include <map>
|
|
#include <random>
|
|
#include <vector>
|
|
|
|
#include "../../common/Logger.h"
|
|
#include "../../common/DiffractionExperiment.h"
|
|
#include "../../common/Reflection.h"
|
|
|
|
#include "HKLKey.h"
|
|
|
|
struct MergeStatisticsShell {
|
|
float d_min = 0.0f;
|
|
float d_max = 0.0f;
|
|
float mean_one_over_d2 = 0;
|
|
|
|
int total_observations = 0;
|
|
int unique_reflections = 0;
|
|
int possible_unique_reflections = 0;
|
|
|
|
double mean_i_over_sigma = 0.0;
|
|
|
|
double cc_half = 0.0f;
|
|
double cc_ref = NAN;
|
|
};
|
|
|
|
struct MergeStatistics {
|
|
std::vector<MergeStatisticsShell> shells;
|
|
MergeStatisticsShell overall;
|
|
};
|
|
|
|
|
|
std::ostream &operator<<(std::ostream &output, const MergeStatisticsShell &in);
|
|
std::ostream &operator<<(std::ostream &output, const MergeStatistics &in);
|
|
|
|
struct MergeAccum {
|
|
int32_t h = 0;
|
|
int32_t k = 0;
|
|
int32_t l = 0;
|
|
float d = NAN;
|
|
double sum_wI = 0.0;
|
|
double sum_w = 0.0;
|
|
double sum_wI_half[2] = {0.0, 0.0};
|
|
double sum_w_half[2] = {0.0, 0.0};
|
|
size_t n_half[2] = {0, 0};
|
|
};
|
|
|
|
class MergeOnTheFly {
|
|
mutable std::mutex merged_mutex;
|
|
|
|
ScalingSettings scaling_settings;
|
|
IndexingSettings indexing_settings;
|
|
|
|
std::optional<UnitCell> reference_cell;
|
|
std::optional<double> high_resolution_limit;
|
|
std::optional<double> image_cc_limit;
|
|
double min_partiality = 0.02;
|
|
|
|
HKLKeyGenerator generator;
|
|
|
|
// To select images for half-datasets to calculate CC1/2, I use a random number generator with a fixed seed.
|
|
// This makes sure that images are selected randomly, but in a fully reproducible manner (at least for the same binary)
|
|
std::mt19937 rng{123456789u};
|
|
std::bernoulli_distribution half_dist{0.5};
|
|
|
|
std::map<uint64_t, MergeAccum> accumulator;
|
|
|
|
void ProcessImage_i(const std::vector<Reflection> &v, int half);
|
|
public:
|
|
MergeOnTheFly(const DiffractionExperiment &x);
|
|
MergeOnTheFly& ReferenceCell(const std::optional<UnitCell> &cell);
|
|
|
|
void AddAll(const std::vector<std::vector<Reflection> > &reflections,
|
|
const std::vector<uint8_t> &merge_mask = {});
|
|
|
|
void AddImage(const std::vector<Reflection> &v, double image_cc, const UnitCell &cell);
|
|
|
|
std::vector<MergedReflection> ExportReflections();
|
|
};
|
|
|
|
size_t CalcMergeMaskCC(const DiffractionExperiment &x,
|
|
const std::vector<float> &scale_cc,
|
|
std::vector<uint8_t> &result_mask);
|
|
|
|
size_t CalcMergeMaskUnitCell(const DiffractionExperiment &x,
|
|
const UnitCell &reference_cell,
|
|
const std::vector<std::optional<UnitCell> > &unit_cells,
|
|
std::vector<uint8_t> &mask);
|
|
|
|
std::vector<MergedReflection> MergeAll(const DiffractionExperiment &x,
|
|
const std::vector<std::vector<Reflection> > &reflections,
|
|
const std::vector<uint8_t> &merge_mask = {});
|
|
|
|
MergeStatistics MergeStats(const DiffractionExperiment &x,
|
|
const std::vector<MergedReflection> &merged,
|
|
const std::vector<std::vector<Reflection> > &reflections,
|
|
const UnitCell &cell,
|
|
const std::vector<uint8_t> &merge_mask = {},
|
|
const std::vector<MergedReflection> &reference = {});
|