Gemmi C++ API
Loading...
Searching...
No Matches
contact.hpp
Go to the documentation of this file.
1// Copyright 2020 Global Phasing Ltd.
2//
3// Contact search, based on NeighborSearch from neighbor.hpp.
4
5#ifndef GEMMI_CONTACT_HPP_
6#define GEMMI_CONTACT_HPP_
7
8#include "model.hpp"
9#include "neighbor.hpp"
10#include "polyheur.hpp" // for check_polymer_type, are_connected
11
12namespace gemmi {
13
18 // parameters used to configure the search
21 bool twice = false; // report both A-B and B-A
22 float min_occupancy = 0.f;
23 double special_pos_cutoff_sq = 0.8 * 0.8;
24 std::vector<float> radii;
25
27
28 // a helper function that sets per-atom radii basing on covalent_radius()
30 radii.resize((size_t)El::END);
31 for (int i = 0; i != (int) El::END; ++i)
32 radii[i] = float(multiplier * Element(i).covalent_r() + tolerance / 2);
33 }
34 float get_radius(El el) const { return radii.empty() ? 0.f : radii[(int)el]; }
35 void set_radius(El el, float r) {
36 if (!radii.empty())
37 radii[(int)el] = r;
38 }
39
40 template<typename Func>
41 void for_each_contact(NeighborSearch& ns, const Func& func);
42
43 struct Result {
46 double dist_sq;
47 };
48 std::vector<Result> find_contacts(NeighborSearch& ns) {
49 std::vector<Result> out;
50 for_each_contact(ns, [&out](const CRA& cra1, const CRA& cra2,
51 int image_idx, double dist_sq) {
52 out.push_back({cra1, cra2, image_idx, dist_sq});
53 });
54 return out;
55 }
56};
57
58template<typename Func>
60 if (!ns.model)
61 fail(ns.small_structure ? "ContactSearch does not work with SmallStructure"
62 : "NeighborSearch not initialized");
63 for (int n_ch = 0; n_ch != (int) ns.model->chains.size(); ++n_ch) {
64 Chain& chain = ns.model->chains[n_ch];
68 for (int n_res = 0; n_res != (int) chain.residues.size(); ++n_res) {
69 Residue& res = chain.residues[n_res];
70 for (int n_atom = 0; n_atom != (int) res.atoms.size(); ++n_atom) {
71 Atom& atom = res.atoms[n_atom];
72 if (!ns.include_h && is_hydrogen(atom.element))
73 continue;
74 if (atom.occ < min_occupancy)
75 continue;
76 ns.for_each(atom.pos, atom.altloc, search_radius,
77 [&](NeighborSearch::Mark& m, double dist_sq) {
78 // do not consider connections inside a residue
79 if (ignore != Ignore::Nothing && m.image_idx == 0 &&
80 m.chain_idx == n_ch && m.residue_idx == n_res)
81 return;
82 switch (ignore) {
83 case Ignore::Nothing:
84 break;
86 if (m.image_idx == 0 && m.chain_idx == n_ch)
87 if (m.residue_idx == n_res)
88 return;
89 break;
91 if (m.image_idx == 0 && m.chain_idx == n_ch)
92 if (m.residue_idx == n_res ||
93 are_connected(res, chain.residues[m.residue_idx], pt) ||
94 are_connected(chain.residues[m.residue_idx], res, pt))
95 return;
96 break;
98 if (m.image_idx == 0 && m.chain_idx == n_ch)
99 return;
100 break;
101 case Ignore::SameAsu:
102 if (m.image_idx == 0)
103 return;
104 break;
105 }
106 // additionally, we may have per-element distances
107 if (!radii.empty()) {
108 double d = radii[atom.element.ordinal()] + radii[m.element.ordinal()];
109 if (d < 0 || dist_sq > d * d)
110 return;
111 }
112 // avoid reporting connections twice (A-B and B-A)
113 if (!twice)
114 if (m.chain_idx < n_ch || (m.chain_idx == n_ch &&
115 (m.residue_idx < n_res || (m.residue_idx == n_res &&
116 m.atom_idx < n_atom))))
117 return;
118 // atom can be linked with its image, but if the image
119 // is too close the atom is likely on special position.
120 if (m.chain_idx == n_ch && m.residue_idx == n_res &&
121 m.atom_idx == n_atom && dist_sq < special_pos_cutoff_sq)
122 return;
123 CRA cra2 = m.to_cra(*ns.model);
124 // ignore atoms with occupancy below the specified value
125 if (cra2.atom->occ < min_occupancy)
126 return;
127 func(CRA{&chain, &res, &atom}, cra2, m.image_idx, dist_sq);
128 });
129 }
130 }
131 }
132}
133
134} // namespace gemmi
135#endif
bool are_connected(const Residue &r1, const Residue &r2, PolymerType ptype)
check C-N or O3'-P distance
Definition polyheur.hpp:56
bool is_hydrogen(El el)
Definition elem.hpp:26
GEMMI_DLL PolymerType check_polymer_type(const ConstResidueSpan &span, bool ignore_entity_type=false)
void fail(const std::string &msg)
Definition fail.hpp:59
Represents atom site in macromolecular structure (~100 bytes).
Definition model.hpp:112
char altloc
Definition model.hpp:115
Element element
Definition model.hpp:117
float occ
Definition model.hpp:124
Position pos
Definition model.hpp:123
Atom * atom
Definition model.hpp:606
ResidueSpan get_polymer()
Definition model.hpp:485
std::vector< Residue > residues
Definition model.hpp:465
void setup_atomic_radii(double multiplier, double tolerance)
Definition contact.hpp:29
double special_pos_cutoff_sq
Definition contact.hpp:23
std::vector< float > radii
Definition contact.hpp:24
void set_radius(El el, float r)
Definition contact.hpp:35
ContactSearch(double radius) noexcept
Definition contact.hpp:26
std::vector< Result > find_contacts(NeighborSearch &ns)
Definition contact.hpp:48
float get_radius(El el) const
Definition contact.hpp:34
void for_each_contact(NeighborSearch &ns, const Func &func)
Definition contact.hpp:59
float covalent_r() const
Definition elem.hpp:305
int ordinal() const
Definition elem.hpp:301
std::vector< Atom > atoms
Definition model.hpp:188