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(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(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
106template<typename T>
108 double radius, T value,
109 bool ignore_hydrogen,
110 bool ignore_zero_occupancy_atoms) {
111 for (const Chain& chain : model.chains)
112 for (const Residue& res : chain.residues)
113 for (const Atom& atom : res.atoms) {
114 if ((ignore_hydrogen && atom.is_hydrogen()) ||
115 (ignore_zero_occupancy_atoms && atom.occ <= 0))
116 continue;
117 mask.set_points_around(atom.pos, radius, value);
118 }
119}
120
121template<typename T>
123 AtomicRadiiSet atomic_radii_set,
124 double r_probe, T value,
125 bool ignore_hydrogen,
126 bool ignore_zero_occupancy_atoms) {
127 for (const Chain& chain : model.chains)
128 for (const Residue& res : chain.residues)
129 for (const Atom& atom : res.atoms) {
130 if ((ignore_hydrogen && atom.is_hydrogen()) ||
131 (ignore_zero_occupancy_atoms && atom.occ <= 0))
132 continue;
133 El elem = atom.element.elem;
134 double r = 0;
135 switch (atomic_radii_set) {
136 case AtomicRadiiSet::VanDerWaals: r = vdw_radius(elem); break;
137 case AtomicRadiiSet::Cctbx: r = cctbx_vdw_radius(elem); break;
139 case AtomicRadiiSet::Constant: assert(0); break;
140 }
141 mask.set_points_around(atom.pos, r + r_probe, value);
142 }
143}
144
145// All points != value in a distance < r from value are set to margin_value
146template<typename T>
147void set_margin_around(Grid<T>& mask, double r, T value, T margin_value) {
148 int du = (int) std::floor(r / mask.spacing[0]);
149 int dv = (int) std::floor(r / mask.spacing[1]);
150 int dw = (int) std::floor(r / mask.spacing[2]);
151 double max_spacing2 = sq(std::max(std::max(mask.unit_cell.a / mask.nu,
152 mask.unit_cell.b / mask.nv),
153 mask.unit_cell.c / mask.nw)) + 1e-6;
154 if (2 * du >= mask.nu || 2 * dv >= mask.nv || 2 * dw >= mask.nw)
155 fail("grid operation failed: radius bigger than half the unit cell?");
156 std::vector<std::array<int,3>> stencil1;
157 std::vector<std::array<int,3>> stencil2;
158 for (int w = -dw; w <= dw; ++w)
159 for (int v = -dv; v <= dv; ++v)
160 for (int u = -du; u <= du; ++u) {
161 Fractional fdelta = mask.get_fractional(u, v, w);
162 double r2 = mask.unit_cell.orthogonalize_difference(fdelta).length_sq();
163 if (r2 <= r * r && r2 != 0.) {
164 std::array<int,3> wvu{{w <= 0 ? w : w - mask.nw,
165 v <= 0 ? v : v - mask.nv,
166 u <= 0 ? u : u - mask.nu}};
167 if (r2 < max_spacing2)
168 stencil1.push_back(wvu);
169 else
170 stencil2.push_back(wvu);
171 }
172 }
173 if (stencil2.empty()) {
174 for (typename Grid<T>::Point p : mask)
175 if (*p.value != value) {
176 for (const auto& wvu : stencil1) {
177 size_t idx = mask.index_near_zero(p.u + wvu[2], p.v + wvu[1], p.w + wvu[0]);
178 if (mask.data[idx] == value) {
180 break;
181 }
182 }
183 }
184 } else {
185 for (typename Grid<T>::Point p : mask) {
186 if (*p.value == value) {
187 bool found = false;
188 for (const auto& wvu : stencil1) {
189 size_t idx = mask.index_near_zero(p.u + wvu[2], p.v + wvu[1], p.w + wvu[0]);
190 if (mask.data[idx] != value) {
191 mask.data[idx] = margin_value;
192 found = true;
193 }
194 }
195 if (found)
196 for (const auto& wvu : stencil2) {
197 size_t idx = mask.index_near_zero(p.u + wvu[2], p.v + wvu[1], p.w + wvu[0]);
198 if (mask.data[idx] != value)
199 mask.data[idx] = margin_value;
200 }
201 }
202 }
203 }
204 //printf("stencil sizes: %zu\n", stencil1.size(), stencil2.size());
205 //printf("margin: %zu\n", std::count(mask.data.begin(), mask.data.end(), margin_value));
206}
207
212 double rprobe;
213 double rshrink;
216
220
221 // currently this function sets also parameters other than radii
225 ignore_hydrogen = true;
227 switch (choice) {
229 rprobe = 1.0;
230 rshrink = 1.1;
232 break;
234 rprobe = 1.1;
235 rshrink = 0.9;
237 break;
239 rprobe = 1.0;
240 rshrink = 0.8;
241 island_min_volume = 50; // the exact value used in Refmac is yet to be found
242 break;
244 rprobe = 0;
245 rshrink = 0;
247 break;
248 }
249 }
250
251 template<typename T> void clear(Grid<T>& grid) const { grid.fill((T)1); }
252
261
262 template<typename T> void symmetrize(Grid<T>& grid) const {
263 grid.symmetrize([&](T a, T b) { return a == (T)0 || b == (T)0 ? (T)0 : (T)1; });
264 }
265
266 template<typename T> void shrink(Grid<T>& grid) const {
267 if (rshrink > 0) {
268 set_margin_around(grid, rshrink, (T)1, (T)-1);
269 grid.change_values((T)-1, (T)1);
270 }
271 }
272
273 template<typename T> void invert(Grid<T>& grid) const {
274 for (auto& v : grid.data)
275 v = (T)1 - v;
276 }
277
278
279 // Removes small islands of Land=1 in the sea of 0. Uses flood fill.
280 // cf. find_blobs_by_flood_fill()
281 template<typename T> int remove_islands(Grid<T>& grid) const {
282 if (island_min_volume <= 0)
283 return 0;
284 size_t limit = static_cast<size_t>(island_min_volume * grid.point_count()
285 / grid.unit_cell.volume);
286 int counter = 0;
288 flood_fill.for_each_islands([&](typename FloodFill<T,1>::Result& r) {
289 //printf("island %d: %zu in %zu (limit: %zu)\n",
290 // counter, r.point_count(), lines.size(), limit);
291 if (r.point_count() <= limit) {
292 ++counter;
293 flood_fill.set_volume_values(r, (T)0);
294 }
295 });
296 return counter;
297 }
298
299 template<typename T> void put_mask_on_grid(Grid<T>& grid, const Model& model) const {
300 clear(grid);
301 assert(!grid.data.empty());
302 mask_points(grid, model);
303 symmetrize(grid);
304 remove_islands(grid);
305 shrink(grid);
306 }
307
308 void set_to_zero(Grid<float>& grid, const Model& model) const {
309 mask_points(grid, model);
310 grid.symmetrize([&](float a, float b) { return b == 0.f ? 0.f : a; });
311 }
312
313#if 0
314 template<typename T> void put_mask_on_grid(Grid<T>& grid, const Model& model) {
315 // use twice finer grid for solvent mask
317 mask.copy_metadata_from(grid);
318 mask.set_size(2*grid.nu, 2*grid.nv, 2*grid.nw);
319 mask.data.resize(8 * grid.data.size(), 1);
320 put_mask_on_grid(mask, model);
321 for (int w = 0, idx = 0; w < grid.nw; ++w)
322 for (int v = 0; v < grid.nv; ++v)
323 for (int u = 0; u < grid.nu; ++u, ++idx) {
324 grid.data[idx] = 0;
325 for (int wa = 0; wa < 2; ++wa)
326 for (int va = 0; va < 2; ++va)
327 for (int ua = 0; ua < 2; ++ua)
328 grid.data[idx] += mask.get_value_q(2*u + ua, 2*v + va, 2*w + wa);
329 grid.data[idx] *= 1. / 8;
330 }
331#endif
332};
333
334// TODO: add argument Box<Fractional> src_extent
335template<typename T>
336void interpolate_grid(Grid<T>& dest, const Grid<T>& src, const Transform& tr, int order=2) {
337 FTransform frac_tr = src.unit_cell.frac.combine(tr).combine(dest.unit_cell.orth);
338 size_t idx = 0;
339 for (int w = 0; w != dest.nw; ++w)
340 for (int v = 0; v != dest.nv; ++v)
341 for (int u = 0; u != dest.nu; ++u, ++idx) {
342 Fractional dest_fr = dest.get_fractional(u, v, w);
344 dest.data[idx] = src.interpolate(src_fr, order);
345 }
346}
347
348struct NodeInfo {
349 double dist_sq; // distance from the nearest atom
350 bool found = false; // the mask flag
351 //Element elem = El::X;
352 int u = 0, v = 0, w = 0; // not normalized near-model grid coordinates
353};
354
356inline void mask_with_node_info(Grid<NodeInfo>& mask, const Model& model, double radius) {
358 default_ni.dist_sq = radius * radius;
359 mask.fill(default_ni);
360 // cf. use_points_around()
361 int du = (int) std::ceil(radius / mask.spacing[0]);
362 int dv = (int) std::ceil(radius / mask.spacing[1]);
363 int dw = (int) std::ceil(radius / mask.spacing[2]);
364 mask.template check_size_for_points_in_box<true>(du, dv, dw, false);
365 for (const Chain& chain : model.chains)
366 for (const Residue& res : chain.residues)
367 for (const Atom& atom : res.atoms) {
368 Fractional frac0 = mask.unit_cell.fractionalize(atom.pos);
369 mask.template do_use_points_in_box<true>(
370 frac0, du, dv, dw,
371 [&](NodeInfo& ni, double d2, const Position&, int u, int v, int w) {
372 if (d2 < ni.dist_sq) {
373 ni.dist_sq = d2;
374 ni.found = true;
375 //ni.elem = atom.element;
376 ni.u = u;
377 ni.v = v;
378 ni.w = w;
379 }
380 },
381 radius);
382 }
383}
384
390 std::vector<GridOp> symmetry_ops = mask.get_scaled_ops_except_id();
391 size_t idx = 0;
392 for (int w = 0; w != mask.nw; ++w)
393 for (int v = 0; v != mask.nv; ++v)
394 for (int u = 0; u != mask.nu; ++u, ++idx) {
395 NodeInfo& ni = mask.data[idx];
396 if (ni.found)
397 for (const GridOp& grid_op : symmetry_ops) {
398 std::array<int,3> t = grid_op.apply(u, v, w);
399 NodeInfo& im_ni = mask.data[mask.index_n(t[0], t[1], t[2])];
400 if (im_ni.found && im_ni.dist_sq > ni.dist_sq)
401 im_ni.found = false;
402 }
403 }
404}
405
406// TODO: rename this function to interpolate_grid_around_model()
407// would it be better to use src_model rather than dest_model?
408template<typename T>
410 const Transform& tr,
411 const Model& dest_model, double radius,
412 int order=2) {
413 Grid<NodeInfo> mask;
414 mask.copy_metadata_from(dest);
417 // Interpolate values for selected nodes.
418 FTransform frac_tr = src.unit_cell.frac.combine(tr.combine(dest.unit_cell.orth));
419 for (size_t idx = 0; idx != mask.data.size(); ++idx) {
420 const NodeInfo& ni = mask.data[idx];
421 if (ni.found) {
422 Fractional dest_fr = dest.get_fractional(ni.u, ni.v, ni.w);
424 dest.data[idx] = src.interpolate(src_fr, order);
425 }
426 }
427}
428
429
430// add soft edge to 1/0 mask using raised cosine function
431template<typename T>
432void add_soft_edge_to_mask(Grid<T>& grid, double width) {
433 const double width2 = width * width;
434 const int du = (int) std::ceil(width / grid.spacing[0]);
435 const int dv = (int) std::ceil(width / grid.spacing[1]);
436 const int dw = (int) std::ceil(width / grid.spacing[2]);
437
438 for (int w = 0; w < grid.nw; ++w)
439 for (int v = 0; v < grid.nv; ++v)
440 for (int u = 0; u < grid.nu; ++u) {
441 size_t idx = grid.index_q(u, v, w);
442 if (grid.data[idx] >= 1e-3) continue;
443 double min_d2 = width2 + 1;
444 Fractional fctr = grid.get_fractional(u, v, w);
445 grid.template use_points_in_box<true>(
446 fctr, du, dv, dw,
447 [&](T& point, double d2, const Position&, int, int, int) {
448 if (point > 0.999) {
449 if (d2 < min_d2)
450 min_d2 = d2;
451 }
452 });
453 if (min_d2 < width2)
454 grid.data[idx] = T(0.5 + 0.5 * std::cos(pi() * std::sqrt(min_d2) / width));
455 }
456}
457
458} // namespace gemmi
459#endif
void interpolate_grid(Grid< T > &dest, const Grid< T > &src, const Transform &tr, int order=2)
Definition solmask.hpp:336
float vdw_radius(El el)
Definition elem.hpp:154
float cctbx_vdw_radius(El el)
Definition solmask.hpp:17
void mask_points_in_varied_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:122
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:389
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)
Definition solmask.hpp:147
void fail(const std::string &msg)
Definition fail.hpp:59
void add_soft_edge_to_mask(Grid< T > &grid, double width)
Definition solmask.hpp:432
float refmac_radius_for_bulk_solvent(El el)
Definition solmask.hpp:57
void interpolate_grid_of_aligned_model2(Grid< T > &dest, const Grid< T > &src, const Transform &tr, const Model &dest_model, double radius, int order=2)
Definition solmask.hpp:409
void mask_with_node_info(Grid< NodeInfo > &mask, const Model &model, double radius)
Populate NodeInfo grid for nodes near the model.
Definition solmask.hpp:356
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:107
Represents atom site in macromolecular structure (~100 bytes).
Definition model.hpp:112
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:303
std::vector< Chain > chains
Definition model.hpp:700
Coordinates in Angstroms - orthogonal (Cartesian) coordinates.
Definition unitcell.hpp:32
void invert(Grid< T > &grid) const
Definition solmask.hpp:273
SolventMasker(AtomicRadiiSet choice, double constant_r_=0.)
Definition solmask.hpp:217
int remove_islands(Grid< T > &grid) const
Definition solmask.hpp:281
void shrink(Grid< T > &grid) const
Definition solmask.hpp:266
void set_to_zero(Grid< float > &grid, const Model &model) const
Definition solmask.hpp:308
void put_mask_on_grid(Grid< T > &grid, const Model &model) const
Definition solmask.hpp:299
AtomicRadiiSet atomic_radii_set
Definition solmask.hpp:209
void set_radii(AtomicRadiiSet choice, double constant_r_=0.)
Definition solmask.hpp:222
void symmetrize(Grid< T > &grid) const
Definition solmask.hpp:262
bool ignore_zero_occupancy_atoms
Definition solmask.hpp:211
void clear(Grid< T > &grid) const
Definition solmask.hpp:251
void mask_points(Grid< T > &grid, const Model &model) const
Definition solmask.hpp:253
Transform combine(const Transform &b) const
Definition math.hpp:382