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 // helper fields used in Topo::find_polymer_link()
101 int atom1_name_id = 0;
102 int atom2_name_id = 0;
103
104 // aliasing1/2 points to vector element in ChemComp::aliases.
105 // The pointers should stay valid even if a ChemComp is moved.
106 const ChemComp::Aliasing* aliasing1 = nullptr;
107 const ChemComp::Aliasing* aliasing2 = nullptr;
108
109 // only for polymer links, res1 and res2 must be in the same vector (Chain)
110 std::ptrdiff_t res_distance() const { return res1 - res2; }
111 };
112
113 struct Mod {
114 std::string id; // id of ChemMod from the dictionary (MonLib)
115 ChemComp::Group alias; // alias to be used when applying the modification
116 char altloc; // \0 = all conformers
117
118 bool operator==(const Mod& o) const {
119 return id == o.id && alias == o.alias && altloc == o.altloc;
120 }
121 };
122
124 char altloc; // Restraints apply to this conformer
125 const ChemComp* cc;
126 };
127
128 struct ResInfo {
130 // in case of microheterogeneity we may have 2+ previous residues
131 std::vector<Link> prev;
132 std::vector<Mod> mods;
133 // Pointer to ChemComp in MonLib::monomers.
134 const ChemComp* orig_chemcomp = nullptr;
135 // Pointer to restraints with modifications applied (if any).
136 std::vector<FinalChemComp> chemcomps;
137 std::vector<Rule> monomer_rules;
138
139 ResInfo(Residue* r) : res(r) {}
140 void add_mod(const std::string& m, const ChemComp::Aliasing* aliasing, char altloc) {
141 if (!m.empty()) {
142 auto alias_group = aliasing ? aliasing->group : ChemComp::Group::Null;
143 Mod mod{m, alias_group, altloc};
144 if (!in_vector(mod, mods))
145 mods.push_back(mod);
146 }
147 }
148
149 const ChemComp& get_final_chemcomp(char altloc) const {
150 if (chemcomps.size() == 1)
151 return *chemcomps[0].cc;
152 assert(!chemcomps.empty());
153 for (const FinalChemComp& it : chemcomps)
154 if (it.altloc == altloc)
155 return *it.cc;
156 return *chemcomps[0].cc;
157 }
158 };
159
160 // corresponds to a sub-chain
161 struct ChainInfo {
163 std::string subchain_name;
164 std::string entity_id;
167 std::vector<ResInfo> res_infos;
168
169 ChainInfo(ResidueSpan& subchain, const Chain& chain, const Entity* ent);
170 using iterator = std::vector<ResInfo>::iterator;
172 auto e = b + 1;
173 while (e != res_infos.end() && e->res->group_key() == b->res->group_key())
174 ++e;
175 return e;
176 }
177 };
178
179 template<typename T>
180 static int has_atom(const Atom* a, const T& t) {
181 for (int i = 0; (size_t) i != t.atoms.size(); ++i)
182 if (t.atoms[i] == a)
183 return i;
184 return -1;
185 }
186
187 std::ostream* warnings = nullptr;
188 bool only_bonds = false; // an internal flag for apply_restraints()
189 std::vector<ChainInfo> chain_infos;
190 std::vector<Link> extras;
191
192 // Restraints applied to Model
193 std::vector<Bond> bonds;
194 std::vector<Angle> angles;
195 std::vector<Torsion> torsions;
196 std::vector<Chirality> chirs;
197 std::vector<Plane> planes;
198
199 std::multimap<const Atom*, Bond*> bond_index; // indexes both atoms
200 std::multimap<const Atom*, Angle*> angle_index; // only middle atom
201 std::multimap<const Atom*, Torsion*> torsion_index; // two middle atoms
202 std::multimap<const Atom*, Plane*> plane_index; // all atoms
203
205 for (ChainInfo& ci : chain_infos)
206 for (ResInfo& ri : ci.res_infos)
207 if (ri.res == res)
208 return &ri;
209 return nullptr;
210 }
211
213 for (const Rule& rule : link.link_rules)
214 if (rule.rkind == RKind::Bond)
215 return &bonds[rule.index];
216 return nullptr;
217 }
218
219 const Restraints::Bond* take_bond(const Atom* a, const Atom* b) const {
220 auto range = bond_index.equal_range(a);
221 for (auto i = range.first; i != range.second; ++i) {
222 const Bond* bond = i->second;
223 if ((bond->atoms[0] == b && bond->atoms[1] == a) ||
224 (bond->atoms[1] == b && bond->atoms[0] == a))
225 return bond->restr;
226 }
227 return nullptr;
228 }
229
231 const Atom* b,
232 const Atom* c) const {
233 auto range = angle_index.equal_range(b);
234 for (auto i = range.first; i != range.second; ++i) {
235 const Angle* ang = i->second;
236 if ((ang->atoms[0] == a && ang->atoms[2] == c) ||
237 (ang->atoms[0] == c && ang->atoms[2] == a))
238 return ang->restr;
239 }
240 return nullptr;
241 }
242
243 const Chirality* get_chirality(const Atom* ctr) const {
244 for (const Chirality& chir : chirs)
245 if (chir.atoms[0] == ctr)
246 return &chir;
247 return nullptr;
248 }
249
251
252 std::vector<Rule> apply_restraints(const Restraints& rt,
253 Residue& res, Residue* res2, Asu asu,
254 char altloc1, char altloc2, bool require_alt);
256
257 // Structure is non-const b/c connections may have link_id assigned.
258 // Model is non-const b/c we store non-const pointers to residues in Topo.
259 // Because of the pointers, don't add or remove residues after this step.
260 // Monlib may get modified by addition of extra links from the model.
262 MonLib& monlib, bool ignore_unknown_links=false);
263
264 // This step stores pointers to gemmi::Atom's from model0,
265 // so after this step don't add or remove atoms.
266 // monlib is needed only for links.
268
269 // prepare bond_index, angle_index, torsion_index, plane_index
271
272 // Searches for matching Link in ResInfo::prev lists.
274
276
277 GEMMI_COLD void err(const std::string& msg) const {
278 if (warnings == nullptr)
279 fail(msg);
280 *warnings << "Warning: " << msg << std::endl;
281 }
282
283private:
284 // storage for link restraints modified by aliases
285 std::vector<std::unique_ptr<Restraints>> rt_storage;
286 // cache for ChemComps after applying modifications
287 std::unordered_map<std::string, std::unique_ptr<ChemComp>> cc_cache;
288 // storage for ad-hoc ChemComps (placeholders for those missing in MonLib)
289 std::vector<std::unique_ptr<ChemComp>> cc_storage;
290
291 void setup_connection(Connection& conn, Model& model0, MonLib& monlib,
293};
294
295GEMMI_DLL std::unique_ptr<Topo>
298 std::ostream* warnings=nullptr, bool ignore_unknown_links=false,
299 bool use_cispeps=false);
300
301
302GEMMI_DLL std::unique_ptr<ChemComp> make_chemcomp_with_restraints(const Residue& res);
303
304GEMMI_DLL std::vector<AtomAddress> find_missing_atoms(const Topo& topo,
305 bool including_hydrogen=false);
306
307} // namespace gemmi
308#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:110
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:164
iterator group_end(iterator b) const
Definition topo.hpp:171
PolymerType polymer_type
Definition topo.hpp:166
std::vector< ResInfo >::iterator iterator
Definition topo.hpp:170
std::string subchain_name
Definition topo.hpp:163
std::vector< ResInfo > res_infos
Definition topo.hpp:167
const Chain & chain_ref
Definition topo.hpp:162
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:125
bool operator==(const Mod &o) const
Definition topo.hpp:118
std::string id
Definition topo.hpp:114
ChemComp::Group alias
Definition topo.hpp:115
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:140
std::vector< Rule > monomer_rules
Definition topo.hpp:137
std::vector< Link > prev
Definition topo.hpp:131
std::vector< FinalChemComp > chemcomps
Definition topo.hpp:136
std::vector< Mod > mods
Definition topo.hpp:132
ResInfo(Residue *r)
Definition topo.hpp:139
const ChemComp & get_final_chemcomp(char altloc) const
Definition topo.hpp:149
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)
const Restraints::Angle * take_angle(const Atom *a, const Atom *b, const Atom *c) const
Definition topo.hpp:230
void initialize_refmac_topology(Structure &st, Model &model0, MonLib &monlib, bool ignore_unknown_links=false)
std::vector< Plane > planes
Definition topo.hpp:197
std::vector< ChainInfo > chain_infos
Definition topo.hpp:189
std::vector< Angle > angles
Definition topo.hpp:194
static int has_atom(const Atom *a, const T &t)
Definition topo.hpp:180
void apply_restraints_from_link(Link &link, const MonLib &monlib)
Topo(Topo const &)=delete
std::multimap< const Atom *, Bond * > bond_index
Definition topo.hpp:199
void set_cispeps_in_structure(Structure &st)
std::multimap< const Atom *, Angle * > angle_index
Definition topo.hpp:200
Bond * first_bond_in_link(const Link &link)
Definition topo.hpp:212
double ideal_chiral_abs_volume(const Chirality &ch) const
const Restraints::Bond * take_bond(const Atom *a, const Atom *b) const
Definition topo.hpp:219
std::vector< Chirality > chirs
Definition topo.hpp:196
std::vector< Bond > bonds
Definition topo.hpp:193
std::vector< Torsion > torsions
Definition topo.hpp:195
GEMMI_COLD void err(const std::string &msg) const
Definition topo.hpp:277
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:201
ResInfo * find_resinfo(const Residue *res)
Definition topo.hpp:204
const Chirality * get_chirality(const Atom *ctr) const
Definition topo.hpp:243
std::vector< Link > extras
Definition topo.hpp:190
std::multimap< const Atom *, Plane * > plane_index
Definition topo.hpp:202