Gemmi C++ API
Loading...
Searching...
No Matches
dencalc.hpp
Go to the documentation of this file.
1// Copyright 2019 Global Phasing Ltd.
2//
3// Tools to prepare a grid with values of electron density of a model.
4
5#ifndef GEMMI_DENCALC_HPP_
6#define GEMMI_DENCALC_HPP_
7
8#include "addends.hpp" // for Addends
9#include "formfact.hpp" // for ExpSum
10#include "grid.hpp" // for Grid
11#include "model.hpp" // for Structure, ...
12#include "calculate.hpp" // for calculate_b_aniso_range
13
14namespace gemmi {
15
16template<int N, typename Real>
18 Real y1, dy;
19 std::tie(y1, dy) = precal.calculate_with_derivative(x1);
20 // Generally, density is supposed to decrease with radius.
21 // But if we have addends (in particular -Z for Mott-Bothe),
22 // it can first rise, then decrease. We want to be after the maximum.
23 while (dy > 0) { // unlikely
24 x1 += 1.0f;
25 std::tie(y1, dy) = precal.calculate_with_derivative(x1);
26 }
27 Real x2 = x1;
28 Real y2 = y1;
29 if (y1 < cutoff_level) {
30 while (y1 < cutoff_level) {
31 x2 = x1;
32 y2 = y1;
33 x1 -= 0.5f;
34 std::tie(y1, dy) = precal.calculate_with_derivative(x1);
35 // with addends it's possible to land on the left side of the maximum
36 if (dy > 0 && y1 > 0) { // unlikely
37 while (dy > 0 && y1 > 0 && x1 + 0.1f < x2) {
38 x1 += 0.1f;
39 std::tie(y1, dy) = precal.calculate_with_derivative(x1);
40 }
41 if (y1 < cutoff_level)
42 return x1;
43 break;
44 }
45 if (x1 < 0) { // unlikely
46 x1 = 0;
47 y1 = precal.calculate(x1 * x1);
48 break;
49 }
50 }
51 } else {
52 while (y2 > cutoff_level) {
53 x1 = x2;
54 y1 = y2;
55 x2 += 0.5f;
56 y2 = precal.calculate(x2 * x2);
57 }
58 }
59
60 return x1 + (x1 - x2) / (y1 - y2) * (cutoff_level - y1);
61}
62
63// approximated radius of electron density (IT92) above cutoff=1e-5 for C
64template <typename Real>
66 return (8.5f + 0.075f * b) / (2.4f + 0.0045f * b);
67}
68
69// Usual usage:
70// - set d_min and optionally also other parameters,
71// - set addends to f' values for your wavelength (see fprime.hpp)
72// - use grid.setup_from() to set grid's unit cell and space group
73// - check that Table has SF coefficients for all elements that are to be used
74// - call put_model_density_on_grid()
75// - do FFT using transform_map_to_f_phi()
76// - if blur is used, multiply the SF by reciprocal_space_multiplier()
77template <typename Table, typename GReal>
79 // GReal = type of grid; CReal = type of coefficients in Table
80 using CReal = typename Table::Coef::coef_type;
82 double d_min = 0.;
83 double rate = 1.5;
84 double blur = 0.;
85 float cutoff = 1e-5f;
86#if GEMMI_COUNT_DC
87 size_t atoms_added = 0;
88 size_t density_computations = 0;
89#endif
91
92 double requested_grid_spacing() const { return d_min / (2 * rate); }
93
94 void set_refmac_compatible_blur(const Model& model, bool allow_negative=false) {
95 double spacing = requested_grid_spacing();
96 if (spacing <= 0)
97 spacing = std::min(std::min(grid.spacing[0], grid.spacing[1]), grid.spacing[2]);
98 double b_min = calculate_b_aniso_range(model).first;
99 blur = u_to_b() / 1.1 * sq(spacing) - b_min;
100 if (!allow_negative && blur < 0)
101 blur = 0.;
102 }
103
104 // pre: check if Table::has(atom.element)
105 void add_atom_density_to_grid(const Atom& atom) {
106 Element el = atom.element;
107 const auto& coef = Table::get(el, atom.charge, atom.serial);
109 }
110
111 // Parameter c is a constant factor and has the same meaning as either addend
112 // or c in scattering factor coefficients (a1, b1, ..., c).
113 void add_c_contribution_to_grid(const Atom& atom, float c) {
115 }
116
117 template<int N>
119 if (N == 1)
120 return std::sqrt(std::log(cutoff / std::abs(precal.a[0])) / precal.b[0]);
123 }
124
125 template<typename Coef>
126 void do_add_atom_density_to_grid(const Atom& atom, const Coef& coef, float addend) {
127#if GEMMI_COUNT_DC
128 ++atoms_added;
129#endif
131 if (!atom.aniso.nonzero()) {
132 // isotropic
133 CReal b = static_cast<CReal>(atom.b_iso + blur);
134 auto precal = coef.precalculate_density_iso(b, addend);
136 grid.template use_points_around<true>(fpos, radius, [&](GReal& point, double r2) {
137 point += GReal(atom.occ * precal.calculate((CReal)r2));
138#if GEMMI_COUNT_DC
140#endif
141 }, /*fail_on_too_large_radius=*/false);
142 } else {
143 // anisotropic
144 auto aniso_b = atom.aniso.scaled(CReal(u_to_b())).added_kI(CReal(blur));
145 // rough estimate, so we don't calculate eigenvalues
146 CReal b_max = std::max(std::max(aniso_b.u11, aniso_b.u22), aniso_b.u33);
147 auto precal_iso = coef.precalculate_density_iso(b_max, addend);
149 auto precal = coef.precalculate_density_aniso_b(aniso_b, addend);
150 int du = (int) std::ceil(radius / grid.spacing[0]);
151 int dv = (int) std::ceil(radius / grid.spacing[1]);
152 int dw = (int) std::ceil(radius / grid.spacing[2]);
154 fpos, du, dv, dw,
155 [&](GReal& point, double, const Position& delta, int, int, int) {
156 point += GReal(atom.occ * precal.calculate(delta));
157#if GEMMI_COUNT_DC
159#endif
160 },
161 false, radius);
162 }
163 }
164
166 grid.data.clear();
167 double spacing = requested_grid_spacing();
168 if (spacing > 0)
170 else if (grid.point_count() > 0)
171 // d_min not set, but a custom grid has been setup by the user
172 grid.fill(0.);
173 else
174 fail("initialize_grid(): d_min is not set");
175 }
176
177 void add_model_density_to_grid(const Model& model) {
179 for (const Chain& chain : model.chains)
180 for (const Residue& res : chain.residues)
181 for (const Atom& atom : res.atoms)
183 }
184
190
191 // deprecated, use directly grid.setup_from(st)
195
196 // The argument is 1/d^2 - as outputted by unit_cell.calculate_1_d2(hkl).
197 double reciprocal_space_multiplier(double inv_d2) const {
198 return std::exp(blur * 0.25 * inv_d2);
199 }
200
201 double mott_bethe_factor(const Miller& hkl) const {
202 double inv_d2 = grid.unit_cell.calculate_1_d2(hkl);
203 double factor = -mott_bethe_const() / inv_d2;
205 }
206};
207
208} // namespace gemmi
209#endif
Addends to scattering form factors used in DensityCalculator and StructureFactorCalculator.
Calculate various properties of the model.
Calculation of atomic form factors approximated by a sum of Gaussians. Tables with numerical coeffici...
3d grids used by CCP4 maps, cell-method search and hkl data.
Data structures to store macromolecular structure models.
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
Real determine_cutoff_radius(Real x1, const ExpSum< N, Real > &precal, Real cutoff_level)
Definition dencalc.hpp:17
constexpr float sq(float x)
Definition math.hpp:34
std::pair< double, double > calculate_b_aniso_range(const Model &model)
uses min/max eigenvalues of Baniso, or Biso if B-factor is isotropic
Definition calculate.hpp:91
void fail(const std::string &msg)
Definition fail.hpp:59
constexpr double u_to_b()
Definition math.hpp:29
Real it92_radius_approx(Real b)
Definition dencalc.hpp:65
float get(Element el) const
Definition addends.hpp:18
Represents atom site in macromolecular structure (~100 bytes).
Definition model.hpp:120
SMat33< float > aniso
Definition model.hpp:135
signed char charge
Definition model.hpp:124
float b_iso
Definition model.hpp:134
Element element
Definition model.hpp:125
float occ
Definition model.hpp:132
Position pos
Definition model.hpp:131
void set_grid_cell_and_spacegroup(const Structure &st)
Definition dencalc.hpp:192
double mott_bethe_factor(const Miller &hkl) const
Definition dencalc.hpp:201
void add_model_density_to_grid(const Model &model)
Definition dencalc.hpp:177
void add_c_contribution_to_grid(const Atom &atom, float c)
Definition dencalc.hpp:113
typename Table::Coef::coef_type CReal
Definition dencalc.hpp:80
CReal estimate_radius(const ExpSum< N, CReal > &precal, CReal b) const
Definition dencalc.hpp:118
void put_model_density_on_grid(const Model &model)
Definition dencalc.hpp:185
double reciprocal_space_multiplier(double inv_d2) const
Definition dencalc.hpp:197
void add_atom_density_to_grid(const Atom &atom)
Definition dencalc.hpp:105
void set_refmac_compatible_blur(const Model &model, bool allow_negative=false)
Definition dencalc.hpp:94
double requested_grid_spacing() const
Definition dencalc.hpp:92
void do_add_atom_density_to_grid(const Atom &atom, const Coef &coef, float addend)
Definition dencalc.hpp:126
Fractional coordinates.
Definition unitcell.hpp:50
std::vector< T > data
Definition grid.hpp:245
void fill(T value)
Definition grid.hpp:271
void check_not_empty() const
Definition grid.hpp:247
size_t point_count() const
Definition grid.hpp:174
UnitCell unit_cell
Definition grid.hpp:169
void set_size_from_spacing(double approx_spacing, GridSizeRounding rounding)
Definition grid.hpp:359
void symmetrize_sum()
multiplies grid points on special position
Definition grid.hpp:768
double spacing[3]
spacing between virtual planes, not between points
Definition grid.hpp:322
void setup_from(const S &st, double approx_spacing=0)
Definition grid.hpp:379
std::vector< Chain > chains
Definition model.hpp:722
Coordinates in Angstroms - orthogonal (Cartesian) coordinates.
Definition unitcell.hpp:32
SMat33< Real > scaled(Real s) const
Definition math.hpp:303
bool nonzero() const
Definition math.hpp:292
Fractional fractionalize(const Position &o) const
Definition unitcell.hpp:394
double calculate_1_d2(const Miller &hkl) const
Definition unitcell.hpp:573