Gemmi C++ API
Loading...
Searching...
No Matches
recgrid.hpp
Go to the documentation of this file.
1// Copyright 2020 Global Phasing Ltd.
2//
3// ReciprocalGrid -- grid for reciprocal space data.
4
5#ifndef GEMMI_RECGRID_HPP_
6#define GEMMI_RECGRID_HPP_
7
8#include <memory> // for unique_ptr
9#include "asudata.hpp"
10#include "grid.hpp"
11
12namespace gemmi {
13
14template<typename T> T friedel_mate_value(T v) { return v; }
15template<typename T>
16std::complex<T> friedel_mate_value(const std::complex<T>& v) {
17 return std::conj(v);
18}
19
20template<typename T>
22 bool half_l = false; // hkl grid that stores only l>=0
23 bool has_index(int u, int v, int w) const {
24 bool half_u = (half_l && this->axis_order == AxisOrder::ZYX);
25 bool half_w = (half_l && this->axis_order != AxisOrder::ZYX);
26 return std::abs(half_u ? u : 2 * u) < this->nu &&
27 std::abs(2 * v) < this->nv &&
28 std::abs(half_w ? w : 2 * w) < this->nw;
29 }
30 void check_index(int u, int v, int w) const {
31 if (!has_index(u, v, w))
32 throw std::out_of_range("ReciprocalGrid: index out of grid.");
33 }
34 // Similar to Grid::index_n(), but works only for -nu <= u < nu, etc.
35 size_t index_n(int u, int v, int w) const {
36 return this->index_q(u >= 0 ? u : u + this->nu,
37 v >= 0 ? v : v + this->nv,
38 w >= 0 ? w : w + this->nw);
39 }
40 size_t index_checked(int u, int v, int w) const {
41 check_index(u, v, w);
42 return index_n(u, v, w);
43 }
44 T get_value(int u, int v, int w) const {
45 return this->data[index_checked(u, v, w)];
46 }
47 T get_value_or_zero(int u, int v, int w) const {
48 return has_index(u, v, w) ? this->data[index_n(u, v, w)] : T{};
49 }
50 void set_value(int u, int v, int w, T x) {
51 this->data[index_checked(u, v, w)] = x;
52 }
53 Miller to_hkl(const typename GridBase<T>::Point& point) const {
54 Miller hkl{{point.u, point.v, point.w}};
55 if (2 * point.u >= this->nu &&
56 !(half_l && this->axis_order == AxisOrder::ZYX))
57 hkl[0] -= this->nu;
58 if (2 * point.v >= this->nv)
59 hkl[1] -= this->nv;
60 if (2 * point.w >= this->nw &&
61 !(half_l && this->axis_order != AxisOrder::ZYX))
62 hkl[2] -= this->nw;
63 if (this->axis_order == AxisOrder::ZYX)
64 std::swap(hkl[0], hkl[2]);
65 return hkl;
66 }
67
68 double calculate_1_d2(const typename GridBase<T>::Point& point) const {
69 return this->unit_cell.calculate_1_d2(to_hkl(point));
70 }
71 double calculate_d(const typename GridBase<T>::Point& point) const {
72 return this->unit_cell.calculate_d(to_hkl(point));
73 }
74
76 bool mott_bethe=false) const {
77 if (this->axis_order == AxisOrder::ZYX)
78 fail("get_value_by_hkl(): ZYX order is not supported yet");
79 T value;
80 if (half_l && hkl[2] < 0)
81 value = friedel_mate_value(this->get_value(-hkl[0], -hkl[1], -hkl[2]));
82 else
83 value = this->get_value(hkl[0], hkl[1], hkl[2]);
84
85 if (unblur != 0. || mott_bethe) {
86 double inv_d2 = this->unit_cell.calculate_1_d2(hkl);
87 double mult = 1;
88 if (unblur != 0)
89 // cf. reciprocal_space_multiplier()
90 mult = std::exp(unblur * 0.25 * inv_d2);
91 if (mott_bethe)
92 // cf. mott_bethe_factor
94 value *= static_cast<decltype(std::abs(value))>(mult);
95 }
96 return value;
97 }
98
99 // the result is always sorted by h,k,l
100 template <typename R=T>
101 AsuData<R> prepare_asu_data(double dmin=0, double unblur=0,
102 bool with_000=false, bool with_sys_abs=false,
103 bool mott_bethe=false) {
105 if (this->axis_order == AxisOrder::ZYX)
106 fail("get_asu_values(): ZYX order is not supported yet");
107 // Why "- 1" below? To skip the value at Nyquist frequency (±n/2).
108 // For even lengths of DFT (real -> reciprocal space) the resulting
109 // h=+nu/2 and h=-nu/2 are both represented by one (strictly real) value.
110 // The grid should be big enough so that these values are not needed.
111 int max_h = (this->nu - 1) / 2;
112 int max_k = (this->nv - 1) / 2;
113 int max_l = half_l ? this->nw - 1 : (this->nw - 1) / 2;
114 double max_1_d2 = 0.;
115 if (dmin != 0.) {
116 max_1_d2 = 1. / (dmin * dmin);
117 Miller lim = this->unit_cell.get_hkl_limits(dmin);
118 max_h = std::min(max_h, lim[0]);
119 max_k = std::min(max_k, lim[1]);
120 max_l = std::min(max_l, lim[2]);
121 }
123 std::unique_ptr<GroupOps> gops;
124 if (!with_sys_abs && this->spacegroup)
125 gops.reset(new GroupOps(this->spacegroup->operations()));
126 Miller hkl;
127 for (hkl[0] = -max_h; hkl[0] <= max_h; ++hkl[0]) {
128 int hi = hkl[0] >= 0 ? hkl[0] : hkl[0] + this->nu;
129 int hi_ = -hkl[0] >= 0 ? -hkl[0] : -hkl[0] + this->nu;
130 for (hkl[1] = -max_k; hkl[1] <= max_k; ++hkl[1]) {
131 hkl[2] = -max_l;
132 // (hkl)s with l<0 might be needed to get complete asu.
133 // If they are absent in the data (Hermitian FFT), use Friedel's pairs.
134 if (half_l) {
135 int ki_ = -hkl[1] >= 0 ? -hkl[1] : -hkl[1] + this->nv;
136 for (; hkl[2] < 0; ++hkl[2])
137 if (asu.is_in(hkl) &&
138 (max_1_d2 == 0. || this->unit_cell.calculate_1_d2(hkl) < max_1_d2) &&
139 (with_sys_abs || !gops->is_systematically_absent(hkl)))
140 asu_data.v.push_back({hkl,
141 friedel_mate_value(this->get_value_q(hi_, ki_, -hkl[2]))});
142 }
143 int ki = hkl[1] >= 0 ? hkl[1] : hkl[1] + this->nv;
144 for (; hkl[2] <= max_l; ++hkl[2])
145 if (asu.is_in(hkl) &&
146 (max_1_d2 == 0. || this->unit_cell.calculate_1_d2(hkl) < max_1_d2) &&
147 (with_sys_abs || !gops->is_systematically_absent(hkl)) &&
148 (with_000 || !(hkl[0] == 0 && hkl[1] == 0 && hkl[2] == 0))) {
149 int li = hkl[2] >= 0 ? hkl[2] : hkl[2] + this->nw;
150 asu_data.v.push_back({hkl, this->get_value_q(hi, ki, li)});
151 }
152 }
153 }
154 if (unblur != 0. || mott_bethe)
155 for (HklValue<R>& hv : asu_data.v) {
156 double inv_d2 = this->unit_cell.calculate_1_d2(hv.hkl);
157 double mult = 1;
158 if (unblur != 0)
159 // cf. reciprocal_space_multiplier()
160 mult = std::exp(unblur * 0.25 * inv_d2);
161 if (mott_bethe)
162 // cf. mott_bethe_factor
164 hv.value *= static_cast<decltype(std::abs(hv.value))>(mult);
165 }
166 asu_data.unit_cell_ = this->unit_cell;
167 asu_data.spacegroup_ = this->spacegroup;
168 return asu_data;
169 }
170};
171
172template<typename T> using FPhiGrid = ReciprocalGrid<std::complex<T>>;
173
174} // namespace gemmi
175#endif
AsuData for storing reflection data.
3d grids used by CCP4 maps, cell-method search and hkl data.
std::array< int, 3 > Miller
A synonym for convenient passing of hkl.
Definition unitcell.hpp:129
constexpr double mott_bethe_const()
Definition math.hpp:26
T friedel_mate_value(T v)
Definition recgrid.hpp:14
void fail(const std::string &msg)
Definition fail.hpp:59
grid coordinates (modulo size) and a pointer to value
Definition grid.hpp:240
A common subset of Grid and ReciprocalGrid.
Definition grid.hpp:238
std::vector< T > data
Definition grid.hpp:245
T get_value_q(int u, int v, int w) const
Definition grid.hpp:257
size_t index_q(int u, int v, int w) const
Quick(est) index function, but works only if `0 <= u < nu`, etc.
Definition grid.hpp:210
AxisOrder axis_order
Definition grid.hpp:172
const SpaceGroup * spacegroup
Definition grid.hpp:170
UnitCell unit_cell
Definition grid.hpp:169
bool is_in(const Op::Miller &hkl) const
Definition symmetry.hpp:927
AsuData< R > prepare_asu_data(double dmin=0, double unblur=0, bool with_000=false, bool with_sys_abs=false, bool mott_bethe=false)
Definition recgrid.hpp:101
T get_value_by_hkl(Miller hkl, double unblur=0, bool mott_bethe=false) const
Definition recgrid.hpp:75
Miller to_hkl(const typename GridBase< T >::Point &point) const
Definition recgrid.hpp:53
size_t index_n(int u, int v, int w) const
Definition recgrid.hpp:35
T get_value(int u, int v, int w) const
Definition recgrid.hpp:44
size_t index_checked(int u, int v, int w) const
Definition recgrid.hpp:40
T get_value_or_zero(int u, int v, int w) const
Definition recgrid.hpp:47
double calculate_1_d2(const typename GridBase< T >::Point &point) const
Definition recgrid.hpp:68
void check_index(int u, int v, int w) const
Definition recgrid.hpp:30
double calculate_d(const typename GridBase< T >::Point &point) const
Definition recgrid.hpp:71
void set_value(int u, int v, int w, T x)
Definition recgrid.hpp:50
bool has_index(int u, int v, int w) const
Definition recgrid.hpp:23
double calculate_d(const Miller &hkl) const
Calculate d-spacing.
Definition unitcell.hpp:579
Miller get_hkl_limits(double dmin) const
Definition unitcell.hpp:605
double calculate_1_d2(const Miller &hkl) const
Definition unitcell.hpp:573