Gemmi C++ API
Loading...
Searching...
No Matches
small.hpp
Go to the documentation of this file.
1// Copyright 2018 Global Phasing Ltd.
2//
3// Representation of a small molecule or inorganic crystal.
4// Flat list of atom sites. Minimal functionality.
5
6#ifndef GEMMI_SMALL_HPP_
7#define GEMMI_SMALL_HPP_
8
9#include <cctype> // for isalpha
10#include <algorithm> // for any_of
11#include <bitset>
12#include <string>
13#include <vector>
14#include "elem.hpp" // Element
15#include "math.hpp" // SMat33
16#include "symmetry.hpp" // find_spacegroup_by_name
17#include "unitcell.hpp" // UnitCell, Fractional
18#include "util.hpp" // vector_remove_if
19
20namespace gemmi {
21
22inline bool is_complete(const GroupOps& gops) {
23 for (Op op1 : gops.sym_ops)
24 for (Op op2 : gops.sym_ops)
25 if (gops.find_by_rotation((op1 * op2).rot) == nullptr)
26 return false;
27 return true;
28}
29
30inline std::vector<Op> triplets_to_ops(const std::vector<std::string>& symops) {
31 std::vector<Op> ops;
32 ops.reserve(symops.size());
33 for (const std::string& xyz : symops)
34 ops.push_back(parse_triplet(xyz));
35 return ops;
36}
37
39 struct Site {
40 std::string label;
41 std::string type_symbol;
43 double occ = 1.0;
44 double u_iso = 0.;
45 SMat33<double> aniso = {0, 0, 0, 0, 0, 0};
48 signed char charge = 0; // [-8, +8]
49
50 Position orth(const gemmi::UnitCell& cell_) const {
51 return cell_.orthogonalize(fract);
52 }
53
54 std::string element_and_charge_symbol() const {
55 std::string s = element.name();
56 if (charge != 0) {
57 s += std::to_string(std::abs(charge));
58 s += charge > 0 ? '+' : '-';
59 }
60 return s;
61 }
62 };
63
64 struct AtomType {
65 std::string symbol;
67 signed char charge = 0; // [-8, +8]
70 };
71
72 std::string name;
74 const SpaceGroup* spacegroup = nullptr;
75 std::string spacegroup_hm;
76 std::string spacegroup_hall;
78 std::vector<std::string> symops;
79 std::vector<Site> sites;
80 std::vector<AtomType> atom_types;
81 double wavelength = 0.; // the first wavelength if multiple
82
83 std::vector<Site> get_all_unit_cell_sites() const;
84
85 void determine_and_set_spacegroup(const char* order) {
86 spacegroup = nullptr;
87 if (order)
88 for (const char* c = order; *c != '\0' && spacegroup == nullptr; ++c) {
89 try {
90 GroupOps gops;
92 if (!spacegroup && *(c+1) == '.') {
93 // If symops don't correspond to tabulated settings,
94 // we can't set spacegroup, but we can set UnitCell::images.
95 if (gops.order() == (int) symops.size() && is_complete(gops)) {
97 return;
98 }
99 ++c;
100 }
101 } catch (std::exception&) {}
102 }
104 }
105
106 const SpaceGroup* determine_spacegroup_from(char c, GroupOps& gops) const {
107 switch (lower(c)) {
108 case 's':
109 if (symops.empty())
110 return nullptr;
112 return find_spacegroup_by_ops(gops);
113 case 'h':
114 if (spacegroup_hall.empty())
115 return nullptr;
117 case '1':
118 case '2': {
119 if (spacegroup_hm.empty())
120 return nullptr;
121 char prefer[] = {c, '\0'};
123 }
124 case 'n':
125 if (spacegroup_number == 0)
126 return nullptr;
128 default:
129 throw std::invalid_argument("determine_and_set_spacegroup(): wrong character in 'order'");
130 }
131 }
132
133 std::string check_spacegroup() const {
134 std::string err;
135 if (!symops.empty())
136 try {
137 std::vector<Op> ops = triplets_to_ops(symops);
138 for (Op& op : ops)
139 op.wrap();
140 std::sort(ops.begin(), ops.end());
142 if (!is_complete(gops))
143 cat_to(err, "symops list is incomplete or incorrect\n");
144 else if (gops.all_ops_sorted() != ops)
145 cat_to(err, "symops list is incorrect or incomplete or redundant\n");
146 const SpaceGroup* sg = find_spacegroup_by_ops(gops);
147 if (!sg)
148 cat_to(err, "space group from symops not found in the table\n");
149 else if (sg != spacegroup)
150 cat_to(err, "space group from symops differs: ", sg->xhm(), '\n');
151 } catch (std::exception& e) {
152 cat_to(err, "error while processing symops: ", e.what(), '\n');
153 }
154 if (!spacegroup_hall.empty())
155 try {
157 if (!sg)
158 cat_to(err, "space group from Hall symbol (", spacegroup_hall,
159 ") not found in the table\n");
160 else if (spacegroup != sg)
161 cat_to(err, "space group from Hall symbol (", spacegroup_hall,
162 ") differs: ", sg->xhm(), '\n');
163 } catch (std::exception& e) {
164 cat_to(err, "error while processing Hall symbol: ", e.what(), '\n');
165 }
166 if (!spacegroup_hm.empty()) {
168 if (!sg)
169 cat_to(err, "H-M symbol (", spacegroup_hm, ") not found in the table\n");
170 else if (!spacegroup || strcmp(spacegroup->hm, sg->hm) != 0)
171 cat_to(err, "space group from H-M symbol (", spacegroup_hm,
172 ") differs: ", sg->hm, '\n');
173 }
175 cat_to(err, "space group number (", spacegroup_number, ") differs\n");
176 return err;
177 }
178
179 const AtomType* get_atom_type(const std::string& symbol) const {
180 for (const AtomType& at : atom_types)
181 if (at.symbol == symbol)
182 return &at;
183 return nullptr;
184 }
185
186 // similar to Model::present_elements() from model.hpp
187 std::bitset<(size_t)El::END> present_elements() const {
188 std::bitset<(size_t)El::END> table;
189 for (const Site& atom : sites)
190 table.set((size_t)atom.element.elem);
191 return table;
192 }
193
195 vector_remove_if(sites, [](const Site& a) { return a.element.is_hydrogen(); });
196 }
197
198 // pre: atoms on special positions have "chemical" occupancy (i.e. not divided
199 // by n for n-fold symmetry)
201 for (Site& site : sites) {
203 if (n_mates != 0)
204 site.occ /= (n_mates + 1);
205 }
206 }
207
211};
212
213template<typename T>
214inline void split_element_and_charge(const std::string& label, T* dest) {
215 int len = label.size() > 1 && std::isalpha(label[1]) ? 2 : 1;
216 dest->element = len == 1 ? impl::find_single_letter_element(label[0] & ~0x20)
217 : find_element(label.c_str());
218 if (dest->element != El::X && (label.back() == '+' || label.back() == '-')) {
219 int sign = label.back() == '+' ? 1 : -1;
220 if (label.size() - len == 1)
221 dest->charge = sign;
222 else if (label.size() - len == 2 && label[len] >= '0' && label[len] <= '9')
223 dest->charge = sign * (label[len] - '0');
224 }
225}
226
227inline std::vector<SmallStructure::Site>
229 const double SPECIAL_POS_TOL = 0.4;
230 std::vector<Site> all;
231 for (const Site& site : sites) {
232 size_t start = all.size();
233 all.push_back(site);
234 for (const FTransform& image : cell.images) {
235 Fractional fpos = image.apply(site.fract);
236 if (std::any_of(all.begin() + start, all.end(), [&](const Site& other) {
237 return cell.distance_sq(fpos, other.fract) < sq(SPECIAL_POS_TOL);
238 }))
239 continue;
240 all.push_back(site);
241 all.back().fract = fpos;
242 }
243 }
244 return all;
245}
246
247} // namespace gemmi
248#endif
Elements from the periodic table.
Math utilities. 3D linear algebra.
char lower(char c)
Definition util.hpp:54
void vector_remove_if(std::vector< T > &v, F &&condition)
Definition util.hpp:267
El find_element(const char *symbol)
Definition elem.hpp:274
GEMMI_DLL Op parse_triplet(const std::string &s, char notation=' ')
void split_element_and_charge(const std::string &label, T *dest)
Definition small.hpp:214
GroupOps symops_from_hall(const char *hall)
Definition symmetry.hpp:564
const SpaceGroup * find_spacegroup_by_number(int ccp4) noexcept
Definition symmetry.hpp:852
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...
GroupOps split_centering_vectors(const std::vector< Op > &ops)
Definition symmetry.hpp:545
std::vector< Op > triplets_to_ops(const std::vector< std::string > &symops)
Definition small.hpp:30
void cat_to(std::string &)
Definition util.hpp:26
const SpaceGroup * find_spacegroup_by_ops(const GroupOps &gops)
Definition symmetry.hpp:897
bool is_complete(const GroupOps &gops)
Definition small.hpp:22
bool is_hydrogen() const
Definition elem.hpp:310
const char * name() const
Definition elem.hpp:316
Like Transform, but apply() arg is Fractional (not Vec3 - for type safety).
Definition unitcell.hpp:112
Fractional coordinates.
Definition unitcell.hpp:50
Op * find_by_rotation(const Op::Rot &r)
Definition symmetry.hpp:293
std::vector< Op > sym_ops
Definition symmetry.hpp:255
int order() const
Definition symmetry.hpp:258
std::vector< Op > all_ops_sorted() const
Definition symmetry.hpp:393
Coordinates in Angstroms - orthogonal (Cartesian) coordinates.
Definition unitcell.hpp:32
SMat33< double > aniso
Definition small.hpp:45
Position orth(const gemmi::UnitCell &cell_) const
Definition small.hpp:50
std::string element_and_charge_symbol() const
Definition small.hpp:54
std::string spacegroup_hm
Definition small.hpp:75
std::vector< Site > get_all_unit_cell_sites() const
Definition small.hpp:228
const SpaceGroup * spacegroup
Definition small.hpp:74
std::vector< Site > sites
Definition small.hpp:79
std::vector< AtomType > atom_types
Definition small.hpp:80
std::string check_spacegroup() const
Definition small.hpp:133
void change_occupancies_to_crystallographic(double max_dist=0.4)
Definition small.hpp:200
void determine_and_set_spacegroup(const char *order)
Definition small.hpp:85
std::string name
Definition small.hpp:72
const AtomType * get_atom_type(const std::string &symbol) const
Definition small.hpp:179
std::bitset<(size_t) El::END > present_elements() const
Definition small.hpp:187
const SpaceGroup * determine_spacegroup_from(char c, GroupOps &gops) const
Definition small.hpp:106
std::string spacegroup_hall
Definition small.hpp:76
std::vector< std::string > symops
Definition small.hpp:78
Unit cell.
Definition unitcell.hpp:165
Position orthogonalize(const Fractional &f) const
Definition unitcell.hpp:391
void set_cell_images_from_groupops(const GroupOps &group_ops)
Definition unitcell.hpp:354
std::vector< FTransform > images
Definition unitcell.hpp:181
void set_cell_images_from_spacegroup(const SpaceGroup *sg)
Definition unitcell.hpp:363
int is_special_position(const Fractional &fpos, double max_dist) const
Counts nearby symmetry mates (0 = none, 3 = 4-fold axis, etc).
Definition unitcell.hpp:547
Crystallographic Symmetry. Space Groups. Coordinate Triplets.
Unit cell.
Utilities. Mostly for working with strings and vectors.