Gemmi C++ API
Loading...
Searching...
No Matches
solmask.hpp
Go to the documentation of this file.
1// Copyright 2021 Global Phasing Ltd.
2//
3// Flat bulk solvent mask. With helper tools that modify data on grid.
4
5#ifndef GEMMI_SOLMASK_HPP_
6#define GEMMI_SOLMASK_HPP_
7
8#include "grid.hpp" // for Grid
9#include "floodfill.hpp" // for FloodFill
10#include "model.hpp" // for Model, Atom, ...
11
12namespace gemmi {
13
15
16// data from cctbx/eltbx/van_der_waals_radii.py used to generate identical mask
17inline float cctbx_vdw_radius(El el) {
18 static constexpr float radii[] = {
19 /*X*/ 1.00f,
20 /*H*/ 1.20f, /*He*/ 1.40f,
21 /*Li*/ 1.82f, /*Be*/ 0.63f, /*B*/ 1.75f, /*C*/ 1.775f, /*N*/ 1.50f,
22 /*O*/ 1.45f, /*F*/ 1.47f, /*Ne*/ 1.54f,
23 /*Na*/ 2.27f, /*Mg*/ 1.73f, /*Al*/ 1.50f, /*Si*/ 2.10f, /*P*/ 1.90f,
24 /*S*/ 1.80f, /*Cl*/ 1.75f, /*Ar*/ 1.88f,
25 /*K*/ 2.75f, /*Ca*/ 1.95f, /*Sc*/ 1.32f, /*Ti*/ 1.95f, /*V*/ 1.06f,
26 /*Cr*/ 1.13f, /*Mn*/ 1.19f, /*Fe*/ 1.26f, /*Co*/ 1.13f, /*Ni*/ 1.63f,
27 /*Cu*/ 1.40f, /*Zn*/ 1.39f, /*Ga*/ 1.87f, /*Ge*/ 1.48f, /*As*/ 0.83f,
28 /*Se*/ 1.90f, /*Br*/ 1.85f, /*Kr*/ 2.02f,
29 /*Rb*/ 2.65f, /*Sr*/ 2.02f, /*Y*/ 1.61f, /*Zr*/ 1.42f, /*Nb*/ 1.33f,
30 /*Mo*/ 1.75f, /*Tc*/ 2.00f, /*Ru*/ 1.20f, /*Rh*/ 1.22f, /*Pd*/ 1.63f,
31 /*Ag*/ 1.72f, /*Cd*/ 1.58f, /*In*/ 1.93f, /*Sn*/ 2.17f, /*Sb*/ 1.12f,
32 /*Te*/ 1.26f, /*I*/ 1.98f, /*Xe*/ 2.16f,
33 /*Cs*/ 3.01f, /*Ba*/ 2.41f, /*La*/ 1.83f, /*Ce*/ 1.86f, /*Pr*/ 1.62f,
34 /*Nd*/ 1.79f, /*Pm*/ 1.76f, /*Sm*/ 1.74f, /*Eu*/ 1.96f, /*Gd*/ 1.69f,
35 /*Tb*/ 1.66f, /*Dy*/ 1.63f, /*Ho*/ 1.61f, /*Er*/ 1.59f, /*Tm*/ 1.57f,
36 /*Yb*/ 1.54f, /*Lu*/ 1.53f, /*Hf*/ 1.40f, /*Ta*/ 1.22f, /*W*/ 1.26f,
37 /*Re*/ 1.30f, /*Os*/ 1.58f, /*Ir*/ 1.22f, /*Pt*/ 1.72f, /*Au*/ 1.66f,
38 /*Hg*/ 1.55f, /*Tl*/ 1.96f, /*Pb*/ 2.02f, /*Bi*/ 1.73f, /*Po*/ 1.21f,
39 /*At*/ 1.12f, /*Rn*/ 2.30f,
40 /*Fr*/ 3.24f, /*Ra*/ 2.57f, /*Ac*/ 2.12f, /*Th*/ 1.84f, /*Pa*/ 1.60f,
41 /*U*/ 1.75f, /*Np*/ 1.71f, /*Pu*/ 1.67f, /*Am*/ 1.66f, /*Cm*/ 1.65f,
42 /*Bk*/ 1.64f, /*Cf*/ 1.63f, /*Es*/ 1.62f, /*Fm*/ 1.61f, /*Md*/ 1.60f,
43 /*No*/ 1.59f, /*Lr*/ 1.58f, /*Rf*/ 1.00f, /*Db*/ 1.00f, /*Sg*/ 1.00f,
44 /*Bh*/ 1.00f, /*Hs*/ 1.00f, /*Mt*/ 1.00f, /*Ds*/ 1.00f, /*Rg*/ 1.00f,
45 /*Cn*/ 1.00f, /*Nh*/ 1.00f, /*Fl*/ 1.00f, /*Mc*/ 1.00f, /*Lv*/ 1.00f,
46 /*Ts*/ 1.00f, /*Og*/ 1.00f,
47 /*D*/ 1.20f, /*END*/0.f
48 };
49 static_assert(ce_almost_eq(radii[static_cast<int>(El::D)], 1.2f), "Hmm");
50 static_assert(sizeof(radii) / sizeof(radii[0]) ==
51 static_cast<int>(El::END) + 1, "Hmm");
52 return radii[static_cast<int>(el)];
53}
54
55// Data from Refmac's ener_lib.cif: ionic radius - 0.2A or vdW radius + 0.2A.
56// For full compatibility use r_probe=1.0A and r_shrink=0.8A.
58#if 0
59 static constexpr float radii[] = {
60 /*X*/ 1.00f,
61 /*H*/ 1.40f, /*He*/ 1.60f,
62 /*Li*/ 0.53f, /*Be*/ 0.21f, /*B*/ 0.05f, /*C*/ 1.90f, /*N*/ 1.12f,
63 /*O*/ 1.08f, /*F*/ 0.99f, /*Ne*/ 0.92f,
64 /*Na*/ 0.93f, /*Mg*/ 0.51f, /*Al*/ 0.33f, /*Si*/ 0.20f, /*P*/ 0.39f,
65 /*S*/ 0.20f, /*Cl*/ 1.47f, /*Ar*/ 1.34f,
66 /*K*/ 1.31f, /*Ca*/ 0.94f, /*Sc*/ 0.69f, /*Ti*/ 0.36f, /*V*/ 0.48f,
67 /*Cr*/ 0.33f, /*Mn*/ 0.26f, /*Fe*/ 0.48f, /*Co*/ 0.34f, /*Ni*/ 0.43f,
68 /*Cu*/ 0.51f, /*Zn*/ 0.54f, /*Ga*/ 0.41f, /*Ge*/ 0.20f, /*As*/ 0.28f,
69 /*Se*/ 0.22f, /*Br*/ 0.53f, /*Kr*/ 1.49f,
70 /*Rb*/ 1.28f, /*Sr*/ 1.12f, /*Y*/ 0.84f, /*Zr*/ 0.53f, /*Nb*/ 0.42f,
71 /*Mo*/ 0.35f, /*Tc*/ 0.31f, /*Ru*/ 0.32f, /*Rh*/ 0.49f, /*Pd*/ 0.58f,
72 /*Ag*/ 0.61f, /*Cd*/ 0.72f, /*In*/ 0.56f, /*Sn*/ 0.49f, /*Sb*/ 0.70f,
73 /*Te*/ 0.37f, /*I*/ 0.36f, /*Xe*/ 1.70f,
74 /*Cs*/ 1.61f, /*Ba*/ 1.29f, /*La*/ 0.97f, /*Ce*/ 0.81f, /*Pr*/ 0.79f,
75 /*Nd*/ 0.92f, /*Pm*/ 0.91f, /*Sm*/ 0.90f, /*Eu*/ 0.89f, /*Gd*/ 0.88f,
76 /*Tb*/ 0.70f, /*Dy*/ 0.85f, /*Ho*/ 0.84f, /*Er*/ 0.83f, /*Tm*/ 0.82f,
77 /*Yb*/ 0.81f, /*Lu*/ 0.80f, /*Hf*/ 0.52f, /*Ta*/ 0.58f, /*W*/ 0.36f,
78 /*Re*/ 0.32f, /*Os*/ 0.33f, /*Ir*/ 0.51f, /*Pt*/ 0.51f, /*Au*/ 0.51f,
79 /*Hg*/ 0.90f, /*Tl*/ 0.69f, /*Pb*/ 0.59f, /*Bi*/ 0.70f, /*Po*/ 0.61f,
80 /*At*/ 0.56f, /*Rn*/ 1.80f,
81 /*Fr*/ 1.74f, /*Ra*/ 1.42f, /*Ac*/ 1.06f, /*Th*/ 0.88f, /*Pa*/ 0.72f,
82 /*U*/ 0.46f, /*Np*/ 0.65f, /*Pu*/ 0.65f, /*Am*/ 0.79f, /*Cm*/ 0.79f,
83 /*Bk*/ 0.77f, /*Cf*/ 0.76f, /*Es*/ 1.00f, /*Fm*/ 1.00f, /*Md*/ 1.00f,
84 /*No*/ 1.00f, /*Lr*/ 1.00f, /*Rf*/ 1.00f, /*Db*/ 1.00f, /*Sg*/ 1.00f,
85 /*Bh*/ 1.00f, /*Hs*/ 1.00f, /*Mt*/ 1.00f, /*Ds*/ 1.00f, /*Rg*/ 1.00f,
86 /*Cn*/ 1.00f, /*Nh*/ 1.00f, /*Fl*/ 1.00f, /*Mc*/ 1.00f, /*Lv*/ 1.00f,
87 /*Ts*/ 1.00f, /*Og*/ 1.00f,
88 /*D*/ 1.40f, /*END*/0.f
89 };
90 static_assert(ce_almost_eq(radii[static_cast<int>(El::D)], 1.40f), "Hmm");
91 return radii[static_cast<int>(el)];
92#else
93 // temporary solution used in Refmac
94 switch (el) {
95 case El::H: return 1.4f;
96 case El::D: return 1.4f;
97 case El::O: return 1.08f;
98 case El::C: return 2.0f;
99 case El::N: return 1.12f;
100 default: return 1.6f;
101 };
102#endif
103}
104
105// mask utilities
106
107template<typename T>
108void mask_points_in_radius(Grid<T>& mask, const Model& model,
109 AtomicRadiiSet atomic_radii_set,
110 double r_probe, T value,
111 bool ignore_hydrogen,
112 bool ignore_zero_occupancy_atoms) {
113 for (const Chain& chain : model.chains)
114 for (const Residue& res : chain.residues)
115 for (const Atom& atom : res.atoms) {
116 if ((ignore_hydrogen && atom.is_hydrogen()) ||
117 (ignore_zero_occupancy_atoms && atom.occ <= 0))
118 continue;
119 El elem = atom.element.elem;
120 double r = r_probe;
121 switch (atomic_radii_set) {
122 case AtomicRadiiSet::VanDerWaals: r += vdw_radius(elem); break;
123 case AtomicRadiiSet::Cctbx: r += cctbx_vdw_radius(elem); break;
125 case AtomicRadiiSet::Constant: /* r is included in r_probe */ break;
126 }
127 mask.set_points_around(atom.pos, r, value);
128 }
129}
130
131// deprecated
132template<typename T>
134 double radius, T value,
135 bool ignore_hydrogen,
136 bool ignore_zero_occupancy_atoms) {
138 ignore_hydrogen, ignore_zero_occupancy_atoms);
139}
140
141
142inline std::string distinct_altlocs(const Model& model) {
143 std::string altlocs;
144 for (const Chain& chain : model.chains)
145 for (const Residue& res : chain.residues)
146 add_distinct_altlocs(res, altlocs);
147 return altlocs;
148}
149
159inline
161 AtomicRadiiSet atomic_radii_set, double r_probe,
162 bool ignore_hydrogen,
163 bool ignore_zero_occupancy_atoms) {
164
165 std::string altlocs = distinct_altlocs(model);
166 altlocs += '\0'; // no altloc
167
169 m.copy_metadata_from(mask);
170 for (char& altloc : altlocs) {
171 m.fill(0.0);
172 for (const Chain& chain : model.chains) {
173 for (const Residue& res : chain.residues) {
174 for (const Atom& atom : res.atoms) {
175 if ((ignore_hydrogen && atom.is_hydrogen()) ||
176 (ignore_zero_occupancy_atoms && atom.occ <= 0))
177 continue;
178 if (atom.altloc == altloc) {
179 El elem = atom.element.elem;
180 double r = r_probe;
181 switch (atomic_radii_set) {
182 case AtomicRadiiSet::VanDerWaals: r += vdw_radius(elem); break;
183 case AtomicRadiiSet::Cctbx: r += cctbx_vdw_radius(elem); break;
185 case AtomicRadiiSet::Constant: /* r is included in r_probe */ break;
186 }
187 Fractional fpos = m.unit_cell.fractionalize(atom.pos);
188 m.use_points_around<true>(fpos, r, [&](float& ref, double) {
189 ref = std::min(ref, -atom.occ);
190 }, false);
191 }
192 }
193 }
194 }
195
196 // reduce starting mask
197 for (size_t i = 0; i < m.data.size(); ++i) {
198 if (m.data[i] < 0.0)
199 mask.data[i] += m.data[i];
200 }
201 }
202
203 // When we reduced the solvent mask by the atom occupancy each time
204 // we hit a grid point, we might end up with a value below zero (due
205 // to overlapping atoms) and need to limit it here.
206 for (float& d : mask.data)
207 d = std::max(d, 0.f);
208}
209
215template<typename T>
216void set_margin_around(Grid<T>& mask, double r, T value, T margin_value) {
217 int du = (int) std::floor(r / mask.spacing[0]);
218 int dv = (int) std::floor(r / mask.spacing[1]);
219 int dw = (int) std::floor(r / mask.spacing[2]);
220 double max_spacing2 = sq(std::max(std::max(mask.unit_cell.a / mask.nu,
221 mask.unit_cell.b / mask.nv),
222 mask.unit_cell.c / mask.nw)) + 1e-6;
223 if (2 * du >= mask.nu || 2 * dv >= mask.nv || 2 * dw >= mask.nw)
224 fail("grid operation failed: radius bigger than half the unit cell?");
225 std::vector<std::array<int,3>> stencil1;
226 std::vector<std::array<int,3>> stencil2;
227 for (int w = -dw; w <= dw; ++w)
228 for (int v = -dv; v <= dv; ++v)
229 for (int u = -du; u <= du; ++u) {
230 Fractional fdelta = mask.get_fractional(u, v, w);
231 double r2 = mask.unit_cell.orthogonalize_difference(fdelta).length_sq();
232 if (r2 <= r * r && r2 != 0.) {
233 std::array<int,3> wvu{{w <= 0 ? w : w - mask.nw,
234 v <= 0 ? v : v - mask.nv,
235 u <= 0 ? u : u - mask.nu}};
236 if (r2 < max_spacing2)
237 stencil1.push_back(wvu);
238 else
239 stencil2.push_back(wvu);
240 }
241 }
242 if (stencil2.empty()) {
243 // r is small; it should be faster to go through masked points and
244 // for each one check if any point in given radius are unmasked.
245 for (typename Grid<T>::Point p : mask)
246 if (*p.value < value) {
247 for (const auto& wvu : stencil1) {
248 size_t idx = mask.index_near_zero(p.u + wvu[2], p.v + wvu[1], p.w + wvu[0]);
249 if (mask.data[idx] >= value) {
251 break;
252 }
253 }
254 }
255 } else {
256 // r is large; it should be faster to go through unmasked points
257 // and for each one check if it has masked near neighbors (stencil1).
258 // These neighbors get marked as margin. If all near neighbors are
259 // unmasked, we can skip further neighbors (they will be checked
260 // from other points).
261 for (typename Grid<T>::Point p : mask) {
262 if (*p.value >= value) {
263 bool found = false;
264 for (const auto& wvu : stencil1) {
265 size_t idx = mask.index_near_zero(p.u + wvu[2], p.v + wvu[1], p.w + wvu[0]);
266 if (mask.data[idx] < value) {
267 mask.data[idx] = margin_value;
268 found = true;
269 }
270 }
271 if (found)
272 for (const auto& wvu : stencil2) {
273 size_t idx = mask.index_near_zero(p.u + wvu[2], p.v + wvu[1], p.w + wvu[0]);
274 if (mask.data[idx] < value)
275 mask.data[idx] = margin_value;
276 }
277 }
278 }
279 }
280 //printf("stencil sizes: %zu\n", stencil1.size(), stencil2.size());
281 //printf("margin: %zu\n", std::count(mask.data.begin(), mask.data.end(), margin_value));
282}
283
288 bool use_atom_occupancy = false;
289 double rprobe;
290 double rshrink;
293 double requested_spacing = 0.;
294
298
299 // currently this function sets also parameters other than radii
303 ignore_hydrogen = true;
305 switch (choice) {
307 rprobe = 1.0;
308 rshrink = 1.1;
310 break;
312 rprobe = 1.1;
313 rshrink = 0.9;
315 break;
317 rprobe = 1.0;
318 rshrink = 0.8;
319 island_min_volume = 50; // the exact value used in Refmac is yet to be found
320 break;
322 rprobe = 0;
323 rshrink = 0;
325 break;
326 }
327 }
328
330 template<typename T> void clear(Grid<T>& grid) const { grid.fill((T)1); }
331
333 template<typename T> void mask_points(Grid<T>& grid, const Model& model) const {
336 }
337
338 void mask_points(Grid<float>& grid, const Model& model) const {
342 else
343 mask_points<float>(grid, model);
344 }
345
350 template<typename T> void symmetrize(Grid<T>& grid) const {
351 if (std::is_same<T, std::int8_t>::value) {
352 grid.symmetrize([&](T a, T b) { return a == (T)0 || b == (T)0 ? (T)0 : (T)1; });
353 }
354 else {
355 grid.symmetrize([&](T a, T b) { return a < b ? a : b; });
356 }
357 }
358
359 template<typename T> void shrink(Grid<T>& grid) const {
360 if (rshrink > 0) {
361 set_margin_around(grid, rshrink, (T)1, (T)-1);
362 grid.change_values((T)-1, (T)1);
363 }
364 }
365
366 template<typename T> void invert(Grid<T>& grid) const {
367 for (auto& v : grid.data)
368 v = (T)1 - v;
369 }
370
371
372 // Removes small islands of Land=1 in the sea of 0. Uses flood fill.
373 // cf. find_blobs_by_flood_fill()
374 // Currently doesn't work mask from mask_points_using_occupancy().
375 template<typename T> int remove_islands(Grid<T>& grid) const {
376 if (island_min_volume <= 0)
377 return 0;
378 size_t limit = static_cast<size_t>(island_min_volume * grid.point_count()
379 / grid.unit_cell.volume);
380 int counter = 0;
382 flood_fill.for_each_islands([&](typename FloodFill<T,1>::Result& r) {
383 //printf("island %d: %zu in %zu (limit: %zu)\n",
384 // counter, r.point_count(), lines.size(), limit);
385 if (r.point_count() <= limit) {
386 ++counter;
387 flood_fill.set_volume_values(r, (T)0);
388 }
389 });
390 return counter;
391 }
392
393 template<typename T> void put_mask_on_grid(Grid<T>& grid, const Model& model) const {
394 clear(grid);
395 assert(!grid.data.empty());
396 mask_points(grid, model);
397 symmetrize(grid);
398 remove_islands(grid);
399 shrink(grid);
400 }
401
402 void set_to_zero(Grid<float>& grid, const Model& model) const {
403 mask_points(grid, model);
404 grid.symmetrize([&](float a, float b) { return b == 0.f ? 0.f : a; });
405 }
406
407#if 0
408 template<typename T> void put_mask_on_grid(Grid<T>& grid, const Model& model) {
409 // use twice finer grid for solvent mask
411 mask.copy_metadata_from(grid);
412 mask.set_size(2*grid.nu, 2*grid.nv, 2*grid.nw);
413 mask.data.resize(8 * grid.data.size(), 1);
414 put_mask_on_grid(mask, model);
415 for (int w = 0, idx = 0; w < grid.nw; ++w)
416 for (int v = 0; v < grid.nv; ++v)
417 for (int u = 0; u < grid.nu; ++u, ++idx) {
418 grid.data[idx] = 0;
419 for (int wa = 0; wa < 2; ++wa)
420 for (int va = 0; va < 2; ++va)
421 for (int ua = 0; ua < 2; ++ua)
422 grid.data[idx] += mask.get_value_q(2*u + ua, 2*v + va, 2*w + wa);
423 grid.data[idx] *= 1. / 8;
424 }
425#endif
426};
427
428struct NodeInfo {
429 double dist_sq; // distance from the nearest atom
430 bool found = false; // the mask flag
431 //Element elem = El::X;
432 int u = 0, v = 0, w = 0; // not normalized near-model grid coordinates
433};
434
436inline void mask_with_node_info(Grid<NodeInfo>& mask, const Model& model, double radius) {
438 default_ni.dist_sq = radius * radius;
439 mask.fill(default_ni);
440 // cf. use_points_around()
441 int du = (int) std::ceil(radius / mask.spacing[0]);
442 int dv = (int) std::ceil(radius / mask.spacing[1]);
443 int dw = (int) std::ceil(radius / mask.spacing[2]);
444 mask.template check_size_for_points_in_box<true>(du, dv, dw, false);
445 for (const Chain& chain : model.chains)
446 for (const Residue& res : chain.residues)
447 for (const Atom& atom : res.atoms) {
448 Fractional frac0 = mask.unit_cell.fractionalize(atom.pos);
449 mask.template do_use_points_in_box<true>(
450 frac0, du, dv, dw,
451 [&](NodeInfo& ni, double d2, const Position&, int u, int v, int w) {
452 if (d2 < ni.dist_sq) {
453 ni.dist_sq = d2;
454 ni.found = true;
455 //ni.elem = atom.element;
456 ni.u = u;
457 ni.v = v;
458 ni.w = w;
459 }
460 },
461 radius);
462 }
463}
464
470 std::vector<GridOp> symmetry_ops = mask.get_scaled_ops_except_id();
471 size_t idx = 0;
472 for (int w = 0; w != mask.nw; ++w)
473 for (int v = 0; v != mask.nv; ++v)
474 for (int u = 0; u != mask.nu; ++u, ++idx) {
475 NodeInfo& ni = mask.data[idx];
476 if (ni.found)
477 for (const GridOp& grid_op : symmetry_ops) {
478 std::array<int,3> t = grid_op.apply(u, v, w);
479 NodeInfo& im_ni = mask.data[mask.index_n(t[0], t[1], t[2])];
480 if (im_ni.found && im_ni.dist_sq > ni.dist_sq)
481 im_ni.found = false;
482 }
483 }
484}
485
486// TODO: would it be better to use src_model rather than dest_model?
487template<typename T>
489 const Transform& tr,
490 const Model& dest_model, double radius,
491 int order=1) {
492 Grid<NodeInfo> mask;
493 mask.copy_metadata_from(dest);
496 // Interpolate values for selected nodes.
497 FTransform frac_tr = src.unit_cell.frac.combine(tr.combine(dest.unit_cell.orth));
498 for (size_t idx = 0; idx != mask.data.size(); ++idx) {
499 const NodeInfo& ni = mask.data[idx];
500 if (ni.found) {
501 Fractional dest_fr = dest.get_fractional(ni.u, ni.v, ni.w);
503 dest.data[idx] = src.interpolate_value(src_fr, order);
504 }
505 }
506}
507
508
509// add soft edge to 1/0 mask using raised cosine function
510template<typename T>
511void add_soft_edge_to_mask(Grid<T>& grid, double width) {
512 const double width2 = width * width;
513 const int du = (int) std::ceil(width / grid.spacing[0]);
514 const int dv = (int) std::ceil(width / grid.spacing[1]);
515 const int dw = (int) std::ceil(width / grid.spacing[2]);
516
517 for (int w = 0; w < grid.nw; ++w)
518 for (int v = 0; v < grid.nv; ++v)
519 for (int u = 0; u < grid.nu; ++u) {
520 size_t idx = grid.index_q(u, v, w);
521 if (grid.data[idx] >= 1e-3) continue;
522 double min_d2 = width2 + 1;
523 Fractional fctr = grid.get_fractional(u, v, w);
524 grid.template use_points_in_box<true>(
525 fctr, du, dv, dw,
526 [&](T& point, double d2, const Position&, int, int, int) {
527 if (point > 0.999) {
528 if (d2 < min_d2)
529 min_d2 = d2;
530 }
531 });
532 if (min_d2 < width2)
533 grid.data[idx] = T(0.5 + 0.5 * std::cos(pi() * std::sqrt(min_d2) / width));
534 }
535}
536
537} // namespace gemmi
538#endif
The flood fill (scanline fill) algorithm for Grid. Assumes periodic boundary conditions in the grid a...
3d grids used by CCP4 maps, cell-method search and hkl data.
Data structures to store macromolecular structure models.
void mask_points_in_radius(Grid< T > &mask, const Model &model, AtomicRadiiSet atomic_radii_set, double r_probe, T value, bool ignore_hydrogen, bool ignore_zero_occupancy_atoms)
Definition solmask.hpp:108
constexpr bool ce_almost_eq(double x, double y)
Definition elem.hpp:70
std::string distinct_altlocs(const Model &model)
Definition solmask.hpp:142
void interpolate_grid_around_model(Grid< T > &dest, const Grid< T > &src, const Transform &tr, const Model &dest_model, double radius, int order=1)
Definition solmask.hpp:488
float vdw_radius(El el)
Definition elem.hpp:161
void add_distinct_altlocs(const Residue &res, std::string &altlocs)
Definition model.hpp:292
void mask_points_using_occupancy(Grid< float > &mask, const Model &model, AtomicRadiiSet atomic_radii_set, double r_probe, bool ignore_hydrogen, bool ignore_zero_occupancy_atoms)
mask all grid points within a varying radius around model atoms
Definition solmask.hpp:160
float cctbx_vdw_radius(El el)
Definition solmask.hpp:17
constexpr float sq(float x)
Definition math.hpp:34
void unmask_symmetry_mates(Grid< NodeInfo > &mask)
Skip nodes that are closer to a symmetry mate of the model than to the original model.
Definition solmask.hpp:469
constexpr double pi()
Definition math.hpp:16
AtomicRadiiSet
Definition solmask.hpp:14
void set_margin_around(Grid< T > &mask, double r, T value, T margin_value)
All points close to a grid point which is currently set below a value are changed.
Definition solmask.hpp:216
void fail(const std::string &msg)
Definition fail.hpp:59
void add_soft_edge_to_mask(Grid< T > &grid, double width)
Definition solmask.hpp:511
float refmac_radius_for_bulk_solvent(El el)
Definition solmask.hpp:57
void mask_with_node_info(Grid< NodeInfo > &mask, const Model &model, double radius)
Populate NodeInfo grid for nodes near the model.
Definition solmask.hpp:436
void mask_points_in_constant_radius(Grid< T > &mask, const Model &model, double radius, T value, bool ignore_hydrogen, bool ignore_zero_occupancy_atoms)
Definition solmask.hpp:133
Represents atom site in macromolecular structure (~100 bytes).
Definition model.hpp:120
Like Transform, but apply() arg is Fractional (not Vec3 - for type safety).
Definition unitcell.hpp:112
Fractional coordinates.
Definition unitcell.hpp:50
typename GridBase< T >::Point Point
Definition grid.hpp:313
std::vector< Chain > chains
Definition model.hpp:722
Coordinates in Angstroms - orthogonal (Cartesian) coordinates.
Definition unitcell.hpp:32
void invert(Grid< T > &grid) const
Definition solmask.hpp:366
void mask_points(Grid< float > &grid, const Model &model) const
Definition solmask.hpp:338
SolventMasker(AtomicRadiiSet choice, double constant_r_=0.)
Definition solmask.hpp:295
int remove_islands(Grid< T > &grid) const
Definition solmask.hpp:375
void shrink(Grid< T > &grid) const
Definition solmask.hpp:359
void set_to_zero(Grid< float > &grid, const Model &model) const
Definition solmask.hpp:402
void put_mask_on_grid(Grid< T > &grid, const Model &model) const
Definition solmask.hpp:393
AtomicRadiiSet atomic_radii_set
Definition solmask.hpp:285
void set_radii(AtomicRadiiSet choice, double constant_r_=0.)
Definition solmask.hpp:300
void symmetrize(Grid< T > &grid) const
Apply symmetry to grid (to fill whole grid).
Definition solmask.hpp:350
bool ignore_zero_occupancy_atoms
Definition solmask.hpp:287
void clear(Grid< T > &grid) const
fill whole grid with 1
Definition solmask.hpp:330
void mask_points(Grid< T > &grid, const Model &model) const
set grid points around atoms to 0
Definition solmask.hpp:333
Transform combine(const Transform &b) const
Definition math.hpp:404