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
14namespace gemmi {
15
17 int n = 0;
18 double sum_xx = 0.;
19 double sum_yy = 0.;
20 std::complex<double> sum_xy = 0.;
21 std::complex<double> mean_x = 0.;
22 std::complex<double> mean_y = 0.;
23 void add_point(std::complex<double> x, std::complex<double> y) {
24 ++n;
25 double inv_n = 1.0 / n;
26 double weight = (n - 1.0) * inv_n;
27 std::complex<double> dx = x - mean_x;
28 std::complex<double> dy = y - mean_y;
29 sum_xx += weight * std::norm(dx);
30 sum_yy += weight * std::norm(dy);
31 sum_xy += weight * (dx * std::conj(dy));
32 mean_x += dx * inv_n;
33 mean_y += dy * inv_n;
34 }
35 void add_point(std::complex<float> x, std::complex<float> y) {
36 add_point(std::complex<double>(x), std::complex<double>(y));
37 }
38 std::complex<double> coefficient() const { return sum_xy / std::sqrt(sum_xx * sum_yy); }
39 double mean_ratio() const { return std::abs(mean_y) / std::abs(mean_x); }
40};
41
42
44template<typename Func, typename T>
45void for_matching_reflections(const std::vector<T>& a,
46 const std::vector<T>& b,
47 const Func& func) {
48 auto r1 = a.begin();
49 auto r2 = b.begin();
50 while (r1 != a.end() && r2 != b.end()) {
51 if (r1->hkl == r2->hkl) {
52 func(*r1, *r2);
53 ++r1;
54 ++r2;
55 } else if (r1->hkl < r2->hkl) {
56 ++r1;
57 } else {
58 ++r2;
59 }
60 }
61}
62
64template<typename T>
66 const std::vector<T>& b) {
67 Correlation cor;
68 for_matching_reflections(a, b, [&cor](const T& x, const T& y) {
69 cor.add_point(x.value, y.value);
70 });
71 return cor;
72}
73
75template<typename T>
77 const std::vector<T>& b) {
79 for_matching_reflections(a, b, [&cor](const T& x, const T& y) {
80 cor.add_point(x.value, y.value);
81 });
82 return cor;
83}
84
86template<typename T>
87int count_equal_values(const std::vector<T>& a, const std::vector<T>& b) {
88 int count = 0;
89 for_matching_reflections(a, b, [&count](const T& x, const T& y) {
90 if (x.value == y.value)
91 ++count;
92 });
93 return count;
94}
95
96template<typename T>
97struct HklValue {
100
101 bool operator<(const Miller& m) const { return hkl < m; }
102 bool operator<(const HklValue& o) const { return operator<(o.hkl); }
103};
104
105template<typename T>
107 using value_type = T;
109
110 bool operator==(const ValueSigma& o) const {
111 return value == o.value && sigma == o.sigma;
112 }
113};
114
115namespace impl {
116template<typename T>
117void move_to_asu(const GroupOps&, const Miller& hkl, int, HklValue<T>& hkl_value) {
118 hkl_value.hkl = hkl;
119}
120
121template<typename R>
122void move_to_asu(const GroupOps& gops, const Miller& hkl, int isym,
123 HklValue<std::complex<R>>& v) {
124 v.hkl = hkl;
125 // cf. Mtz::ensure_asu()
126 const Op& op = gops.sym_ops[(isym - 1) / 2];
127 double shift = op.phase_shift(hkl);
128 if (shift != 0) {
129 double phase = std::arg(v.value) + shift;
130 v.value = std::polar(std::abs(v.value), (R)phase);
131 }
132 if (isym % 2 == 0)
133 v.value.imag(-v.value.imag());
134}
135} // namespace impl
136
137template<typename T>
138struct AsuData {
139 std::vector<HklValue<T>> v;
140 UnitCell unit_cell_;
141 const SpaceGroup* spacegroup_ = nullptr;
142 // function defining FPhiProxy interface
143 size_t stride() const { return 1; }
144 size_t size() const { return v.size(); }
145 Miller get_hkl(size_t n) const { return v[n].hkl; }
146 double get_f(size_t n) const { return std::abs(v[n].value); }
147 double get_phi(size_t n) const { return std::arg(v[n].value); }
148 const UnitCell& unit_cell() const { return unit_cell_; }
149 const SpaceGroup* spacegroup() const { return spacegroup_; }
151 if (!std::is_sorted(v.begin(), v.end()))
152 std::sort(v.begin(), v.end());
153 }
154
155 void ensure_asu(bool tnt_asu=false) {
156 if (!spacegroup_)
157 fail("AsuData::ensure_asu(): space group not set");
158 GroupOps gops = spacegroup_->operations();
159 ReciprocalAsu asu(spacegroup_, tnt_asu);
160 for (HklValue<T>& hkl_value : v) {
161 const Miller& hkl = hkl_value.hkl;
162 if (asu.is_in(hkl))
163 continue;
164 auto result = asu.to_asu(hkl, gops);
165 impl::move_to_asu(gops, result.first, result.second, hkl_value);
166 }
167 }
168
169 // load values from one column
170 template<typename DataProxy>
171 void load_values(const DataProxy& proxy, const std::string& label,
172 bool as_is=false) {
173 std::size_t col = proxy.column_index(label);
174 unit_cell_ = proxy.unit_cell();
175 spacegroup_ = proxy.spacegroup();
176 for (size_t i = 0; i < proxy.size(); i += proxy.stride()) {
177 auto num = proxy.get_num(i + col);
178 if (!std::isnan(num))
179 v.push_back({proxy.get_hkl(i), (T)num});
180 }
181 if (!as_is) {
182 ensure_asu();
184 }
185 }
186
187 // load values from two or more columns
188 template<int N, typename DataProxy>
189 void load_values(const DataProxy& proxy, const std::array<std::string,N>& labels,
190 bool as_is=false) {
191 std::array<std::size_t, N> cols;
192 for (int i = 0; i < N; ++i)
193 cols[i] = proxy.column_index(labels[i]);
194 unit_cell_ = proxy.unit_cell();
195 spacegroup_ = proxy.spacegroup();
196 using Val = typename T::value_type;
197 for (size_t i = 0; i < proxy.size(); i += proxy.stride()) {
198 std::array<Val, N> nums;
199 for (int j = 0; j < N; ++j)
200 nums[j] = (Val) proxy.get_num(i + cols[j]);
201 if (!std::any_of(nums.begin(), nums.end(), [](Val f) { return std::isnan(f); })) {
202 v.emplace_back();
203 v.back().hkl = proxy.get_hkl(i);
204 set_value_from_array(v.back().value, nums);
205 }
206 }
207 if (!as_is) {
208 ensure_asu();
210 }
211 }
212
213private:
214 // for T being a number, std::array and std::complex, respectively:
215 static void set_value_from_array(T& val, const std::array<T,1>& nums) { val = nums[0]; }
216 static void set_value_from_array(T& val, const T& nums) { val = nums; }
217 template<typename R>
218 static void set_value_from_array(std::complex<R>& val, const std::array<R,2>& nums) {
219 R theta = (R)rad(nums[1]);
220 val = {nums[0] * std::cos(theta), nums[0] * std::sin(theta)};
221 }
222 template<typename R>
223 static void set_value_from_array(ValueSigma<R>& val, const std::array<R,2>& nums) {
224 val.value = nums[0];
225 val.sigma = nums[1];
226 }
227};
228
229template<typename T, int N, typename Data>
230AsuData<T> make_asu_data(const Data& data, const std::array<std::string,N>& labels,
231 bool as_is=false) {
234 return asu_data;
235}
236template<typename T, typename Data>
237AsuData<T> make_asu_data(const Data& data, const std::string& label, bool as_is) {
239 asu_data.load_values(data_proxy(data), label, as_is);
240 return asu_data;
241}
242
243} // namespace gemmi
244#endif
MtzDataProxy data_proxy(const Mtz &mtz)
Definition mtz.hpp:1096
void for_matching_reflections(const std::vector< T > &a, const std::vector< T > &b, const Func &func)
Definition asudata.hpp:45
std::array< int, 3 > Miller
A synonym for convenient passing of hkl.
Definition unitcell.hpp:128
int count_equal_values(const std::vector< T > &a, const std::vector< T > &b)
Definition asudata.hpp:87
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:76
Correlation calculate_hkl_value_correlation(const std::vector< T > &a, const std::vector< T > &b)
Definition asudata.hpp:65
AsuData< T > make_asu_data(const Data &data, const std::array< std::string, N > &labels, bool as_is=false)
Definition asudata.hpp:230
double get_phi(size_t n) const
Definition asudata.hpp:147
const SpaceGroup * spacegroup() const
Definition asudata.hpp:149
Miller get_hkl(size_t n) const
Definition asudata.hpp:145
size_t stride() const
Definition asudata.hpp:143
void load_values(const DataProxy &proxy, const std::string &label, bool as_is=false)
Definition asudata.hpp:171
void ensure_sorted()
Definition asudata.hpp:150
double get_f(size_t n) const
Definition asudata.hpp:146
size_t size() const
Definition asudata.hpp:144
std::vector< HklValue< T > > v
Definition asudata.hpp:139
void ensure_asu(bool tnt_asu=false)
Definition asudata.hpp:155
const UnitCell & unit_cell() const
Definition asudata.hpp:148
void load_values(const DataProxy &proxy, const std::array< std::string, N > &labels, bool as_is=false)
Definition asudata.hpp:189
std::complex< double > mean_y
Definition asudata.hpp:22
void add_point(std::complex< double > x, std::complex< double > y)
Definition asudata.hpp:23
double mean_ratio() const
Definition asudata.hpp:39
std::complex< double > coefficient() const
Definition asudata.hpp:38
std::complex< double > mean_x
Definition asudata.hpp:21
void add_point(std::complex< float > x, std::complex< float > y)
Definition asudata.hpp:35
std::complex< double > sum_xy
Definition asudata.hpp:20
void add_point(double x, double y)
Definition stats.hpp:53
bool operator<(const Miller &m) const
Definition asudata.hpp:101
bool operator<(const HklValue &o) const
Definition asudata.hpp:102
bool is_in(const Op::Miller &hkl) const
std::pair< Op::Miller, int > to_asu(const Op::Miller &hkl, const GroupOps &gops) const
Returns hkl in asu and MTZ ISYM - 2*n-1 for reflections in the positive asu (I+ of a Friedel pair),...
GroupOps operations() const
Unit cell.
Definition unitcell.hpp:139
bool operator==(const ValueSigma &o) const
Definition asudata.hpp:110