Gemmi C++ API
Loading...
Searching...
No Matches
calculate.hpp
Go to the documentation of this file.
1// Copyright 2017-2018 Global Phasing Ltd.
2//
3// Calculate various properties of the model.
4
5#ifndef GEMMI_CALCULATE_HPP_
6#define GEMMI_CALCULATE_HPP_
7
8#include <array>
9#include "model.hpp"
10
11namespace gemmi {
12
13template<class T> bool has_hydrogen(const T& obj) {
14 for (const auto& child : obj.children())
16 return true;
17 return false;
18}
19template<> inline bool has_hydrogen(const Atom& atom) {
20 return atom.is_hydrogen();
21}
22
24template<class T> size_t count_hydrogen_sites(const T& obj) {
25 size_t sum = 0;
26 for (const auto& child : obj.children())
28 return sum;
29}
30template<> inline size_t count_hydrogen_sites(const Atom& atom) {
31 return (size_t) atom.is_hydrogen();
32}
33
34template<class T> double calculate_mass(const T& obj) {
35 double sum = 0;
36 for (const auto& child : obj.children())
37 sum += calculate_mass(child);
38 return sum;
39}
40template<> inline double calculate_mass(const Atom& atom) {
41 return atom.occ * atom.element.weight();
42}
43
49
50template<class T> CenterOfMass calculate_center_of_mass(const T& obj) {
51 CenterOfMass total{{}, 0.};
52 for (const auto& child : obj.children()) {
54 total = {total.weighted_sum + part.weighted_sum, total.mass + part.mass};
55 }
56 return total;
57}
58template<> inline CenterOfMass calculate_center_of_mass(const Atom& atom) {
59 double w_mass = atom.element.weight() * atom.occ;
60 return CenterOfMass{Position(atom.pos * w_mass), w_mass};
61}
62
63template<class T> void expand_box(const T& obj, Box<Position>& box) {
64 for (const auto& child : obj.children())
66}
67template<> inline void expand_box(const Atom& atom, Box<Position>& box) {
68 box.extend(atom.pos);
69}
70
71// we don't take NCS into account here (cf. NeighborSearch::set_bounding_cell())
72inline Box<Position> calculate_box(const Structure& st, double margin=0.) {
75 if (margin != 0.)
76 box.add_margin(margin);
77 return box;
78}
79
82 for (const Model& model : st.models)
83 for (const Chain& chain : model.chains)
84 for (const Residue& res : chain.residues)
85 for (const Atom& atom : res.atoms)
86 box.extend(st.cell.fractionalize(atom.pos));
87 if (margin != 0.)
88 box.add_margins({margin * st.cell.ar, margin * st.cell.br, margin * st.cell.cr});
89 return box;
90}
91
92
93// Calculate B_est from E. Merritt, Some B_eq are more equivalent than others,
94// Acta Cryst. A67, 512 (2011)
95// http://skuld.bmsc.washington.edu/parvati/ActaA_67_512.pdf
96inline double calculate_b_est(const Atom& atom) {
97 auto eig = atom.aniso.calculate_eigenvalues();
98 return u_to_b() * std::sqrt((eig[0] + eig[1] + eig[2]) /
99 (1/eig[0] + 1/eig[1] + 1/eig[2]));
100}
101
102inline double calculate_angle(const Position& p0, const Position& p1,
103 const Position& p2) {
104 return (p0 - p1).angle(p2 - p1);
105}
106
107// discussion: https://stackoverflow.com/questions/20305272/
108inline double calculate_dihedral(const Position& p0, const Position& p1,
109 const Position& p2, const Position& p3) {
110 Vec3 b0 = p1 - p0;
111 Vec3 b1 = p2 - p1;
112 Vec3 b2 = p3 - p2;
113 Vec3 u = b1.cross(b0);
114 Vec3 w = b2.cross(b1);
115 double y = u.cross(w).dot(b1);
116 double x = u.dot(w) * b1.length();
117 return std::atan2(y, x);
118}
119
121inline double calculate_dihedral_from_atoms(const Atom* a, const Atom* b,
122 const Atom* c, const Atom* d) {
123 if (a && b && c && d)
124 return calculate_dihedral(a->pos, b->pos, c->pos, d->pos);
125 return NAN;
126}
127
128inline double calculate_omega(const Residue& res, const Residue& next) {
129 return calculate_dihedral_from_atoms(res.get_ca(), res.get_c(),
130 next.get_n(), next.get_ca());
131}
132
133inline bool is_peptide_bond_cis(const Atom* ca1, const Atom* c,
134 const Atom* n, const Atom* ca2) {
136 return std::fabs(omega) < rad(30.);
137}
138
139inline double calculate_chiral_volume(const Position& actr, const Position& a1,
140 const Position& a2, const Position& a3) {
141 return (a1 - actr).dot((a2 - actr).cross(a3 - actr));
142}
143
144inline std::array<double, 2> calculate_phi_psi(const Residue* prev,
145 const Residue& res,
146 const Residue* next) {
147 std::array<double, 2> phi_psi{{NAN, NAN}};
148 if (prev || next) {
149 const Atom* CA = res.get_ca();
150 const Atom* C = res.get_c();
151 const Atom* N = res.get_n();
152 if (prev)
154 if (next)
156 }
157 return phi_psi;
158}
159
160GEMMI_DLL std::array<double, 4> find_best_plane(const std::vector<Atom*>& atoms);
161
162inline double get_distance_from_plane(const Position& pos,
163 const std::array<double, 4>& coeff) {
164 return coeff[0] * pos.x + coeff[1] * pos.y + coeff[2] * pos.z + coeff[3];
165}
166
167} // namespace gemmi
168#endif
#define GEMMI_DLL
Definition fail.hpp:53
double calculate_b_est(const Atom &atom)
Definition calculate.hpp:96
double calculate_mass(const T &obj)
Definition calculate.hpp:34
double calculate_chiral_volume(const Position &actr, const Position &a1, const Position &a2, const Position &a3)
size_t count_hydrogen_sites(const T &obj)
deprecated, use has_hydrogen() or count_atom_sites(..., Selection("[H,D]")
Definition calculate.hpp:24
CenterOfMass calculate_center_of_mass(const T &obj)
Definition calculate.hpp:50
void expand_box(const T &obj, Box< Position > &box)
Definition calculate.hpp:63
double calculate_omega(const Residue &res, const Residue &next)
Box< Position > calculate_box(const Structure &st, double margin=0.)
Definition calculate.hpp:72
bool is_peptide_bond_cis(const Atom *ca1, const Atom *c, const Atom *n, const Atom *ca2)
GEMMI_DLL std::array< double, 4 > find_best_plane(const std::vector< Atom * > &atoms)
double get_distance_from_plane(const Position &pos, const std::array< double, 4 > &coeff)
double calculate_dihedral(const Position &p0, const Position &p1, const Position &p2, const Position &p3)
bool has_hydrogen(const T &obj)
Definition calculate.hpp:13
double calculate_angle(const Position &p0, const Position &p1, const Position &p2)
Box< Fractional > calculate_fractional_box(const Structure &st, double margin=0.)
Definition calculate.hpp:80
constexpr double rad(double angle)
Definition math.hpp:32
Vec3_< double > Vec3
Definition math.hpp:101
std::array< double, 2 > calculate_phi_psi(const Residue *prev, const Residue &res, const Residue *next)
double calculate_dihedral_from_atoms(const Atom *a, const Atom *b, const Atom *c, const Atom *d)
the return value is in the same range as that of atan2(), i.e. [-pi, pi]
constexpr double u_to_b()
Definition math.hpp:29
Represents atom site in macromolecular structure (~100 bytes).
Definition model.hpp:112
SMat33< float > aniso
Definition model.hpp:127
bool is_hydrogen() const
Definition model.hpp:140
Element element
Definition model.hpp:117
float occ
Definition model.hpp:124
Position pos
Definition model.hpp:123
Position get() const
Definition calculate.hpp:47
double weight() const
Definition elem.hpp:304
Coordinates in Angstroms - orthogonal (Cartesian) coordinates.
Definition unitcell.hpp:32
const Atom * get_ca() const
Definition model.hpp:247
const Atom * get_c() const
Definition model.hpp:248
const Atom * get_n() const
Definition model.hpp:249
std::array< double, 3 > calculate_eigenvalues() const
Based on https://en.wikipedia.org/wiki/Eigenvalue_algorithm To calculate both eigenvalues and eigenve...
Definition math.hpp:351