Gemmi C++ API
Loading...
Searching...
No Matches
topo.hpp
Go to the documentation of this file.
1// Copyright 2018 Global Phasing Ltd.
2//
3// Topo(logy) - restraints (from a monomer library) applied to a model.
4
5#ifndef GEMMI_TOPO_HPP_
6#define GEMMI_TOPO_HPP_
7
8#include <map> // for multimap
9#include <ostream> // for ostream
10#include <memory> // for unique_ptr
11#include <unordered_map> // for unordered_map
12#include "chemcomp.hpp" // for ChemComp
13#include "monlib.hpp" // for MonLib
14#include "model.hpp" // for Residue, Atom
15#include "calculate.hpp" // for calculate_angle, calculate_dihedral
16
17namespace gemmi {
18
22
24 // We have internal pointers in this class (pointers setup in
25 // apply_restraints() that point to ResInfo::chemcomp.rt),
26 // disable copying this class.
27 Topo() = default;
28 Topo(Topo const&) = delete;
29 Topo& operator=(Topo const&) = delete;
30
31 struct Bond {
33 std::array<Atom*, 2> atoms;
35 double calculate() const {
36 return asu != Asu::Different ? atoms[0]->pos.dist(atoms[1]->pos) : NAN;
37 }
38 double calculate_z_(double d) const { return std::abs(d - restr->value) / restr->esd; }
39 double calculate_z() const { return calculate_z_(calculate()); }
40 };
41 struct Angle {
43 std::array<Atom*, 3> atoms;
44 double calculate() const {
45 return calculate_angle(atoms[0]->pos, atoms[1]->pos, atoms[2]->pos);
46 }
47 double calculate_z() const { return angle_z(calculate(), *restr); }
48 };
49 struct Torsion {
51 std::array<Atom*, 4> atoms;
52 double calculate() const {
53 return calculate_dihedral(atoms[0]->pos, atoms[1]->pos,
54 atoms[2]->pos, atoms[3]->pos);
55 }
56 double calculate_z() const {
57 return angle_z(calculate(), *restr, 360. / std::max(1, restr->period));
58 }
59 };
60 struct Chirality {
62 std::array<Atom*, 4> atoms;
63 double calculate() const {
64 return calculate_chiral_volume(atoms[0]->pos, atoms[1]->pos,
65 atoms[2]->pos, atoms[3]->pos);
66 }
67 double calculate_z(double ideal_abs_vol, double esd) const {
68 double calc = calculate();
69 if (restr->sign == ChiralityType::Negative ||
70 (restr->sign == ChiralityType::Both && calc < 0))
71 ideal_abs_vol *= -1;
72 return std::abs(calc - ideal_abs_vol) / esd;
73 }
74 bool check() const { return !restr->is_wrong(calculate()); }
75 };
76 struct Plane {
78 std::vector<Atom*> atoms;
79 bool has(const Atom* atom) const {
80 return in_vector(const_cast<Atom*>(atom), atoms);
81 }
82 };
83
84 enum class RKind { Bond, Angle, Torsion, Chirality, Plane };
85 struct Rule {
87 size_t index; // index in the respective vector (bonds, ...) in Topo
88 };
89
90 struct Link {
91 std::string link_id;
92 Residue* res1 = nullptr;
93 Residue* res2 = nullptr;
94 std::vector<Rule> link_rules;
95 char alt1 = '\0';
96 char alt2 = '\0';
97 Asu asu = Asu::Any; // used only in Links in ChainInfo::extras
98 bool is_cis = false; // helper field for CISPEP record generation
99
100 // aliasing1/2 points to vector element in ChemComp::aliases.
101 // The pointers should stay valid even if a ChemComp is moved.
102 const ChemComp::Aliasing* aliasing1 = nullptr;
103 const ChemComp::Aliasing* aliasing2 = nullptr;
104
105 // only for polymer links, res1 and res2 must be in the same vector (Chain)
106 std::ptrdiff_t res_distance() const { return res1 - res2; }
107 };
108
109 struct Mod {
110 std::string id; // id of ChemMod from the dictionary (MonLib)
111 ChemComp::Group alias; // alias to be used when applying the modification
112 char altloc; // \0 = all conformers
113
114 bool operator==(const Mod& o) const {
115 return id == o.id && alias == o.alias && altloc == o.altloc;
116 }
117 };
118
120 char altloc; // Restraints apply to this conformer
121 const ChemComp* cc;
122 };
123
124 struct ResInfo {
126 // in case of microheterogeneity we may have 2+ previous residues
127 std::vector<Link> prev;
128 std::vector<Mod> mods;
129 // Pointer to ChemComp in MonLib::monomers.
130 const ChemComp* orig_chemcomp = nullptr;
131 // Pointer to restraints with modifications applied (if any).
132 std::vector<FinalChemComp> chemcomps;
133 std::vector<Rule> monomer_rules;
134
135 ResInfo(Residue* r) : res(r) {}
136 void add_mod(const std::string& m, const ChemComp::Aliasing* aliasing, char altloc) {
137 if (!m.empty()) {
138 auto alias_group = aliasing ? aliasing->group : ChemComp::Group::Null;
139 Mod mod{m, alias_group, altloc};
140 if (!in_vector(mod, mods))
141 mods.push_back(mod);
142 }
143 }
144
145 const ChemComp& get_final_chemcomp(char altloc) const {
146 if (chemcomps.size() == 1)
147 return *chemcomps[0].cc;
148 assert(!chemcomps.empty());
149 for (const FinalChemComp& it : chemcomps)
150 if (it.altloc == altloc)
151 return *it.cc;
152 return *chemcomps[0].cc;
153 }
154 };
155
156 // corresponds to a sub-chain
157 struct ChainInfo {
159 std::string subchain_name;
160 std::string entity_id;
163 std::vector<ResInfo> res_infos;
164
165 ChainInfo(ResidueSpan& subchain, const Chain& chain, const Entity* ent);
166 using iterator = std::vector<ResInfo>::iterator;
168 auto e = b + 1;
169 while (e != res_infos.end() && e->res->group_key() == b->res->group_key())
170 ++e;
171 return e;
172 }
173 };
174
175 template<typename T>
176 static int has_atom(const Atom* a, const T& t) {
177 for (int i = 0; (size_t) i != t.atoms.size(); ++i)
178 if (t.atoms[i] == a)
179 return i;
180 return -1;
181 }
182
183 std::ostream* warnings = nullptr;
184 bool only_bonds = false; // an internal flag for apply_restraints()
185 std::vector<ChainInfo> chain_infos;
186 std::vector<Link> extras;
187
188 // Restraints applied to Model
189 std::vector<Bond> bonds;
190 std::vector<Angle> angles;
191 std::vector<Torsion> torsions;
192 std::vector<Chirality> chirs;
193 std::vector<Plane> planes;
194
195 std::multimap<const Atom*, Bond*> bond_index; // indexes both atoms
196 std::multimap<const Atom*, Angle*> angle_index; // only middle atom
197 std::multimap<const Atom*, Torsion*> torsion_index; // two middle atoms
198 std::multimap<const Atom*, Plane*> plane_index; // all atoms
199
201 for (ChainInfo& ci : chain_infos)
202 for (ResInfo& ri : ci.res_infos)
203 if (ri.res == res)
204 return &ri;
205 return nullptr;
206 }
207
209 for (const Rule& rule : link.link_rules)
210 if (rule.rkind == RKind::Bond)
211 return &bonds[rule.index];
212 return nullptr;
213 }
214
215 const Restraints::Bond* take_bond(const Atom* a, const Atom* b) const {
216 auto range = bond_index.equal_range(a);
217 for (auto i = range.first; i != range.second; ++i) {
218 const Bond* bond = i->second;
219 if ((bond->atoms[0] == b && bond->atoms[1] == a) ||
220 (bond->atoms[1] == b && bond->atoms[0] == a))
221 return bond->restr;
222 }
223 return nullptr;
224 }
225
227 const Atom* b,
228 const Atom* c) const {
229 auto range = angle_index.equal_range(b);
230 for (auto i = range.first; i != range.second; ++i) {
231 const Angle* ang = i->second;
232 if ((ang->atoms[0] == a && ang->atoms[2] == c) ||
233 (ang->atoms[0] == c && ang->atoms[2] == a))
234 return ang->restr;
235 }
236 return nullptr;
237 }
238
239 const Chirality* get_chirality(const Atom* ctr) const {
240 for (const Chirality& chir : chirs)
241 if (chir.atoms[0] == ctr)
242 return &chir;
243 return nullptr;
244 }
245
247
248 std::vector<Rule> apply_restraints(const Restraints& rt,
249 Residue& res, Residue* res2, Asu asu,
250 char altloc1, char altloc2, bool require_alt);
252
253 // Structure is non-const b/c connections may have link_id assigned.
254 // Model is non-const b/c we store non-const pointers to residues in Topo.
255 // Because of the pointers, don't add or remove residues after this step.
256 // Monlib may get modified by addition of extra links from the model.
258 MonLib& monlib, bool ignore_unknown_links=false);
259
260 // This step stores pointers to gemmi::Atom's from model0,
261 // so after this step don't add or remove atoms.
262 // monlib is needed only for links.
264
265 // prepare bond_index, angle_index, torsion_index, plane_index
267
269 for (ChainInfo& ci : chain_infos)
270 if (a1.chain_name == ci.chain_ref.name && a2.chain_name == ci.chain_ref.name) {
271 for (ResInfo& ri : ci.res_infos)
272 for (Link& link : ri.prev) {
273 assert(link.res1 && link.res2);
274 if ((a1.res_id.matches_noseg(*link.res1) &&
275 a2.res_id.matches_noseg(*link.res2) &&
276 a1.altloc == link.alt1 && a2.altloc == link.alt2) ||
277 (a2.res_id.matches_noseg(*link.res1) &&
278 a1.res_id.matches_noseg(*link.res2) &&
279 a1.altloc == link.alt2 && a2.altloc == link.alt1))
280 return &link;
281 }
282 }
283 return nullptr;
284 }
285
287
288 GEMMI_COLD void err(const std::string& msg) const {
289 if (warnings == nullptr)
290 fail(msg);
291 *warnings << "Warning: " << msg << std::endl;
292 }
293
294private:
295 // storage for link restraints modified by aliases
296 std::vector<std::unique_ptr<Restraints>> rt_storage;
297 // cache for ChemComps after applying modifications
298 std::unordered_map<std::string, std::unique_ptr<ChemComp>> cc_cache;
299 // storage for ad-hoc ChemComps (placeholders for those missing in MonLib)
300 std::vector<std::unique_ptr<ChemComp>> cc_storage;
301
302 void setup_connection(Connection& conn, Model& model0, MonLib& monlib,
304};
305
306GEMMI_DLL std::unique_ptr<Topo>
309 std::ostream* warnings=nullptr, bool ignore_unknown_links=false,
310 bool use_cispeps=false);
311
312
313GEMMI_DLL std::unique_ptr<ChemComp> make_chemcomp_with_restraints(const Residue& res);
314
315GEMMI_DLL std::vector<AtomAddress> find_missing_atoms(const Topo& topo,
316 bool including_hydrogen=false);
317
318} // namespace gemmi
319#endif
#define GEMMI_DLL
Definition fail.hpp:53
#define GEMMI_COLD
Definition fail.hpp:28
double calculate_chiral_volume(const Position &actr, const Position &a1, const Position &a2, const Position &a3)
GEMMI_DLL std::unique_ptr< Topo > prepare_topology(Structure &st, MonLib &monlib, size_t model_index, HydrogenChange h_change, bool reorder, std::ostream *warnings=nullptr, bool ignore_unknown_links=false, bool use_cispeps=false)
double calculate_dihedral(const Position &p0, const Position &p1, const Position &p2, const Position &p3)
GEMMI_DLL std::vector< AtomAddress > find_missing_atoms(const Topo &topo, bool including_hydrogen=false)
double calculate_angle(const Position &p0, const Position &p1, const Position &p2)
bool in_vector(const T &x, const std::vector< T > &v)
Definition util.hpp:241
double angle_z(double value_rad, const Restr &restr, double full=360.)
Definition chemcomp.hpp:300
void fail(const std::string &msg)
Definition fail.hpp:59
HydrogenChange
Definition topo.hpp:19
GEMMI_DLL std::unique_ptr< ChemComp > make_chemcomp_with_restraints(const Residue &res)
Represents atom site in macromolecular structure (~100 bytes).
Definition model.hpp:112
bool is_wrong(double volume) const
Definition chemcomp.hpp:122
const Restraints::Angle * restr
Definition topo.hpp:42
std::array< Atom *, 3 > atoms
Definition topo.hpp:43
double calculate_z() const
Definition topo.hpp:47
double calculate() const
Definition topo.hpp:44
double calculate() const
Definition topo.hpp:35
std::array< Atom *, 2 > atoms
Definition topo.hpp:33
double calculate_z() const
Definition topo.hpp:39
const Restraints::Bond * restr
Definition topo.hpp:32
std::string entity_id
Definition topo.hpp:160
iterator group_end(iterator b) const
Definition topo.hpp:167
PolymerType polymer_type
Definition topo.hpp:162
std::vector< ResInfo >::iterator iterator
Definition topo.hpp:166
std::string subchain_name
Definition topo.hpp:159
std::vector< ResInfo > res_infos
Definition topo.hpp:163
const Chain & chain_ref
Definition topo.hpp:158
ChainInfo(ResidueSpan &subchain, const Chain &chain, const Entity *ent)
double calculate() const
Definition topo.hpp:63
bool check() const
Definition topo.hpp:74
std::array< Atom *, 4 > atoms
Definition topo.hpp:62
double calculate_z(double ideal_abs_vol, double esd) const
Definition topo.hpp:67
const Restraints::Chirality * restr
Definition topo.hpp:61
const ChemComp * cc
Definition topo.hpp:121
bool operator==(const Mod &o) const
Definition topo.hpp:114
std::string id
Definition topo.hpp:110
ChemComp::Group alias
Definition topo.hpp:111
const Restraints::Plane * restr
Definition topo.hpp:77
bool has(const Atom *atom) const
Definition topo.hpp:79
std::vector< Atom * > atoms
Definition topo.hpp:78
void add_mod(const std::string &m, const ChemComp::Aliasing *aliasing, char altloc)
Definition topo.hpp:136
std::vector< Rule > monomer_rules
Definition topo.hpp:133
std::vector< Link > prev
Definition topo.hpp:127
std::vector< FinalChemComp > chemcomps
Definition topo.hpp:132
std::vector< Mod > mods
Definition topo.hpp:128
ResInfo(Residue *r)
Definition topo.hpp:135
const ChemComp & get_final_chemcomp(char altloc) const
Definition topo.hpp:145
std::array< Atom *, 4 > atoms
Definition topo.hpp:51
const Restraints::Torsion * restr
Definition topo.hpp:50
double calculate() const
Definition topo.hpp:52
double calculate_z() const
Definition topo.hpp:56
Topo & operator=(Topo const &)=delete
Topo()=default
void apply_all_restraints(const MonLib &monlib)
void create_indices()
Link * find_polymer_link(const AtomAddress &a1, const AtomAddress &a2)
Definition topo.hpp:268
const Restraints::Angle * take_angle(const Atom *a, const Atom *b, const Atom *c) const
Definition topo.hpp:226
void initialize_refmac_topology(Structure &st, Model &model0, MonLib &monlib, bool ignore_unknown_links=false)
std::vector< Plane > planes
Definition topo.hpp:193
std::vector< ChainInfo > chain_infos
Definition topo.hpp:185
std::vector< Angle > angles
Definition topo.hpp:190
static int has_atom(const Atom *a, const T &t)
Definition topo.hpp:176
void apply_restraints_from_link(Link &link, const MonLib &monlib)
Topo(Topo const &)=delete
std::multimap< const Atom *, Bond * > bond_index
Definition topo.hpp:195
void set_cispeps_in_structure(Structure &st)
std::multimap< const Atom *, Angle * > angle_index
Definition topo.hpp:196
Bond * first_bond_in_link(const Link &link)
Definition topo.hpp:208
double ideal_chiral_abs_volume(const Chirality &ch) const
const Restraints::Bond * take_bond(const Atom *a, const Atom *b) const
Definition topo.hpp:215
std::vector< Chirality > chirs
Definition topo.hpp:192
std::vector< Bond > bonds
Definition topo.hpp:189
std::vector< Torsion > torsions
Definition topo.hpp:191
GEMMI_COLD void err(const std::string &msg) const
Definition topo.hpp:288
std::vector< Rule > apply_restraints(const Restraints &rt, Residue &res, Residue *res2, Asu asu, char altloc1, char altloc2, bool require_alt)
std::multimap< const Atom *, Torsion * > torsion_index
Definition topo.hpp:197
ResInfo * find_resinfo(const Residue *res)
Definition topo.hpp:200
const Chirality * get_chirality(const Atom *ctr) const
Definition topo.hpp:239
std::vector< Link > extras
Definition topo.hpp:186
std::multimap< const Atom *, Plane * > plane_index
Definition topo.hpp:198