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