Gemmi C++ API
Loading...
Searching...
No Matches
model.hpp
Go to the documentation of this file.
1// Copyright 2017 Global Phasing Ltd.
2//
3// Data structures to keep macromolecular structure model.
4
5#ifndef GEMMI_MODEL_HPP_
6#define GEMMI_MODEL_HPP_
7
8#include <algorithm> // for find_if, count_if, lower_bound
9#include <array>
10#include <bitset>
11#include <iterator> // for back_inserter
12#include <map> // for map
13#include <stdexcept> // for out_of_range
14#include <string>
15#include <vector>
16#include <unordered_map>
17
18#include "elem.hpp"
19#include "fail.hpp" // for fail
20#include "unitcell.hpp"
21#include "symmetry.hpp"
22#include "metadata.hpp"
23#include "iterator.hpp"
24#include "span.hpp" // for Span, MutableVectorSpan
25#include "seqid.hpp"
26#include "util.hpp" // for join_str, vector_move_extend, in_vector
27
28namespace gemmi {
29
30namespace impl {
31
32template<typename T>
33T* find_or_null(std::vector<T>& vec, const std::string& name) {
34 auto it = std::find_if(vec.begin(), vec.end(),
35 [&name](const T& m) { return m.name == name; });
36 return it != vec.end() ? &*it : nullptr;
37}
38
39template<typename T>
40T& find_or_add(std::vector<T>& vec, const std::string& name) {
41 if (T* ret = find_or_null(vec, name))
42 return *ret;
43 vec.emplace_back(name);
44 return vec.back();
45}
46
47template<typename Span, typename T = typename Span::value_type>
48typename Span::iterator find_iter(Span& span, const std::string& name) {
49 auto i = std::find_if(span.begin(), span.end(),
50 [&](const T& x) { return x.name == name; });
51 if (i == span.end())
52 throw std::invalid_argument(
53 T::what() + (" " + name) + " not found (only [" +
54 join_str(span.begin(), span.end(), ' ',
55 [](const T& x) { return x.name; }) +
56 "])");
57 return i;
58}
59
60template<typename Group>
61typename Group::element_type& get_by_altloc(Group& group, char alt) {
62 for (auto& atom : group)
63 if (atom.altloc == alt)
64 return atom;
65 fail("No such altloc");
66}
67
68template<typename T, typename M> std::vector<T> model_subchains(M* model) {
69 std::vector<T> v;
70 for (auto& chain : model->chains)
71 vector_move_extend(v, chain.subchains());
72 return v;
73}
74} // namespace impl
75
76
81
83enum class CalcFlag : signed char {
84 // NoHydrogen is the same as NotSet; it's used internally to mark atoms
85 // which should not have riding hydrogens.
86 // NB: add_cif_atoms() relies on this order.
88};
89
91struct OldToNew { std::string old, new_; };
92
96 bool split_chain_on_ter = false;
97 bool skip_remarks = false;
98};
99// end of PdbReadOptions for mol.rst
100
101// remove empty residues from chain, empty chains from model, etc
102template<class T> void remove_empty_children(T& obj) {
103 using Item = typename T::child_type;
104 vector_remove_if(obj.children(), [](const Item& x) { return x.children().empty(); });
105}
106
107inline bool is_same_conformer(char altloc1, char altloc2) {
108 return altloc1 == '\0' || altloc2 == '\0' || altloc1 == altloc2;
109}
110
112struct Atom {
113 static const char* what() { return "Atom"; }
114 std::string name;
115 char altloc = '\0'; // 0 if not set
116 signed char charge = 0; // [-8, +8]
118 CalcFlag calc_flag = CalcFlag::NotSet; // mmCIF _atom_site.calc_flag
119 char flag = '\0'; // a custom flag
120 short tls_group_id = -1;
121 int serial = 0;
122 float fraction = 0.f; // custom value, one use is Refmac's ccp4_deuterium_fraction
124 float occ = 1.0f;
125 // ADP - in MX it's usual to give isotropic ADP as B and anisotropic as U
126 float b_iso = 20.0f; // arbitrary default value
127 SMat33<float> aniso = {0, 0, 0, 0, 0, 0};
128
129 char altloc_or(char null_char) const { return altloc ? altloc : null_char; }
130 bool same_conformer(const Atom& other) const {
131 return is_same_conformer(altloc, other.altloc);
132 }
133 bool altloc_matches(char request) const {
134 return request == '*' || altloc == '\0' || altloc == request;
135 }
136 // group_key() is used in UniqIter and similar tools
137 const std::string& group_key() const { return name; }
138 bool has_altloc() const { return altloc != '\0'; }
139 double b_eq() const { return u_to_b() / 3. * aniso.trace(); }
140 bool is_hydrogen() const { return gemmi::is_hydrogen(element); }
141
142 // Name as a string left-padded like in the PDB format:
143 // the first two characters make the element name.
144 std::string padded_name() const {
145 std::string s;
146 const char* el = element.uname();
147 if (el[1] == '\0' &&
148 (el[0] == alpha_up(name[0]) || (is_hydrogen() && alpha_up(name[0]) == 'H')) &&
149 name.size() < 4)
150 s += ' ';
151 s += name;
152 return s;
153 }
154
155 // a method present in Atom, Residue, ... Structure - used in templates
156 Atom empty_copy() const { return Atom(*this); }
157};
158
159template<typename AtomType>
160struct AtomGroup_ : ItemGroup<AtomType> {
161 using ItemGroup<AtomType>::ItemGroup;
162 std::string name() const { return !this->empty() ? this->front().name : ""; }
163 AtomType& by_altloc(char alt) {
164 for (int i = 0; i != this->extent(); ++i) {
165 AtomType* a = &this->front() + i;
166 if (a->altloc == alt && (a->name == this->front().name))
167 return *a;
168 }
169 fail("No such altloc");
170 }
171};
172
175
176struct Residue : public ResidueId {
178 static const char* what() { return "Residue"; }
179
180 std::string subchain; // mmCIF _atom_site.label_asym_id
181 std::string entity_id; // mmCIF _atom_site.label_entity_id
182 OptionalNum label_seq; // mmCIF _atom_site.label_seq_id
184 char het_flag = '\0'; // 'A' = ATOM, 'H' = HETATM, 0 = unspecified
185 char flag = '\0'; // custom flag
186 SiftsUnpResidue sifts_unp; // UniProt reference from SIFTS
187 short group_idx = 0; // ignore - internal variable
188 std::vector<Atom> atoms;
189
190 Residue() = default;
191 explicit Residue(const ResidueId& rid) noexcept : ResidueId(rid) {}
192
193 // copy all but atoms (children) - for use in templates
195 Residue res((ResidueId&)*this);
196 res.subchain = subchain;
197 res.label_seq = label_seq;
199 res.het_flag = het_flag;
200 res.flag = flag;
201 return res;
202 }
204 std::vector<Atom>& children() { return atoms; }
205 const std::vector<Atom>& children() const { return atoms; }
206
207 const Atom* find_by_element(El el) const {
208 for (const Atom& a : atoms)
209 if (a.element == el)
210 return &a;
211 return nullptr;
212 }
213
214 // default values accept anything
215 Atom* find_atom(const std::string& atom_name, char altloc, El el=El::X) {
216 for (Atom& a : atoms)
217 if (a.name == atom_name && a.altloc_matches(altloc) && (el == El::X || a.element == el))
218 return &a;
219 return nullptr;
220 }
221 const Atom* find_atom(const std::string& atom_name, char altloc, El el=El::X) const {
222 return const_cast<Residue*>(this)->find_atom(atom_name, altloc, el);
223 }
224
225 std::vector<Atom>::iterator find_atom_iter(const std::string& atom_name,
226 char altloc, El el=El::X) {
227 if (Atom* a = find_atom(atom_name, altloc, el))
228 return atoms.begin() + (a - atoms.data());
229 fail("Atom not found.");
230 }
231
232 AtomGroup get(const std::string& atom_name) {
233 for (Atom& atom : atoms)
234 if (atom.name == atom_name)
235 return AtomGroup(&atom, atoms.data() + atoms.size());
236 fail("No such atom: " + atom_name);
237 }
238
239 Atom& sole_atom(const std::string& atom_name) {
240 AtomGroup aa = get(atom_name);
241 if (aa.size() != 1)
242 fail("Multiple alternative atoms " + atom_name);
243 return aa.front();
244 }
245
246 // short-cuts to access peptide backbone atoms
247 const Atom* get_ca() const { return find_atom("CA", '*', El::C); }
248 const Atom* get_c() const { return find_atom("C", '*', El::C); }
249 const Atom* get_n() const { return find_atom("N", '*', El::N); }
250 // short-cuts to access nucleic acid atoms
251 const Atom* get_p() const { return find_atom("P", '*', El::P); }
252 const Atom* get_o3prim() const { return find_atom("O3'", '*', El::O); }
253
254 bool same_conformer(const Residue& other) const {
255 return atoms.empty() || other.atoms.empty() ||
256 atoms[0].same_conformer(other.atoms[0]) ||
257 other.find_atom(other.atoms[0].name, atoms[0].altloc) != nullptr;
258 }
259
263 bool is_water() const {
264 if (name.length() != 3)
265 return false;
266 int id = ialpha4_id(name.c_str());
267 return id == ialpha4_id("HOH") || id == ialpha4_id("DOD") ||
268 id == ialpha4_id("WAT") || id == ialpha4_id("H2O");
269 }
270
271 // Iterators that in case of multiple conformations (alt. locations)
272 // skip all but the first conformation.
275};
276
277struct ResidueGroup;
278struct ConstResidueGroup;
279
280struct ConstResidueSpan : Span<const Residue> {
282 using Parent::Span;
283 ConstResidueSpan(Parent&& span) : Parent(std::move(span)) {}
284
285 int length() const {
286 int length = (int) size();
287 for (int n = length - 1; n > 0; --n)
288 if ((begin() + n)->group_key() == (begin() + n - 1)->group_key())
289 --length;
290 return length;
291 }
292
293 // sign=-1 for min, sign=1 for max
294 SeqId::OptionalNum extreme_num(bool label, int sign) const {
296 for (const Residue& r : *this) {
297 if (auto num = label ? r.label_seq : r.seqid.num)
298 if (!result || sign * int(num) > sign * int(result))
299 result = num;
300 }
301 return result;
302 }
303
307
308 const std::string& subchain_id() const {
309 if (this->empty())
310 throw std::out_of_range("subchain_id(): empty span");
311 if (this->size() > 1 && this->front().subchain != this->back().subchain)
312 fail("subchain id varies in a residue span: ", this->front().subchain,
313 " vs ", this->back().subchain);
314 return this->begin()->subchain;
315 }
316
318
319 std::vector<std::string> extract_sequence() const {
320 std::vector<std::string> seq;
321 for (const Residue& res : first_conformer())
322 seq.push_back(res.name);
323 return seq;
324 }
325
326 // We assume residues are ordered. It works (approximately) also with
327 // missing numbers which can be present in DBREF.
329 if (size() == 0)
330 throw std::out_of_range("label_seq_id_to_auth(): empty span");
331 auto it = std::lower_bound(begin(), end(), label_seq_id,
332 [](const Residue& r, SeqId::OptionalNum v){ return r.label_seq < v; });
333 if (it == end())
334 --it;
335 else if (it->label_seq == label_seq_id)
336 return it->seqid;
337 else if (it != begin() &&
339 --it;
340 return {it->seqid.num + (label_seq_id - it->label_seq), ' '};
341 }
342 // The residue numbers (auth) are sometimes not ordered.
343 // That is why we use this multi-step heuristic.
345 if (size() == 0)
346 throw std::out_of_range("auth_seq_id_to_label(): empty span");
347 for (const Residue& r : *this)
348 if (r.seqid == auth_seq_id)
349 return r.label_seq;
351 if (auth_seq_id.num < front().seqid.num) {
352 it = begin();
353 } else if (back().seqid.num < auth_seq_id.num) {
354 it = end() - 1;
355 } else {
356 it = std::lower_bound(begin(), end(), auth_seq_id.num,
357 [](const Residue& r, SeqId::OptionalNum v){ return r.seqid.num < v; });
358 while (it != end() && it->seqid.num == auth_seq_id.num &&
359 it->seqid.icode != auth_seq_id.icode)
360 ++it;
361 if (it == end())
362 --it;
363 }
364 return it->label_seq + (auth_seq_id.num - it->seqid.num);
365 }
366};
367
368// ResidueSpan represents consecutive residues within the same chain.
369// It's used as return value of get_polymer(), get_ligands(), get_waters()
370// and get_subchain().
373 struct GroupingProxy;
374 ResidueSpan() = default;
375 ResidueSpan(Parent&& span) : Parent(std::move(span)) {}
377 : Parent(v, begin, n) {}
378 int length() const { return const_().length(); }
379 SeqId::OptionalNum extreme_num(bool label, int sign) const {
380 return const_().extreme_num(label, sign);
381 }
384 GroupingProxy residue_groups();
385 const std::string& subchain_id() const { return const_().subchain_id(); }
387 std::vector<std::string> extract_sequence() const { return const_().extract_sequence(); }
390 return const_().label_seq_id_to_auth(label_seq_id);
391 }
393 return const_().auth_seq_id_to_label(auth_seq_id);
394 }
395private:
396 ConstResidueSpan const_() const { return ConstResidueSpan(begin(), size()); }
397};
398
399// ResidueGroup represents residues with the same sequence number and insertion
400// code, but different residue names. I.e. microheterogeneity.
401// Usually, there is only one residue in the group.
402// The residues must be consecutive.
404 ResidueGroup() = default;
406 Residue& by_resname(const std::string& name) {
407 return *impl::find_iter(*this, name);
408 }
409 void remove_residue(const std::string& name) {
410 erase(impl::find_iter(*this, name));
411 }
412};
413
415 ConstResidueGroup() = default;
417 const Residue& by_resname(const std::string& name) {
418 return *impl::find_iter(*this, name);
419 }
420};
421
423 return ResidueSpan(subspan([&](const Residue& r) { return r.seqid == id; }));
424}
426 return const_().find_residue_group(id);
427}
429 return ConstResidueSpan(subspan([&](const Residue& r) { return r.seqid == id; }));
430}
431
442
444 return {*this};
445}
446
447
448namespace impl {
449template<typename T, typename Ch> std::vector<T> chain_subchains(Ch* ch) {
450 std::vector<T> v;
451 for (auto start = ch->residues.begin(); start != ch->residues.end(); ) {
452 auto end = start + 1;
453 while (end != ch->residues.end() && end->subchain == start->subchain)
454 ++end;
455 v.push_back(ch->whole().sub(start, end));
456 start = end;
457 }
458 return v;
459}
460} // namespace impl
461
462struct Chain {
463 static const char* what() { return "Chain"; }
464 std::string name;
465 std::vector<Residue> residues;
466
467 explicit Chain(std::string cname) noexcept : name(cname) {}
468
470 Residue* begin = residues.empty() ? nullptr : &residues[0];
471 return ResidueSpan(residues, begin, residues.size());
472 }
474 const Residue* begin = residues.empty() ? nullptr : &residues[0];
475 return ConstResidueSpan(begin, residues.size());
476 }
477
478 template<typename F> ResidueSpan get_residue_span(F&& func) {
479 return whole().subspan(func);
480 }
481 template<typename F> ConstResidueSpan get_residue_span(F&& func) const {
482 return whole().subspan(func);
483 }
484
486 auto begin = residues.begin();
487 while (begin != residues.end() && begin->entity_type != EntityType::Polymer)
488 ++begin;
489 auto end = begin;
490 while (end != residues.end() && end->entity_type == EntityType::Polymer
491 && end->subchain == begin->subchain)
492 ++end;
493 return ResidueSpan(residues, &*begin, end - begin);
494 }
496 return const_cast<Chain*>(this)->get_polymer();
497 }
498
500 return get_residue_span([](const Residue& r) {
501 return r.entity_type == EntityType::NonPolymer ||
502 r.entity_type == EntityType::Branched;
503 });
504 }
506 return const_cast<Chain*>(this)->get_ligands();
507 }
508
510 return get_residue_span([](const Residue& r) {
511 return r.entity_type == EntityType::Water;
512 });
513 }
515 return const_cast<Chain*>(this)->get_waters();
516 }
517
518 ResidueSpan get_subchain(const std::string& s) {
519 return get_residue_span([&](const Residue& r) { return r.subchain == s; });
520 }
521 ConstResidueSpan get_subchain(const std::string& s) const {
522 return const_cast<Chain*>(this)->get_subchain(s);
523 }
524
525 std::vector<ResidueSpan> subchains() {
526 return impl::chain_subchains<ResidueSpan>(this);
527 }
528 std::vector<ConstResidueSpan> subchains() const {
529 return impl::chain_subchains<ConstResidueSpan>(this);
530 }
531
538
540 const Residue* find_residue(const ResidueId& rid) const {
541 return const_cast<Chain*>(this)->find_residue(rid);
542 }
543
545 void append_residues(std::vector<Residue> new_resi, int min_sep=0);
546
547 // methods present in Structure, Model, ... - used in templates
548 Chain empty_copy() const { return Chain(name); }
550 std::vector<Residue>& children() { return residues; }
551 const std::vector<Residue>& children() const { return residues; }
552
553 // Returns false only for alternative conformation (microheterogeneity).
554 bool is_first_in_group(const Residue& res) const {
555 return &res == residues.data() || (&res - 1)->group_key() != res.group_key();
556 }
557
558 // Returns the previous residue or nullptr.
559 // Got complicated by handling of multi-conformations / microheterogeneity.
560 const Residue* previous_residue(const Residue& res) const {
561 const Residue* start = residues.data();
562 for (const Residue* p = &res; p-- != start; )
563 if (res.group_key() != p->group_key()) {
564 while (p != start && p->group_key() == (p-1)->group_key() &&
565 (res.atoms.at(0).altloc == '\0' || !res.same_conformer(*p)))
566 --p;
567 return p;
568 }
569 return nullptr;
570 }
571
572 // Returns the next residue or nullptr.
573 const Residue* next_residue(const Residue& res) const {
574 const Residue* end = residues.data() + residues.size();
575 for (const Residue* p = &res + 1; p != end; ++p)
576 if (res.group_key() != p->group_key()) {
577 while (p+1 != end && p->group_key() == (p+1)->group_key() &&
578 !res.same_conformer(*p))
579 ++p;
580 return p;
581 }
582 return nullptr;
583 }
584
585 // Iterators that in case of multiple conformations (microheterogeneity)
586 // skip all but the first conformation.
589};
590
591inline std::string atom_str(const Chain& chain,
592 const ResidueId& res_id,
593 const Atom& atom) {
594 return atom_str(chain.name, res_id, atom.name, atom.altloc);
595}
596
597struct const_CRA {
598 const Chain* chain;
600 const Atom* atom;
601};
602
603struct CRA {
607 operator const_CRA() const { return const_CRA{chain, residue, atom}; }
608};
609
610inline std::string atom_str(const const_CRA& cra) {
611 static const ResidueId null_residue_id = {};
612 return atom_str(cra.chain ? cra.chain->name : "null",
613 cra.residue ? *cra.residue : null_residue_id,
614 cra.atom ? cra.atom->name : "null",
615 cra.atom ? cra.atom->altloc : '\0');
616}
617
618inline bool atom_matches(const const_CRA& cra, const AtomAddress& addr, bool ignore_segment=false) {
619 return cra.chain && cra.chain->name == addr.chain_name &&
620 cra.residue && cra.residue->matches_noseg(addr.res_id) &&
621 (ignore_segment || cra.residue->segment == addr.res_id.segment) &&
622 cra.atom && cra.atom->name == addr.atom_name &&
623 cra.atom->altloc == addr.altloc;
624}
625
626inline AtomAddress make_address(const Chain& ch, const Residue& res, const Atom& at) {
627 return AtomAddress(ch.name, res, at.name, at.altloc);
628}
629
630
631template<typename CraT>
633public:
635 using reference = const CraT;
636 CraIterPolicy() : chains_end(nullptr), cra{nullptr, nullptr, nullptr} {}
637 CraIterPolicy(const Chain* end, CraT cra_) : chains_end(end), cra(cra_) {}
638 void increment() {
639 if (cra.atom == nullptr)
640 return;
641 if (++cra.atom == vector_end_ptr(cra.residue->atoms)) {
642 do {
643 if (++cra.residue == vector_end_ptr(cra.chain->residues)) {
644 do {
645 if (++cra.chain == chains_end) {
646 cra.atom = nullptr;
647 return;
648 }
649 } while (cra.chain->residues.empty());
650 cra.residue = &cra.chain->residues[0];
651 }
652 } while (cra.residue->atoms.empty());
653 cra.atom = &cra.residue->atoms[0];
654 }
655 }
656 void decrement() {
657 while (cra.atom == nullptr || cra.atom == cra.residue->atoms.data()) {
658 while (cra.residue == nullptr || cra.residue == cra.chain->residues.data()) {
659 // iterating backward beyond begin() will have undefined effects
660 while ((--cra.chain)->residues.empty()) {}
661 cra.residue = vector_end_ptr(cra.chain->residues);
662 }
663 --cra.residue;
664 cra.atom = vector_end_ptr(cra.residue->atoms);
665 }
666 --cra.atom;
667 }
668 bool equal(const CraIterPolicy& o) const { return cra.atom == o.cra.atom; }
669 CraT dereference() { return cra; } // make copy b/c increment() modifies cra
671 operator const_policy() const { return const_policy(chains_end, cra); }
672private:
673 const Chain* chains_end;
674 CraT cra;
675};
676
677template<typename CraT, typename ChainsRefT>
678struct CraProxy_ {
679 ChainsRefT chains;
680 using iterator = BidirIterator<CraIterPolicy<CraT>>;
681 iterator begin() {
682 for (auto& chain : chains)
683 for (auto& residue : chain.residues)
684 for (auto& atom : residue.atoms)
685 return CraIterPolicy<CraT>{vector_end_ptr(chains), CraT{&chain, &residue, &atom}};
686 return {};
687 }
688 iterator end() {
689 auto* chains_end = vector_end_ptr(chains);
690 return CraIterPolicy<CraT>{chains_end, CraT{chains_end, nullptr, nullptr}};
691 }
692};
693
696
697struct Model {
698 static const char* what() { return "Model"; }
699 std::string name; // actually an integer number
700 std::vector<Chain> chains;
701 explicit Model(std::string mname) noexcept : name(mname) {}
702
703 // Returns the first chain with given name, or nullptr.
704 Chain* find_chain(const std::string& chain_name) {
705 return impl::find_or_null(chains, chain_name);
706 }
707 const Chain* find_chain(const std::string& chain_name) const {
708 return const_cast<Model*>(this)->find_chain(chain_name);
709 }
710
711 // Returns the last chain with given name, or nullptr.
712 Chain* find_last_chain(const std::string& chain_name) {
713 auto it = std::find_if(chains.rbegin(), chains.rend(),
714 [&](const Chain& c) { return c.name == chain_name; });
715 return it != chains.rend() ? &*it : nullptr;
716 }
717
718
719 void remove_chain(const std::string& chain_name) {
721 [&](const Chain& c) { return c.name == chain_name; });
722 }
723
725 for (auto i = chains.begin(); i != chains.end(); ++i)
726 for (auto j = i + 1; j != chains.end(); ++j)
727 if (i->name == j->name) {
728 i->append_residues(j->residues, min_sep);
729 chains.erase(j--);
730 }
731 }
732
733 ResidueSpan get_subchain(const std::string& sub_name) {
734 for (Chain& chain : chains)
735 if (ResidueSpan sub = chain.get_subchain(sub_name))
736 return sub;
737 return ResidueSpan();
738 }
739 ConstResidueSpan get_subchain(const std::string& sub_name) const {
740 return const_cast<Model*>(this)->get_subchain(sub_name);
741 }
742
743 std::vector<ResidueSpan> subchains() {
744 return impl::model_subchains<ResidueSpan>(this);
745 }
746 std::vector<ConstResidueSpan> subchains() const {
747 return impl::model_subchains<ConstResidueSpan>(this);
748 }
749
750 std::map<std::string, std::string> subchain_to_chain() const {
751 std::map<std::string, std::string> mapping;
752 for (const Chain& chain : chains) {
753 std::string prev;
754 for (const Residue& res : chain.residues)
755 if (!res.subchain.empty() && res.subchain != prev) {
756 prev = res.subchain;
757 mapping[res.subchain] = chain.name;
758 }
759 }
760 return mapping;
761 }
762
763 Residue* find_residue(const std::string& chain_name, const ResidueId& rid) {
764 for (Chain& chain : chains)
765 if (chain.name == chain_name)
766 if (Residue* residue = chain.find_residue(rid))
767 return residue;
768 return nullptr;
769 }
770 const Residue* find_residue(const std::string& chain_name, const ResidueId& rid) const {
771 return const_cast<Model*>(this)->find_residue(chain_name, rid);
772 }
773
774
775 ResidueGroup find_residue_group(const std::string& chain_name, SeqId seqid) {
776 for (Chain& chain : chains)
777 if (chain.name == chain_name)
778 if (ResidueGroup res_group = chain.find_residue_group(seqid))
779 return res_group;
780 fail("No such chain or residue: " + chain_name + " " + seqid.str());
781 }
782
783 Residue& sole_residue(const std::string& chain_name, SeqId seqid) {
784 ResidueSpan rr = find_residue_group(chain_name, seqid);
785 if (rr.size() != 1)
786 fail("Multiple residues " + chain_name + " " + seqid.str());
787 return rr[0];
788 }
789
790 std::vector<std::string> get_all_residue_names() const {
791 std::vector<std::string> names;
792 for (const Chain& chain : chains)
793 for (const Residue& res : chain.residues)
794 if (!in_vector(res.name, names))
795 names.push_back(res.name);
796 return names;
797 }
798
800 for (Chain& chain : chains)
801 if (chain.name == address.chain_name) {
802 for (Residue& res : chain.residues)
803 if (address.res_id.matches_noseg(res) &&
804 (ignore_segment || address.res_id.segment == res.segment)) {
805 Atom *at = nullptr;
806 if (!address.atom_name.empty())
807 at = res.find_atom(address.atom_name, address.altloc);
808 return {&chain, &res, at};
809 }
810 }
811 return {nullptr, nullptr, nullptr};
812 }
813
815 return const_cast<Model*>(this)->find_cra(address, ignore_segment);
816 }
817
818 CraProxy all() { return {chains}; }
819 ConstCraProxy all() const { return {chains}; }
820
822 const Atom* find_atom(const AtomAddress& address) const { return find_cra(address).atom; }
823
824 std::array<int, 3> get_indices(const Chain* c, const Residue* r,
825 const Atom* a) const {
826 return {{ c ? static_cast<int>(c - chains.data()) : -1,
827 c && r ? static_cast<int>(r - c->residues.data()) : -1,
828 r && a ? static_cast<int>(a - r->atoms.data()) : -1 }};
829 }
830
831 std::bitset<(size_t)El::END> present_elements() const {
832 std::bitset<(size_t)El::END> table;
833 for (const Chain& chain : chains)
834 for (const Residue& res : chain.residues)
835 for (const Atom& a : res.atoms)
836 table.set(a.element.ordinal());
837 return table;
838 }
839
840 CRA get_cra(Atom* atom) { return parent_index.get_cra(*this, atom); }
841 Chain* get_parent_of(Residue* res) { return parent_index.get_parent_of(*this, res); }
842
843 // methods present in Structure, Model, ... - used in templates
844 Model empty_copy() const { return Model(name); }
846 std::vector<Chain>& children() { return chains; }
847 const std::vector<Chain>& children() const { return chains; }
848
849private:
850 struct ParentIndex {
851 using index_type = std::uint32_t;
852 std::unordered_map<const Atom*, std::array<index_type, 3>> atom_parents;
853 std::unordered_map<const Residue*, std::array<index_type, 2>> residue_parents;
854 void update(const Model& model) {
855 clear();
856 for (index_type ic = 0; ic < model.chains.size(); ++ic) {
857 const Chain& chain = model.chains[ic];
858 for (index_type ir = 0; ir < chain.residues.size(); ++ir) {
859 const Residue& res = chain.residues[ir];
860 residue_parents.emplace(&res, std::array<index_type,2>{ic, ir});
861 for (index_type ia = 0; ia < res.atoms.size(); ++ia)
862 atom_parents.emplace(&res.atoms[ia], std::array<index_type,3>{ic, ir, ia});
863 }
864 }
865 }
866 void clear() {
867 atom_parents.clear();
868 residue_parents.clear();
869 }
870 CRA get_cra(Model& model, Atom* atom) {
871 for (;;) {
872 auto it = atom_parents.find(atom);
873 if (it != atom_parents.end()) {
874 auto ic = it->second[0];
875 auto ir = it->second[1];
876 auto ia = it->second[2];
877 if (ic < model.chains.size()) {
878 Chain& chain = model.chains[ic];
879 if (ir < chain.residues.size()) {
880 Residue& res = chain.residues[ir];
881 if (ia < res.atoms.size() && atom == &res.atoms[ia])
882 return {&chain, &res, atom};
883 }
884 }
885 }
886 update(model);
887 }
888 }
889 Chain* get_parent_of(Model& model, Residue* res) {
890 for (;;) {
891 auto it = residue_parents.find(res);
892 if (it != residue_parents.end()) {
893 auto ic = it->second[0];
894 auto ir = it->second[1];
895 if (ic < model.chains.size()) {
896 Chain& chain = model.chains[ic];
897 if (ir < chain.residues.size() && res == &chain.residues[ir])
898 return &chain;
899 }
900 }
901 update(model);
902 }
903 }
904 };
905 ParentIndex parent_index;
906};
907
908inline Entity* find_entity_of_subchain(const std::string& subchain_id,
909 std::vector<Entity>& entities) {
910 if (!subchain_id.empty())
911 for (Entity& ent : entities)
912 if (in_vector(subchain_id, ent.subchains))
913 return &ent;
914 return nullptr;
915}
916inline const Entity* find_entity_of_subchain(const std::string& subchain_id,
917 const std::vector<Entity>& entities) {
918 return find_entity_of_subchain(subchain_id, const_cast<std::vector<Entity>&>(entities));
919}
920
921struct Structure {
922 std::string name;
924 std::string spacegroup_hm; // usually pdb symbol, cf. SpaceGroup::pdb_name()
925 std::vector<Model> models;
926 std::vector<NcsOp> ncs;
927 std::vector<Entity> entities;
928 std::vector<Connection> connections;
929 std::vector<CisPep> cispeps;
930 std::vector<ModRes> mod_residues;
931 std::vector<Helix> helices;
932 std::vector<Sheet> sheets;
933 std::vector<Assembly> assemblies;
934 std::map<int, std::vector<int>> conect_map;
936
938 bool has_d_fraction = false; // uses Refmac's ccp4_deuterium_fraction
940 char ter_status = '\0';
941
943 bool has_origx = false;
945
947 std::map<std::string, std::string> info;
949 std::vector<OldToNew> shortened_ccd_codes;
951 std::vector<std::string> raw_remarks;
953 double resolution = 0;
954
958
959 const std::string& get_info(const std::string& tag) const {
960 static const std::string empty;
961 auto it = info.find(tag);
962 return it != info.end() ? it->second : empty;
963 }
964
966 if (models.empty())
967 fail("no structural models");
968 return models[0];
969 }
970 const Model& first_model() const {
971 return const_cast<Structure*>(this)->first_model();
972 }
973
974 Model* find_model(const std::string& model_name) {
975 return impl::find_or_null(models, model_name);
976 }
977 const Model* find_model(const std::string& model_name) const {
978 return const_cast<Structure*>(this)->find_model(model_name);
979 }
980 Model& find_or_add_model(const std::string& model_name) {
981 return impl::find_or_add(models, model_name);
982 }
983
984 void remove_model(const std::string& model_name) {
985 models.erase(impl::find_iter(models, model_name));
986 }
987
989 for (size_t i = 0; i != models.size(); ++i)
990 models[i].name = std::to_string(i+1);
991 }
992
993 Entity* get_entity(const std::string& ent_id) {
994 return impl::find_or_null(entities, ent_id);
995 }
996 const Entity* get_entity(const std::string& ent_id) const {
997 return const_cast<Structure*>(this)->get_entity(ent_id);
998 }
999
1001 return sub ? find_entity_of_subchain(sub.subchain_id(), entities) : nullptr;
1002 }
1003 const Entity* get_entity_of(const ConstResidueSpan& sub) const {
1004 return const_cast<Structure*>(this)->get_entity_of(sub);
1005 }
1006
1007 Assembly* find_assembly(const std::string& assembly_id) {
1008 return impl::find_or_null(assemblies, assembly_id);
1009 }
1010
1012 return impl::find_or_null(connections, conn_name);
1013 }
1014 const Connection* find_connection_by_name(const std::string& conn_name) const {
1015 return const_cast<Structure*>(this)->find_connection_by_name(conn_name);
1016 }
1017
1019 const const_CRA& cra2,
1020 bool ignore_segment=false) {
1021 for (Connection& c : connections)
1022 if ((atom_matches(cra1, c.partner1, ignore_segment) &&
1023 atom_matches(cra2, c.partner2, ignore_segment)) ||
1024 (atom_matches(cra1, c.partner2, ignore_segment) &&
1025 atom_matches(cra2, c.partner1, ignore_segment)))
1026 return &c;
1027 return nullptr;
1028 }
1029
1031 for (Connection& c : connections)
1032 if ((a1 == c.partner1 && a2 == c.partner2) ||
1033 (a1 == c.partner2 && a2 == c.partner1))
1034 return &c;
1035 return nullptr;
1036 }
1037
1038 size_t ncs_given_count() const {
1039 return std::count_if(ncs.begin(), ncs.end(), [](const NcsOp& o) { return o.given; });
1040 }
1041 double get_ncs_multiplier() const {
1042 return (ncs.size() + 1.0) / (ncs_given_count() + 1.0); // +1 b/c identity not included
1043 }
1044 bool ncs_not_expanded() const {
1045 return std::any_of(ncs.begin(), ncs.end(), [](const NcsOp& o) { return !o.given; });
1046 }
1047
1048 void add_conect_one_way(int serial1, int serial2, int order) {
1049 auto& vec = conect_map[serial1];
1050 for (int i = 0; i < order; ++i)
1051 vec.insert(std::upper_bound(vec.begin(), vec.end(), serial2), serial2);
1052 }
1053 void add_conect(int serial1, int serial2, int order) {
1056 }
1057
1059 for (Model& model : models)
1060 model.merge_chain_parts(min_sep);
1061 }
1062
1064 for (Model& model : models)
1065 remove_empty_children(model);
1066 }
1067
1068 // copy all but models (in general, empty_copy copies all but children)
1070 Structure st;
1071 st.name = name;
1072 st.cell = cell;
1073 st.spacegroup_hm = spacegroup_hm;
1074 st.ncs = ncs;
1075 st.entities = entities;
1076 st.connections = connections;
1077 st.helices = helices;
1078 st.sheets = sheets;
1079 st.assemblies = assemblies;
1080 st.meta = meta;
1081 st.has_origx = has_origx;
1082 st.origx = origx;
1083 st.info = info;
1084 st.raw_remarks = raw_remarks;
1085 st.resolution = resolution;
1086 st.input_format = input_format;
1087 return st;
1088 }
1090 std::vector<Model>& children() { return models; }
1091 const std::vector<Model>& children() const { return models; }
1092
1093 void setup_cell_images();
1094};
1095
1097 auto it = std::find_if(residues.begin(), residues.end(),
1098 [&](const Residue& r) { return r.matches(rid); });
1099 return it != residues.end() ? &*it : nullptr;
1100}
1101
1104 if (r)
1105 return r;
1106 residues.emplace_back(rid);
1107 return &residues.back();
1108}
1109
1110inline void Chain::append_residues(std::vector<Residue> new_resi, int min_sep) {
1111 if (new_resi.empty())
1112 return;
1113 if (min_sep > 0) {
1115 // adjust sequence numbers if necessary
1116 auto diff = new_span.extreme_num(false, -1) - whole().extreme_num(false, 1);
1117 if (diff && int(diff) < min_sep)
1118 for (Residue& res : new_resi)
1119 res.seqid.num += min_sep - int(diff);
1120 // adjust label_seq_id if necessary
1121 diff = new_span.extreme_num(true, -1) - whole().extreme_num(true, 1);
1122 if (diff && int(diff) < min_sep)
1123 for (Residue& res : new_resi)
1124 res.label_seq += min_sep - int(diff);
1125 }
1126 std::move(new_resi.begin(), new_resi.end(), std::back_inserter(residues));
1127}
1128
1134
1135} // namespace gemmi
1136
1137#endif
CraIterPolicy(const Chain *end, CraT cra_)
Definition model.hpp:637
CraIterPolicy< const_CRA > const_policy
Definition model.hpp:670
bool equal(const CraIterPolicy &o) const
Definition model.hpp:668
CoorFormat
File format of a macromolecular model.
Definition model.hpp:80
T * vector_end_ptr(std::vector< T > &v)
Definition util.hpp:251
bool atom_matches(const const_CRA &cra, const AtomAddress &addr, bool ignore_segment=false)
Definition model.hpp:618
std::string atom_str(const Chain &chain, const ResidueId &res_id, const Atom &atom)
Definition model.hpp:591
void vector_remove_if(std::vector< T > &v, F &&condition)
Definition util.hpp:266
Entity * find_entity_of_subchain(const std::string &subchain_id, std::vector< Entity > &entities)
Definition model.hpp:908
AtomGroup_< Atom > AtomGroup
Definition model.hpp:173
const SpaceGroup * find_spacegroup_by_name(std::string name, double alpha=0., double gamma=0.) noexcept
bool is_hydrogen(El el)
Definition elem.hpp:26
bool is_same_conformer(char altloc1, char altloc2)
Definition model.hpp:107
void remove_empty_children(T &obj)
Definition model.hpp:102
std::string join_str(T begin, T end, const S &sep, const F &getter)
Definition util.hpp:182
bool in_vector(const T &x, const std::vector< T > &v)
Definition util.hpp:241
CalcFlag
corresponds to _atom_site.calc_flag in mmCIF
Definition model.hpp:83
void fail(const std::string &msg)
Definition fail.hpp:59
AtomAddress make_address(const Chain &ch, const Residue &res, const Atom &at)
Definition model.hpp:626
constexpr double u_to_b()
Definition math.hpp:29
constexpr int ialpha4_id(const char *s)
Definition util.hpp:305
void vector_move_extend(std::vector< T > &dst, std::vector< T > &&src)
Definition util.hpp:256
char alpha_up(char c)
Definition util.hpp:60
Definition seqid.hpp:149
Represents atom site in macromolecular structure (~100 bytes).
Definition model.hpp:112
double b_eq() const
Definition model.hpp:139
SMat33< float > aniso
Definition model.hpp:127
char altloc
Definition model.hpp:115
short tls_group_id
Definition model.hpp:120
bool is_hydrogen() const
Definition model.hpp:140
signed char charge
Definition model.hpp:116
bool altloc_matches(char request) const
Definition model.hpp:133
char flag
Definition model.hpp:119
float b_iso
Definition model.hpp:126
Element element
Definition model.hpp:117
const std::string & group_key() const
Definition model.hpp:137
float fraction
Definition model.hpp:122
CalcFlag calc_flag
Definition model.hpp:118
std::string padded_name() const
Definition model.hpp:144
float occ
Definition model.hpp:124
bool same_conformer(const Atom &other) const
Definition model.hpp:130
char altloc_or(char null_char) const
Definition model.hpp:129
Atom empty_copy() const
Definition model.hpp:156
bool has_altloc() const
Definition model.hpp:138
Position pos
Definition model.hpp:123
static const char * what()
Definition model.hpp:113
std::string name
Definition model.hpp:114
Residue * residue
Definition model.hpp:605
Chain * chain
Definition model.hpp:604
Atom * atom
Definition model.hpp:606
Residue * find_residue(const ResidueId &rid)
Definition model.hpp:1096
UniqProxy< Residue > first_conformer()
Definition model.hpp:587
const Residue * next_residue(const Residue &res) const
Definition model.hpp:573
ConstResidueSpan get_waters() const
Definition model.hpp:514
ResidueSpan get_polymer()
Definition model.hpp:485
ConstResidueSpan get_residue_span(F &&func) const
Definition model.hpp:481
ResidueSpan get_ligands()
Definition model.hpp:499
std::vector< Residue > residues
Definition model.hpp:465
const std::vector< Residue > & children() const
Definition model.hpp:551
ResidueSpan get_subchain(const std::string &s)
Definition model.hpp:518
std::string name
Definition model.hpp:464
const Residue * find_residue(const ResidueId &rid) const
Definition model.hpp:540
ConstUniqProxy< Residue > first_conformer() const
Definition model.hpp:588
Residue * find_or_add_residue(const ResidueId &rid)
Definition model.hpp:1102
ResidueGroup find_residue_group(SeqId id)
Definition model.hpp:532
ResidueSpan get_residue_span(F &&func)
Definition model.hpp:478
ConstResidueGroup find_residue_group(SeqId id) const
Definition model.hpp:535
Chain empty_copy() const
Definition model.hpp:548
bool is_first_in_group(const Residue &res) const
Definition model.hpp:554
ConstResidueSpan get_polymer() const
Definition model.hpp:495
ResidueSpan whole()
Definition model.hpp:469
std::vector< ConstResidueSpan > subchains() const
Definition model.hpp:528
ConstResidueSpan get_subchain(const std::string &s) const
Definition model.hpp:521
std::vector< ResidueSpan > subchains()
Definition model.hpp:525
ResidueSpan get_waters()
Definition model.hpp:509
ConstResidueSpan get_ligands() const
Definition model.hpp:505
ConstResidueSpan whole() const
Definition model.hpp:473
const Residue * previous_residue(const Residue &res) const
Definition model.hpp:560
std::vector< Residue > & children()
Definition model.hpp:550
void append_residues(std::vector< Residue > new_resi, int min_sep=0)
Definition model.hpp:1110
static const char * what()
Definition model.hpp:463
Chain(std::string cname) noexcept
Definition model.hpp:467
const Residue & by_resname(const std::string &name)
Definition model.hpp:417
ConstResidueGroup(ConstResidueSpan &&sp)
Definition model.hpp:416
ConstResidueGroup find_residue_group(SeqId id) const
Definition model.hpp:428
SeqId label_seq_id_to_auth(SeqId::OptionalNum label_seq_id) const
Definition model.hpp:328
std::vector< std::string > extract_sequence() const
Definition model.hpp:319
ConstResidueSpan(Parent &&span)
Definition model.hpp:283
SeqId::OptionalNum auth_seq_id_to_label(SeqId auth_seq_id) const
Definition model.hpp:344
ConstUniqProxy< Residue, ConstResidueSpan > first_conformer() const
Definition model.hpp:304
const std::string & subchain_id() const
Definition model.hpp:308
SeqId::OptionalNum extreme_num(bool label, int sign) const
Definition model.hpp:294
const char * uname() const
Definition elem.hpp:311
ResidueGroup find_residue_group(const std::string &chain_name, SeqId seqid)
Definition model.hpp:775
void remove_chain(const std::string &chain_name)
Definition model.hpp:719
ConstCraProxy all() const
Definition model.hpp:819
std::vector< std::string > get_all_residue_names() const
Definition model.hpp:790
std::map< std::string, std::string > subchain_to_chain() const
Definition model.hpp:750
Residue * find_residue(const std::string &chain_name, const ResidueId &rid)
Definition model.hpp:763
const Residue * find_residue(const std::string &chain_name, const ResidueId &rid) const
Definition model.hpp:770
ConstResidueSpan get_subchain(const std::string &sub_name) const
Definition model.hpp:739
const Chain * find_chain(const std::string &chain_name) const
Definition model.hpp:707
const std::vector< Chain > & children() const
Definition model.hpp:847
ResidueSpan get_subchain(const std::string &sub_name)
Definition model.hpp:733
const_CRA find_cra(const AtomAddress &address, bool ignore_segment=false) const
Definition model.hpp:814
std::vector< ConstResidueSpan > subchains() const
Definition model.hpp:746
CraProxy all()
Definition model.hpp:818
CRA get_cra(Atom *atom)
Definition model.hpp:840
static const char * what()
Definition model.hpp:698
const Atom * find_atom(const AtomAddress &address) const
Definition model.hpp:822
std::vector< Chain > chains
Definition model.hpp:700
std::vector< ResidueSpan > subchains()
Definition model.hpp:743
std::string name
Definition model.hpp:699
Chain * find_chain(const std::string &chain_name)
Definition model.hpp:704
Chain * find_last_chain(const std::string &chain_name)
Definition model.hpp:712
Model empty_copy() const
Definition model.hpp:844
void merge_chain_parts(int min_sep=0)
Definition model.hpp:724
Model(std::string mname) noexcept
Definition model.hpp:701
Chain * get_parent_of(Residue *res)
Definition model.hpp:841
Atom * find_atom(const AtomAddress &address)
Definition model.hpp:821
std::bitset<(size_t) El::END > present_elements() const
Definition model.hpp:831
CRA find_cra(const AtomAddress &address, bool ignore_segment=false)
Definition model.hpp:799
std::array< int, 3 > get_indices(const Chain *c, const Residue *r, const Atom *a) const
Definition model.hpp:824
Residue & sole_residue(const std::string &chain_name, SeqId seqid)
Definition model.hpp:783
std::vector< Chain > & children()
Definition model.hpp:846
typename Span< Residue >::iterator iterator
Definition span.hpp:96
std::vector< typename Span< Residue >::value_type > vector_type
Definition span.hpp:95
MutableVectorSpan< Item > sub(Iter first, Iter last)
Definition span.hpp:104
MutableVectorSpan< Residue > subspan(F &&func)
Definition span.hpp:108
Non-crystallographic symmetry operation (such as in the MTRIXn record)
Definition unitcell.hpp:120
helper type used for Structure::shortened_ccd_codes
Definition model.hpp:91
std::string old
Definition model.hpp:91
options affecting how pdb file is read
Definition model.hpp:94
Coordinates in Angstroms - orthogonal (Cartesian) coordinates.
Definition unitcell.hpp:32
ResidueGroup()=default
void remove_residue(const std::string &name)
Definition model.hpp:409
ResidueGroup(ResidueSpan &&span)
Definition model.hpp:405
Residue & by_resname(const std::string &name)
Definition model.hpp:406
std::string name
Definition seqid.hpp:91
SeqId group_key() const
Definition seqid.hpp:94
GroupingProxy residue_groups()
Definition model.hpp:443
ConstUniqProxy< Residue, ResidueSpan > first_conformer() const
Definition model.hpp:383
std::vector< std::string > extract_sequence() const
Definition model.hpp:387
SeqId::OptionalNum auth_seq_id_to_label(SeqId auth_seq_id) const
Definition model.hpp:392
ResidueSpan(vector_type &v, iterator begin, std::size_t n)
Definition model.hpp:376
ResidueGroup find_residue_group(SeqId id)
Definition model.hpp:422
int length() const
Definition model.hpp:378
ResidueSpan()=default
SeqId::OptionalNum extreme_num(bool label, int sign) const
Definition model.hpp:379
SeqId label_seq_id_to_auth(SeqId::OptionalNum label_seq_id) const
Definition model.hpp:389
UniqProxy< Residue, ResidueSpan > first_conformer()
Definition model.hpp:382
const std::string & subchain_id() const
Definition model.hpp:385
ResidueSpan(Parent &&span)
Definition model.hpp:375
const Atom * get_p() const
Definition model.hpp:251
Atom * find_atom(const std::string &atom_name, char altloc, El el=El::X)
Definition model.hpp:215
bool same_conformer(const Residue &other) const
Definition model.hpp:254
AtomGroup get(const std::string &atom_name)
Definition model.hpp:232
bool is_water() const
Convenience function that duplicates functionality from resinfo.hpp.
Definition model.hpp:263
std::string subchain
Definition model.hpp:180
OptionalNum label_seq
Definition model.hpp:182
std::vector< Atom > & children()
Definition model.hpp:204
short group_idx
Definition model.hpp:187
std::string entity_id
Definition model.hpp:181
SiftsUnpResidue sifts_unp
Definition model.hpp:186
UniqProxy< Atom > first_conformer()
Definition model.hpp:273
ConstUniqProxy< Atom > first_conformer() const
Definition model.hpp:274
const std::vector< Atom > & children() const
Definition model.hpp:205
const Atom * get_o3prim() const
Definition model.hpp:252
Residue(const ResidueId &rid) noexcept
Definition model.hpp:191
const Atom * find_atom(const std::string &atom_name, char altloc, El el=El::X) const
Definition model.hpp:221
const Atom * get_ca() const
Definition model.hpp:247
std::vector< Atom > atoms
Definition model.hpp:188
EntityType entity_type
Definition model.hpp:183
static const char * what()
Definition model.hpp:178
const Atom * find_by_element(El el) const
Definition model.hpp:207
const Atom * get_c() const
Definition model.hpp:248
Residue empty_copy() const
Definition model.hpp:194
std::vector< Atom >::iterator find_atom_iter(const std::string &atom_name, char altloc, El el=El::X)
Definition model.hpp:225
Residue()=default
const Atom * get_n() const
Definition model.hpp:249
Atom & sole_atom(const std::string &atom_name)
Definition model.hpp:239
T trace() const
Definition math.hpp:272
std::string str() const
Definition seqid.hpp:79
OptionalInt< INT_MIN > OptionalNum
Definition seqid.hpp:53
Reference to UniProt residue, based on _pdbx_sifts_xref_db.
Definition metadata.hpp:248
Item * iterator
Definition span.hpp:20
Span< V > subspan(F &&func)
Definition span.hpp:74
const Residue & back()
Definition span.hpp:51
const_iterator begin() const
Definition span.hpp:44
const Residue & front()
Definition span.hpp:49
const_iterator end() const
Definition span.hpp:45
std::size_t size() const
Definition span.hpp:66
const std::vector< Model > & children() const
Definition model.hpp:1091
void merge_chain_parts(int min_sep=0)
Definition model.hpp:1058
std::vector< Sheet > sheets
Definition model.hpp:932
std::vector< Connection > connections
Definition model.hpp:928
std::string name
Definition model.hpp:922
const Entity * get_entity_of(const ConstResidueSpan &sub) const
Definition model.hpp:1003
Metadata meta
Definition model.hpp:935
const Model * find_model(const std::string &model_name) const
Definition model.hpp:977
std::vector< ModRes > mod_residues
Definition model.hpp:930
bool ncs_not_expanded() const
Definition model.hpp:1044
Entity * get_entity_of(const ConstResidueSpan &sub)
Definition model.hpp:1000
std::vector< Assembly > assemblies
Definition model.hpp:933
const Entity * get_entity(const std::string &ent_id) const
Definition model.hpp:996
const Model & first_model() const
Definition model.hpp:970
Model & find_or_add_model(const std::string &model_name)
Definition model.hpp:980
Model * find_model(const std::string &model_name)
Definition model.hpp:974
const Connection * find_connection_by_name(const std::string &conn_name) const
Definition model.hpp:1014
std::vector< Model > models
Definition model.hpp:925
void remove_empty_chains()
Definition model.hpp:1063
Transform origx
Definition model.hpp:944
void add_conect_one_way(int serial1, int serial2, int order)
Definition model.hpp:1048
Entity * get_entity(const std::string &ent_id)
Definition model.hpp:993
std::vector< NcsOp > ncs
Definition model.hpp:926
std::vector< Model > & children()
Definition model.hpp:1090
Assembly * find_assembly(const std::string &assembly_id)
Definition model.hpp:1007
std::vector< Helix > helices
Definition model.hpp:931
double get_ncs_multiplier() const
Definition model.hpp:1041
Connection * find_connection(const AtomAddress &a1, const AtomAddress &a2)
Definition model.hpp:1030
std::map< int, std::vector< int > > conect_map
Definition model.hpp:934
Connection * find_connection_by_cra(const const_CRA &cra1, const const_CRA &cra2, bool ignore_segment=false)
Definition model.hpp:1018
bool has_d_fraction
Definition model.hpp:938
Structure empty_copy() const
Definition model.hpp:1069
std::vector< CisPep > cispeps
Definition model.hpp:929
void remove_model(const std::string &model_name)
Definition model.hpp:984
void setup_cell_images()
Definition model.hpp:1129
char ter_status
in input PDB file: y = TER records were read, e = errors were detected
Definition model.hpp:940
double resolution
simplistic resolution value from/for REMARK 2
Definition model.hpp:953
UnitCell cell
Definition model.hpp:923
std::vector< OldToNew > shortened_ccd_codes
Mapping of long (4+) CCD codes (residue names) to PDB-compatible ones.
Definition model.hpp:949
CoorFormat input_format
Definition model.hpp:937
bool has_origx
Store ORIGXn / _database_PDB_matrix.origx*.
Definition model.hpp:943
const std::string & get_info(const std::string &tag) const
Definition model.hpp:959
size_t ncs_given_count() const
Definition model.hpp:1038
const SpaceGroup * find_spacegroup() const
Definition model.hpp:955
std::map< std::string, std::string > info
Minimal metadata with keys being mmcif tags: _entry.id, _cell.Z_PDB, ...
Definition model.hpp:947
std::vector< std::string > raw_remarks
original REMARK records stored if the file was read from the PDB format
Definition model.hpp:951
std::string spacegroup_hm
Definition model.hpp:924
void add_conect(int serial1, int serial2, int order)
Definition model.hpp:1053
Connection * find_connection_by_name(const std::string &conn_name)
Definition model.hpp:1011
void renumber_models()
Definition model.hpp:988
Model & first_model()
Definition model.hpp:965
std::vector< Entity > entities
Definition model.hpp:927
Unit cell.
Definition unitcell.hpp:139
void add_ncs_images_to_cs_images(const std::vector< NcsOp > &ncs)
Definition unitcell.hpp:352
void set_cell_images_from_spacegroup(const SpaceGroup *sg)
Definition unitcell.hpp:337
const Atom * atom
Definition model.hpp:600
const Chain * chain
Definition model.hpp:598
const Residue * residue
Definition model.hpp:599