Gemmi C++ API
Loading...
Searching...
No Matches
bond_idx.hpp
Go to the documentation of this file.
1// Copyright 2018 Global Phasing Ltd.
2//
3// BondIndex: for checking which atoms are bonded, calculating graph distance.
4
5#ifndef GEMMI_BOND_IDX_HPP_
6#define GEMMI_BOND_IDX_HPP_
7
8#include <map>
9#include "model.hpp" // for Residue, Atom
10#include "monlib.hpp" // for MonLib
11
12namespace gemmi {
13
14struct BondIndex {
15 const Model& model;
16
17 struct AtomImage {
20 bool operator==(const AtomImage& o) const {
21 return atom_serial == o.atom_serial && same_image == o.same_image;
22 }
23 };
24 std::map<int, std::vector<AtomImage>> index;
25
27 for (const_CRA cra : model.all())
28 if (!index.emplace(cra.atom->serial, std::vector<AtomImage>()).second)
29 fail("duplicated serial numbers");
30 }
31
32 void add_oneway_link(const Atom& a, const Atom& b, bool same_image) {
33 std::vector<AtomImage>& list_a = index.at(a.serial);
34 AtomImage ai{b.serial, same_image};
35 if (!in_vector(ai, list_a))
36 list_a.push_back(ai);
37 }
38
39 void add_link(const Atom& a, const Atom& b, bool same_image) {
40 add_oneway_link(a, b, same_image);
41 add_oneway_link(b, a, same_image);
42 }
43
44 // add_monomer_bonds() is not aware of modifications associated with links.
45 // Modifications that add bonds are rare, but to be more correct, use bonds
46 // from topology (Topo::bonds).
48 for (const Chain& chain : model.chains)
49 for (const Residue& res : chain.residues) {
50 std::string altlocs;
51 add_distinct_altlocs(res, altlocs);
52 if (altlocs.empty())
53 altlocs += '*';
54 auto monomer = monlib.monomers.find(res.name);
55 if (monomer == monlib.monomers.end())
56 fail("Monomer description not found: " + res.name);
57 for (const Restraints::Bond& bond : monomer->second.rt.bonds)
58 for (char alt : altlocs)
59 if (const Atom* at1 = res.find_atom(bond.id1.atom, alt))
60 if (const Atom* at2 = res.find_atom(bond.id2.atom, alt)) {
61 add_link(*at1, *at2, true);
62 if (!at1->altloc && !at2->altloc)
63 break;
64 }
65 }
66 }
67
68 bool are_linked(const Atom& a, const Atom& b, bool same_image) const {
69 return in_vector({b.serial, same_image}, index.at(a.serial));
70 }
71
72 int graph_distance(const Atom& a, const Atom& b, bool same_image,
73 int max_distance=4) const {
74 std::vector<AtomImage> neighbors(1, {a.serial, true});
75 for (int distance = 1; distance <= max_distance; ++distance) {
76 for (size_t n = neighbors.size(); n--; ) {
77 for (AtomImage ai : index.at(neighbors[n].atom_serial)) {
78 if (!neighbors[n].same_image)
79 ai.same_image = !ai.same_image;
80 if (ai.atom_serial == b.serial && ai.same_image == same_image)
81 return distance;
82 if (!in_vector(ai, neighbors))
83 neighbors.push_back(ai);
84 }
85 }
86 }
87 return max_distance + 1;
88 }
89};
90
91} // namespace gemmi
92#endif
void add_distinct_altlocs(const Residue &res, std::string &altlocs)
Definition monlib.hpp:23
bool in_vector(const T &x, const std::vector< T > &v)
Definition util.hpp:241
void fail(const std::string &msg)
Definition fail.hpp:59
Represents atom site in macromolecular structure (~100 bytes).
Definition model.hpp:112
bool operator==(const AtomImage &o) const
Definition bond_idx.hpp:20
std::map< int, std::vector< AtomImage > > index
Definition bond_idx.hpp:24
void add_link(const Atom &a, const Atom &b, bool same_image)
Definition bond_idx.hpp:39
const Model & model
Definition bond_idx.hpp:15
bool are_linked(const Atom &a, const Atom &b, bool same_image) const
Definition bond_idx.hpp:68
void add_oneway_link(const Atom &a, const Atom &b, bool same_image)
Definition bond_idx.hpp:32
void add_monomer_bonds(MonLib &monlib)
Definition bond_idx.hpp:47
int graph_distance(const Atom &a, const Atom &b, bool same_image, int max_distance=4) const
Definition bond_idx.hpp:72
BondIndex(const Model &model_)
Definition bond_idx.hpp:26