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 "asudata.hpp"
9#include "grid.hpp"
10
11namespace gemmi {
12
13inline signed char friedel_mate_value(signed char v) { return v; }
14inline float friedel_mate_value(float v) { return v; }
15inline double friedel_mate_value(double v) { return v; }
16
17template<typename T>
18std::complex<T> friedel_mate_value(const std::complex<T>& v) {
19 return std::conj(v);
20}
21
22template<typename T>
24 bool half_l = false; // hkl grid that stores only l>=0
25 bool has_index(int u, int v, int w) const {
26 bool half_u = (half_l && this->axis_order == AxisOrder::ZYX);
27 bool half_w = (half_l && this->axis_order != AxisOrder::ZYX);
28 return std::abs(half_u ? u : 2 * u) < this->nu &&
29 std::abs(2 * v) < this->nv &&
30 std::abs(half_w ? w : 2 * w) < this->nw;
31 }
32 void check_index(int u, int v, int w) const {
33 if (!has_index(u, v, w))
34 throw std::out_of_range("ReciprocalGrid: index out of grid.");
35 }
36 // Similar to Grid::index_n(), but works only for -nu <= u < nu, etc.
37 size_t index_n(int u, int v, int w) const {
38 return this->index_q(u >= 0 ? u : u + this->nu,
39 v >= 0 ? v : v + this->nv,
40 w >= 0 ? w : w + this->nw);
41 }
42 size_t index_checked(int u, int v, int w) const {
43 check_index(u, v, w);
44 return index_n(u, v, w);
45 }
46 T get_value(int u, int v, int w) const {
47 return this->data[index_checked(u, v, w)];
48 }
49 T get_value_or_zero(int u, int v, int w) const {
50 return has_index(u, v, w) ? this->data[index_n(u, v, w)] : T{};
51 }
52 void set_value(int u, int v, int w, T x) {
53 this->data[index_checked(u, v, w)] = x;
54 }
55 Miller to_hkl(const typename GridBase<T>::Point& point) const {
56 Miller hkl{{point.u, point.v, point.w}};
57 if (2 * point.u >= this->nu &&
58 !(half_l && this->axis_order == AxisOrder::ZYX))
59 hkl[0] -= this->nu;
60 if (2 * point.v >= this->nv)
61 hkl[1] -= this->nv;
62 if (2 * point.w >= this->nw &&
63 !(half_l && this->axis_order != AxisOrder::ZYX))
64 hkl[2] -= this->nw;
65 if (this->axis_order == AxisOrder::ZYX)
66 std::swap(hkl[0], hkl[2]);
67 return hkl;
68 }
69
70 double calculate_1_d2(const typename GridBase<T>::Point& point) const {
71 return this->unit_cell.calculate_1_d2(to_hkl(point));
72 }
73 double calculate_d(const typename GridBase<T>::Point& point) const {
74 return this->unit_cell.calculate_d(to_hkl(point));
75 }
76
78 bool mott_bethe=false) const {
79 if (this->axis_order == AxisOrder::ZYX)
80 fail("get_value_by_hkl(): ZYX order is not supported yet");
81 T value;
82 if (half_l && hkl[2] < 0)
83 value = friedel_mate_value(this->get_value(-hkl[0], -hkl[1], -hkl[2]));
84 else
85 value = this->get_value(hkl[0], hkl[1], hkl[2]);
86
87 if (unblur != 0. || mott_bethe) {
88 double inv_d2 = this->unit_cell.calculate_1_d2(hkl);
89 double mult = 1;
90 if (unblur != 0)
91 // cf. reciprocal_space_multiplier()
92 mult = std::exp(unblur * 0.25 * inv_d2);
93 if (mott_bethe)
94 // cf. mott_bethe_factor
96 value *= static_cast<decltype(std::abs(value))>(mult);
97 }
98 return value;
99 }
100
101 // the result is always sorted by h,k,l
102 template <typename R=T>
103 AsuData<R> prepare_asu_data(double dmin=0, double unblur=0,
104 bool with_000=false, bool with_sys_abs=false,
105 bool mott_bethe=false) {
107 if (this->axis_order == AxisOrder::ZYX)
108 fail("get_asu_values(): ZYX order is not supported yet");
109 int max_h = (this->nu - 1) / 2;
110 int max_k = (this->nv - 1) / 2;
111 int max_l = half_l ? this->nw - 1 : (this->nw - 1) / 2;
112 double max_1_d2 = 0.;
113 if (dmin != 0.) {
114 max_1_d2 = 1. / (dmin * dmin);
115 Miller lim = this->unit_cell.get_hkl_limits(dmin);
116 max_h = std::min(max_h, lim[0]);
117 max_k = std::min(max_k, lim[1]);
118 max_l = std::min(max_l, lim[2]);
119 }
121 std::unique_ptr<GroupOps> gops;
122 if (!with_sys_abs && this->spacegroup)
123 gops.reset(new GroupOps(this->spacegroup->operations()));
124 Miller hkl;
125 for (hkl[0] = -max_h; hkl[0] <= max_h; ++hkl[0]) {
126 int hi = hkl[0] >= 0 ? hkl[0] : hkl[0] + this->nu;
127 int hi_ = -hkl[0] >= 0 ? -hkl[0] : -hkl[0] + this->nu;
128 for (hkl[1] = -max_k; hkl[1] <= max_k; ++hkl[1]) {
129 hkl[2] = -max_l;
130 // (hkl)s with l<0 might be needed to get complete asu.
131 // If they are absent in the data (Hermitian FFT), use Friedel's pairs.
132 if (half_l) {
133 int ki_ = -hkl[1] >= 0 ? -hkl[1] : -hkl[1] + this->nv;
134 for (; hkl[2] < 0; ++hkl[2])
135 if (asu.is_in(hkl) &&
136 (max_1_d2 == 0. || this->unit_cell.calculate_1_d2(hkl) < max_1_d2) &&
137 (with_sys_abs || !gops->is_systematically_absent(hkl)))
138 asu_data.v.push_back({hkl,
139 friedel_mate_value(this->get_value_q(hi_, ki_, -hkl[2]))});
140 }
141 int ki = hkl[1] >= 0 ? hkl[1] : hkl[1] + this->nv;
142 for (; hkl[2] <= max_l; ++hkl[2])
143 if (asu.is_in(hkl) &&
144 (max_1_d2 == 0. || this->unit_cell.calculate_1_d2(hkl) < max_1_d2) &&
145 (with_sys_abs || !gops->is_systematically_absent(hkl)) &&
146 (with_000 || !(hkl[0] == 0 && hkl[1] == 0 && hkl[2] == 0))) {
147 int li = hkl[2] >= 0 ? hkl[2] : hkl[2] + this->nw;
148 asu_data.v.push_back({hkl, this->get_value_q(hi, ki, li)});
149 }
150 }
151 }
152 if (unblur != 0. || mott_bethe)
153 for (HklValue<R>& hv : asu_data.v) {
154 double inv_d2 = this->unit_cell.calculate_1_d2(hv.hkl);
155 double mult = 1;
156 if (unblur != 0)
157 // cf. reciprocal_space_multiplier()
158 mult = std::exp(unblur * 0.25 * inv_d2);
159 if (mott_bethe)
160 // cf. mott_bethe_factor
162 hv.value *= static_cast<decltype(std::abs(hv.value))>(mult);
163 }
164 asu_data.unit_cell_ = this->unit_cell;
165 asu_data.spacegroup_ = this->spacegroup;
166 return asu_data;
167 }
168};
169
170template<typename T> using FPhiGrid = ReciprocalGrid<std::complex<T>>;
171
172} // namespace gemmi
173#endif
signed char friedel_mate_value(signed char v)
Definition recgrid.hpp:13
std::array< int, 3 > Miller
A synonym for convenient passing of hkl.
Definition unitcell.hpp:128
constexpr double mott_bethe_const()
Definition math.hpp:26
void fail(const std::string &msg)
Definition fail.hpp:59
grid coordinates (modulo size) and a pointer to value
Definition grid.hpp:230
A common subset of Grid and ReciprocalGrid.
Definition grid.hpp:228
std::vector< T > data
Definition grid.hpp:235
T get_value_q(int u, int v, int w) const
Definition grid.hpp:247
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:203
AxisOrder axis_order
Definition grid.hpp:165
const SpaceGroup * spacegroup
Definition grid.hpp:163
UnitCell unit_cell
Definition grid.hpp:162
bool is_in(const Op::Miller &hkl) const
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:103
T get_value_by_hkl(Miller hkl, double unblur=0, bool mott_bethe=false) const
Definition recgrid.hpp:77
Miller to_hkl(const typename GridBase< T >::Point &point) const
Definition recgrid.hpp:55
size_t index_n(int u, int v, int w) const
Definition recgrid.hpp:37
T get_value(int u, int v, int w) const
Definition recgrid.hpp:46
size_t index_checked(int u, int v, int w) const
Definition recgrid.hpp:42
T get_value_or_zero(int u, int v, int w) const
Definition recgrid.hpp:49
double calculate_1_d2(const typename GridBase< T >::Point &point) const
Definition recgrid.hpp:70
void check_index(int u, int v, int w) const
Definition recgrid.hpp:32
double calculate_d(const typename GridBase< T >::Point &point) const
Definition recgrid.hpp:73
void set_value(int u, int v, int w, T x)
Definition recgrid.hpp:52
bool has_index(int u, int v, int w) const
Definition recgrid.hpp:25
double calculate_d(const Miller &hkl) const
Calculate d-spacing.
Definition unitcell.hpp:535
Miller get_hkl_limits(double dmin) const
Definition unitcell.hpp:561
double calculate_1_d2(const Miller &hkl) const
Definition unitcell.hpp:529