Gemmi C++ API
Loading...
Searching...
No Matches
asudata.hpp
Go to the documentation of this file.
1// Copyright 2020 Global Phasing Ltd.
2//
3// AsuData for storing reflection data.
4
5#ifndef GEMMI_ASUDATA_HPP_
6#define GEMMI_ASUDATA_HPP_
7
8#include <complex> // for arg, abs
9#include <algorithm> // for sort, is_sorted
10#include "unitcell.hpp"
11#include "symmetry.hpp"
12#include "stats.hpp" // for Correlation
13#include "util.hpp" // for vector_remove_if
14
15namespace gemmi {
16
18 int n = 0;
19 double sum_xx = 0.;
20 double sum_yy = 0.;
21 std::complex<double> sum_xy = 0.;
22 std::complex<double> mean_x = 0.;
23 std::complex<double> mean_y = 0.;
24 void add_point(std::complex<double> x, std::complex<double> y) {
25 ++n;
26 double inv_n = 1.0 / n;
27 double weight = (n - 1.0) * inv_n;
28 std::complex<double> dx = x - mean_x;
29 std::complex<double> dy = y - mean_y;
30 sum_xx += weight * std::norm(dx);
31 sum_yy += weight * std::norm(dy);
32 sum_xy += weight * (dx * std::conj(dy));
33 mean_x += dx * inv_n;
34 mean_y += dy * inv_n;
35 }
36 void add_point(std::complex<float> x, std::complex<float> y) {
37 add_point(std::complex<double>(x), std::complex<double>(y));
38 }
39 std::complex<double> coefficient() const { return sum_xy / std::sqrt(sum_xx * sum_yy); }
40 double mean_ratio() const { return std::abs(mean_y) / std::abs(mean_x); }
41};
42
43
45template<typename Func, typename T>
46void for_matching_reflections(const std::vector<T>& a,
47 const std::vector<T>& b,
48 const Func& func) {
49 auto r1 = a.begin();
50 auto r2 = b.begin();
51 while (r1 != a.end() && r2 != b.end()) {
52 if (r1->hkl == r2->hkl) {
53 func(*r1, *r2);
54 ++r1;
55 ++r2;
56 } else if (r1->hkl < r2->hkl) {
57 ++r1;
58 } else {
59 ++r2;
60 }
61 }
62}
63
65template<typename T>
67 const std::vector<T>& b) {
68 Correlation cor;
69 for_matching_reflections(a, b, [&cor](const T& x, const T& y) {
70 cor.add_point(x.value, y.value);
71 });
72 return cor;
73}
74
76template<typename T>
78 const std::vector<T>& b) {
80 for_matching_reflections(a, b, [&cor](const T& x, const T& y) {
81 cor.add_point(x.value, y.value);
82 });
83 return cor;
84}
85
87template<typename T>
88int count_equal_values(const std::vector<T>& a, const std::vector<T>& b) {
89 int count = 0;
90 for_matching_reflections(a, b, [&count](const T& x, const T& y) {
91 if (x.value == y.value)
92 ++count;
93 });
94 return count;
95}
96
97template<typename T>
98struct HklValue {
99 alignas(8) Miller hkl;
101
102 bool operator<(const Miller& m) const { return hkl < m; }
103 bool operator<(const HklValue& o) const { return operator<(o.hkl); }
104};
105
106template<typename T>
108 using value_type = T;
110
111 bool operator==(const ValueSigma& o) const {
112 return value == o.value && sigma == o.sigma;
113 }
114};
115
116namespace impl {
117template<typename T>
118void move_to_asu(const GroupOps&, const Miller& hkl, int, HklValue<T>& hkl_value) {
119 hkl_value.hkl = hkl;
120}
121
122template<typename R>
123void move_to_asu(const GroupOps& gops, const Miller& hkl, int isym,
124 HklValue<std::complex<R>>& v) {
125 v.hkl = hkl;
126 // cf. Mtz::ensure_asu()
127 const Op& op = gops.sym_ops[(isym - 1) / 2];
128 double shift = op.phase_shift(hkl);
129 if (shift != 0) {
130 double phase = std::arg(v.value) + shift;
131 v.value = std::polar(std::abs(v.value), (R)phase);
132 }
133 if (isym % 2 == 0)
134 v.value.imag(-v.value.imag());
135}
136} // namespace impl
137
138template<typename T>
139struct AsuData {
140 std::vector<HklValue<T>> v;
141 UnitCell unit_cell_;
142 const SpaceGroup* spacegroup_ = nullptr;
143 // function defining FPhiProxy interface
144 size_t stride() const { return 1; }
145 size_t size() const { return v.size(); }
146 Miller get_hkl(size_t n) const { return v[n].hkl; }
147 double get_f(size_t n) const { return std::abs(v[n].value); }
148 double get_phi(size_t n) const { return std::arg(v[n].value); }
149 const UnitCell& unit_cell() const { return unit_cell_; }
150 const SpaceGroup* spacegroup() const { return spacegroup_; }
152 if (!std::is_sorted(v.begin(), v.end()))
153 std::sort(v.begin(), v.end());
154 }
155
156 void ensure_asu(bool tnt_asu=false) {
157 if (!spacegroup_)
158 fail("AsuData::ensure_asu(): space group not set");
159 GroupOps gops = spacegroup_->operations();
160 ReciprocalAsu asu(spacegroup_, tnt_asu);
161 for (HklValue<T>& hkl_value : v) {
162 const Miller& hkl = hkl_value.hkl;
163 if (asu.is_in(hkl))
164 continue;
165 auto result = asu.to_asu(hkl, gops);
166 impl::move_to_asu(gops, result.first, result.second, hkl_value);
167 }
168 }
169
170 // load values from one column
171 template<typename DataProxy>
172 void load_values(const DataProxy& proxy, const std::string& label,
173 bool as_is=false) {
174 std::size_t col = proxy.column_index(label);
175 unit_cell_ = proxy.unit_cell();
176 spacegroup_ = proxy.spacegroup();
177 for (size_t i = 0; i < proxy.size(); i += proxy.stride()) {
178 auto num = proxy.get_num(i + col);
179 if (!std::isnan(num))
180 v.push_back({proxy.get_hkl(i), (T)num});
181 }
182 if (!as_is) {
183 ensure_asu();
185 }
186 }
187
188 // load values from two or more columns
189 template<int N, typename DataProxy>
190 void load_values(const DataProxy& proxy, const std::array<std::string,N>& labels,
191 bool as_is=false) {
192 std::array<std::size_t, N> cols;
193 for (int i = 0; i < N; ++i)
194 cols[i] = proxy.column_index(labels[i]);
195 unit_cell_ = proxy.unit_cell();
196 spacegroup_ = proxy.spacegroup();
197 using Val = typename T::value_type;
198 for (size_t i = 0; i < proxy.size(); i += proxy.stride()) {
199 std::array<Val, N> nums;
200 for (int j = 0; j < N; ++j)
201 nums[j] = (Val) proxy.get_num(i + cols[j]);
202 if (!std::any_of(nums.begin(), nums.end(), [](Val f) { return std::isnan(f); })) {
203 v.emplace_back();
204 v.back().hkl = proxy.get_hkl(i);
205 set_value_from_array(v.back().value, nums);
206 }
207 }
208 if (!as_is) {
209 ensure_asu();
211 }
212 }
213
214private:
215 // for T being a number, std::array and std::complex, respectively:
216 static void set_value_from_array(T& val, const std::array<T,1>& nums) { val = nums[0]; }
217 static void set_value_from_array(T& val, const T& nums) { val = nums; }
218 template<typename R>
219 static void set_value_from_array(std::complex<R>& val, const std::array<R,2>& nums) {
220 R theta = (R)rad(nums[1]);
221 val = {nums[0] * std::cos(theta), nums[0] * std::sin(theta)};
222 }
223 template<typename R>
224 static void set_value_from_array(ValueSigma<R>& val, const std::array<R,2>& nums) {
225 val.value = nums[0];
226 val.sigma = nums[1];
227 }
228};
229
230template<typename T, int N, typename Data>
231AsuData<T> make_asu_data(const Data& data, const std::array<std::string,N>& labels,
232 bool as_is=false) {
235 return asu_data;
236}
237template<typename T, typename Data>
238AsuData<T> make_asu_data(const Data& data, const std::string& label, bool as_is) {
240 asu_data.load_values(data_proxy(data), label, as_is);
241 return asu_data;
242}
243
245template<typename T>
247 vector_remove_if(asu_data.v, [cutoff](const HklValue<ValueSigma<T>>& p) {
248 auto& v = p.value;
249 return v.sigma <= 0 || v.value <= cutoff * v.sigma;
250 });
251}
252
253} // namespace gemmi
254#endif
void vector_remove_if(std::vector< T > &v, F &&condition)
Definition util.hpp:267
MtzDataProxy data_proxy(const Mtz &mtz)
Definition mtz.hpp:596
void for_matching_reflections(const std::vector< T > &a, const std::vector< T > &b, const Func &func)
Definition asudata.hpp:46
void discard_by_sigma_ratio(AsuData< ValueSigma< T > > &asu_data, double cutoff)
retains only points with positive SIGF and F/SIGF > cutoff
Definition asudata.hpp:246
std::array< int, 3 > Miller
A synonym for convenient passing of hkl.
Definition unitcell.hpp:129
int count_equal_values(const std::vector< T > &a, const std::vector< T > &b)
Definition asudata.hpp:88
constexpr double rad(double angle)
Definition math.hpp:32
void fail(const std::string &msg)
Definition fail.hpp:59
ComplexCorrelation calculate_hkl_complex_correlation(const std::vector< T > &a, const std::vector< T > &b)
Definition asudata.hpp:77
Correlation calculate_hkl_value_correlation(const std::vector< T > &a, const std::vector< T > &b)
Definition asudata.hpp:66
AsuData< T > make_asu_data(const Data &data, const std::array< std::string, N > &labels, bool as_is=false)
Definition asudata.hpp:231
Statistics utilities: classes Covariance, Correlation, DataStats.
double get_phi(size_t n) const
Definition asudata.hpp:148
const SpaceGroup * spacegroup() const
Definition asudata.hpp:150
Miller get_hkl(size_t n) const
Definition asudata.hpp:146
size_t stride() const
Definition asudata.hpp:144
void load_values(const DataProxy &proxy, const std::string &label, bool as_is=false)
Definition asudata.hpp:172
void ensure_sorted()
Definition asudata.hpp:151
double get_f(size_t n) const
Definition asudata.hpp:147
size_t size() const
Definition asudata.hpp:145
std::vector< HklValue< T > > v
Definition asudata.hpp:140
void ensure_asu(bool tnt_asu=false)
Definition asudata.hpp:156
const UnitCell & unit_cell() const
Definition asudata.hpp:149
void load_values(const DataProxy &proxy, const std::array< std::string, N > &labels, bool as_is=false)
Definition asudata.hpp:190
std::complex< double > mean_y
Definition asudata.hpp:23
void add_point(std::complex< double > x, std::complex< double > y)
Definition asudata.hpp:24
double mean_ratio() const
Definition asudata.hpp:40
std::complex< double > coefficient() const
Definition asudata.hpp:39
std::complex< double > mean_x
Definition asudata.hpp:22
void add_point(std::complex< float > x, std::complex< float > y)
Definition asudata.hpp:36
std::complex< double > sum_xy
Definition asudata.hpp:21
void add_point(double x, double y)
Definition stats.hpp:53
bool operator<(const Miller &m) const
Definition asudata.hpp:102
bool operator<(const HklValue &o) const
Definition asudata.hpp:103
std::pair< Op::Miller, int > to_asu(const Op::Miller &hkl, const std::vector< Op > &sym_ops) const
Returns hkl in asu and MTZ ISYM - 2*n-1 for reflections in the positive asu (I+ of a Friedel pair),...
Definition symmetry.hpp:991
bool is_in(const Op::Miller &hkl) const
Definition symmetry.hpp:927
GroupOps operations() const
Definition symmetry.hpp:837
Unit cell.
Definition unitcell.hpp:165
bool operator==(const ValueSigma &o) const
Definition asudata.hpp:111
Crystallographic Symmetry. Space Groups. Coordinate Triplets.
Unit cell.
Utilities. Mostly for working with strings and vectors.