Gemmi C++ API
Loading...
Searching...
No Matches
unitcell.hpp
Go to the documentation of this file.
1// Copyright 2017 Global Phasing Ltd.
2//
3// Unit cell.
4
5#ifndef GEMMI_UNITCELL_HPP_
6#define GEMMI_UNITCELL_HPP_
7
8#include <cassert>
9#include <cmath> // for cos, sin, sqrt, floor, NAN
10#include <vector>
11#include "math.hpp"
12#include "fail.hpp" // for fail
13#include "symmetry.hpp" // for Op, SpaceGroup
14
15namespace gemmi {
16
17inline Mat33 rot_as_mat33(const Op::Rot& rot) {
18 double mult = 1.0 / Op::DEN;
19 return Mat33(mult * rot[0][0], mult * rot[0][1], mult * rot[0][2],
20 mult * rot[1][0], mult * rot[1][1], mult * rot[1][2],
21 mult * rot[2][0], mult * rot[2][1], mult * rot[2][2]);
22}
23inline Mat33 rot_as_mat33(const Op& op) { return rot_as_mat33(op.rot); }
24
25
26inline Vec3 tran_as_vec3(const Op& op) {
27 double mult = 1.0 / Op::DEN;
28 return Vec3(mult * op.tran[0], mult * op.tran[1], mult * op.tran[2]);
29}
30
32struct Position : Vec3 {
33 using Vec3::Vec3;
34 Position() = default;
35 explicit Position(const Vec3& v) : Vec3(v) {}
36 Position operator-() const { return Position(Vec3::operator-()); }
37 Position operator-(const Position& o) const { return Position(Vec3::operator-(o)); }
38 Position operator+(const Position& o) const { return Position(Vec3::operator+(o)); }
39 Position operator*(double d) const { return Position(Vec3::operator*(d)); }
40 Position operator/(double d) const { return Position(Vec3::operator/(d)); }
41 Position& operator-=(const Position& o) { *this = *this - o; return *this; }
42 Position& operator+=(const Position& o) { *this = *this + o; return *this; }
43 Position& operator*=(double d) { *this = *this * d; return *this; }
44 Position& operator/=(double d) { return operator*=(1.0/d); }
45};
46
47inline Position operator*(double d, const Position& v) { return v * d; }
48
50struct Fractional : Vec3 {
51 using Vec3::Vec3;
52 Fractional() = default;
53 explicit Fractional(const Vec3& v) : Vec3(v) {}
55 return Fractional(Vec3::operator-(o));
56 }
58 return Fractional(Vec3::operator+(o));
59 }
61 return {x - std::floor(x), y - std::floor(y), z - std::floor(z)};
62 }
64 return {x - std::round(x), y - std::round(y), z - std::round(z)};
65 }
66 Fractional round() const {
67 return {std::round(x), std::round(y), std::round(z)};
68 }
70 if (x > 0.5) x -= 1.0; else if (x < -0.5) x += 1.0;
71 if (y > 0.5) y -= 1.0; else if (y < -0.5) y += 1.0;
72 if (z > 0.5) z -= 1.0; else if (z < -0.5) z += 1.0;
73 }
74};
75
76enum class Asu : unsigned char { Same, Different, Any };
77
80 double dist_sq;
81 int pbc_shift[3] = { 0, 0, 0 };
82 int sym_idx = 0;
83
84 double dist() const { return std::sqrt(dist_sq); }
85 bool same_asu() const {
86 return pbc_shift[0] == 0 && pbc_shift[1] == 0 && pbc_shift[2] == 0 && sym_idx == 0;
87 }
88
90 std::string symmetry_code(bool underscore) const {
91 std::string s = std::to_string(sym_idx + 1);
92 if (underscore)
93 s += '_';
94 if (unsigned(5 + pbc_shift[0]) <= 9 &&
95 unsigned(5 + pbc_shift[1]) <= 9 &&
96 unsigned(5 + pbc_shift[2]) <= 9) { // normal, quick path
97 for (int shift : pbc_shift)
98 s += char('5' + shift);
99 } else { // problematic, non-standard path
100 for (int i = 0; i < 3; ++i) {
101 if (i != 0 && underscore)
102 s += '_';
103 s += std::to_string(5 + pbc_shift[i]);
104 }
105 }
106 return s;
107 }
108};
109
110
114 Fractional apply(const Fractional& p) const {
116 }
117};
118
120struct NcsOp {
121 std::string id;
122 bool given;
124 Position apply(const Position& p) const { return Position(tr.apply(p)); }
125};
126
128using Miller = std::array<int, 3>;
129
131 std::size_t operator()(const Miller& hkl) const noexcept {
132 return std::size_t((hkl[0] * 1024 + hkl[1]) * 1024 + hkl[2]);
133 }
134};
135
139struct UnitCell {
140 UnitCell() = default;
141 UnitCell(double a_, double b_, double c_,
142 double alpha_, double beta_, double gamma_) {
143 set(a_, b_, c_, alpha_, beta_, gamma_);
144 }
145 UnitCell(const std::array<double, 6>& v) {
146 set(v[0], v[1], v[2], v[3], v[4], v[5]);
147 }
148 double a = 1.0, b = 1.0, c = 1.0;
149 double alpha = 90.0, beta = 90.0, gamma = 90.0;
152 double volume = 1.0;
154 double ar = 1.0, br = 1.0, cr = 1.0;
155 double cos_alphar = 0.0, cos_betar = 0.0, cos_gammar = 0.0;
156 bool explicit_matrices = false;
157 short cs_count = 0; // crystallographic symmetries except identity
158 std::vector<FTransform> images; // symmetry operations
159
160 // Non-crystalline (for example NMR) structures are supposed to use fake
161 // unit cell 1x1x1, but sometimes they don't. A number of non-crystalline
162 // entries in the PDB has incorrectly set unit cell or fract. matrix,
163 // that is why we check both.
164 bool is_crystal() const { return a != 1.0 && frac.mat[0][0] != 1.0; }
165
166 bool operator==(const UnitCell& o) const {
167 return a == o.a && b == o.b && c == o.c &&
168 alpha == o.alpha && beta == o.beta && gamma == o.gamma;
169 }
170 bool operator!=(const UnitCell& o) const { return !operator==(o); }
171
172 bool approx(const UnitCell& o, double epsilon) const {
173 auto eq = [&](double x, double y) { return std::fabs(x - y) < epsilon; };
174 return eq(a, o.a) && eq(b, o.b) && eq(c, o.c) &&
175 eq(alpha, o.alpha) && eq(beta, o.beta) && eq(gamma, o.gamma);
176 }
177
178 // compare lengths using relative tolerance rel, angles using tolerance deg
179 bool is_similar(const UnitCell& o, double rel, double deg) const {
180 auto siml = [&](double x, double y) { return std::fabs(x - y) < rel * std::max(x, y); };
181 auto sima = [&](double x, double y) { return std::fabs(x - y) < deg; };
182 return siml(a, o.a) && siml(b, o.b) && siml(c, o.c) &&
183 sima(alpha, o.alpha) && sima(beta, o.beta) && sima(gamma, o.gamma);
184 }
185
187 // ensure exact values for right angles
188 double cos_alpha = alpha == 90. ? 0. : std::cos(rad(alpha));
189 double cos_beta = beta == 90. ? 0. : std::cos(rad(beta));
190 double cos_gamma = gamma == 90. ? 0. : std::cos(rad(gamma));
191 double sin_alpha = alpha == 90. ? 1. : std::sin(rad(alpha));
192 double sin_beta = beta == 90. ? 1. : std::sin(rad(beta));
193 double sin_gamma = gamma == 90. ? 1. : std::sin(rad(gamma));
194 if (sin_alpha == 0 || sin_beta == 0 || sin_gamma == 0)
195 fail("Impossible angle - N*180deg.");
196
197 // volume - formula from Giacovazzo p.62
198 volume = a * b * c * std::sqrt(1 - cos_alpha * cos_alpha
200 + 2 * cos_alpha * cos_beta * cos_gamma);
201
202 // reciprocal parameters a*, b*, ... (Giacovazzo, p. 64)
203 ar = b * c * sin_alpha / volume;
204 br = a * c * sin_beta / volume;
205 cr = a * b * sin_gamma / volume;
208 //cos_alphar = (cos_beta * cos_gamma - cos_alpha) / (sin_beta * sin_gamma);
211
213 return;
214
215 // The orthogonalization matrix we use is described in ITfC B p.262:
216 // "An alternative mode of orthogonalization, used by the Protein
217 // Data Bank and most programs, is to align the a1 axis of the unit
218 // cell with the Cartesian X_1 axis, and to align the a*_3 axis with the
219 // Cartesian X_3 axis."
220 double sin_alphar = std::sqrt(1.0 - cos_alphar * cos_alphar);
221 orth.mat = {a, b * cos_gamma, c * cos_beta,
223 0., 0. , c * sin_beta * sin_alphar};
224 orth.vec = {0., 0., 0.};
225
226 double o12 = -cos_gamma / (sin_gamma * a);
228 / (sin_alphar * sin_beta * sin_gamma * a);
229 double o23 = cos_alphar / (sin_alphar * sin_gamma * b);
230 frac.mat = {1 / a, o12, o13,
231 0., 1 / orth.mat[1][1], o23,
232 0., 0., 1 / orth.mat[2][2]};
233 frac.vec = {0., 0., 0.};
234 }
235
236 double cos_alpha() const { return alpha == 90. ? 0. : std::cos(rad(alpha)); }
237
241 double sin_gammar = std::sqrt(1 - cos_gammar * cos_gammar);
242 double sin_betar = std::sqrt(1 - cos_betar * cos_betar);
243 return Mat33(ar, br * cos_gammar, cr * cos_betar,
244 0., br * sin_gammar, -cr * sin_betar * cos_alpha(),
245 0., 0., 1.0 / c);
246 }
247
252 double calculate_u_eq(const SMat33<double>& ani) const {
253 double aar = a * ar;
254 double bbr = b * br;
255 double ccr = c * cr;
256 // it could be optimized using orth.mat[0][1] and orth.mat[0][2]
257 double cos_beta = beta == 90. ? 0. : std::cos(rad(beta));
258 double cos_gamma = gamma == 90. ? 0. : std::cos(rad(gamma));
259 return 1/3. * (sq(aar) * ani.u11 + sq(bbr) * ani.u22 + sq(ccr) * ani.u33 +
260 2 * (aar * bbr * cos_gamma * ani.u12 +
261 aar * ccr * cos_beta * ani.u13 +
262 bbr * ccr * cos_alpha() * ani.u23));
263 }
264
266 // mmCIF _atom_sites.fract_transf_* and PDB SCALEn records usually contain
267 // fewer significant digits than the unit cell parameters, and sometimes are
268 // just wrong. Use them only if we seem to have non-standard crystal frame.
269 if (f.mat.approx(frac.mat, 1e-4) && f.vec.approx(frac.vec, 1e-6))
270 return;
271 // The SCALE record is sometimes incorrect. Here we only catch cases
272 // when CRYST1 is set as for non-crystal and SCALE is very suspicious.
273 if (frac.mat[0][0] == 1.0 && (f.mat[0][0] == 0.0 || f.mat[0][0] > 1.0))
274 return;
275 frac = f;
276 orth = f.inverse();
277 explicit_matrices = true;
278 }
279
280 void set(double a_, double b_, double c_,
281 double alpha_, double beta_, double gamma_) {
282 if (gamma_ == 0.0) // ignore empty/partial CRYST1 (example: 3iyp)
283 return;
284 a = a_;
285 b = b_;
286 c = c_;
287 alpha = alpha_;
288 beta = beta_;
289 gamma = gamma_;
291 }
292
293 void set_from_vectors(const Vec3& va, const Vec3& vb, const Vec3& vc) {
294 set(va.length(), vb.length(), vc.length(),
295 deg(vb.angle(vc)), deg(vc.angle(va)), deg(va.angle(vb)));
296 }
297
301 new_cell.set_from_vectors(mat.column_copy(0),
302 mat.column_copy(1),
303 mat.column_copy(2));
304 if (set_images && !images.empty()) {
305 new_cell.images.reserve(images.size());
307 Transform tr_inv = tr.inverse();
308 for (const FTransform& im : images)
309 new_cell.images.push_back(tr.combine(im).combine(tr_inv));
310 }
311 return new_cell;
312 }
313
317
318 bool is_compatible_with_groupops(const GroupOps& gops, double eps=1e-3) {
319 std::array<double,6> metric = metric_tensor().elements_voigt();
320 for (const Op& op : gops.sym_ops) {
322 std::array<double,6> other = {{
323 m.column_dot(0,0), m.column_dot(1,1), m.column_dot(2,2),
324 m.column_dot(1,2), m.column_dot(0,2), m.column_dot(0,1)
325 }};
326 for (int i = 0; i < 6; ++i)
327 if (std::fabs(metric[i] - other[i]) > eps)
328 return false;
329 }
330 return true;
331 }
332
334 return sg ? is_compatible_with_groupops(sg->operations(), eps) : false;
335 }
336
338 images.clear();
339 cs_count = 0;
340 if (!sg)
341 return;
342 GroupOps group_ops = sg->operations();
343 cs_count = (short) group_ops.order() - 1;
344 images.reserve(cs_count);
345 for (Op op : group_ops) {
346 if (op == Op::identity())
347 continue;
348 images.push_back(Transform{rot_as_mat33(op), tran_as_vec3(op)});
349 }
350 }
351
352 void add_ncs_images_to_cs_images(const std::vector<NcsOp>& ncs) {
353 assert(cs_count == (short) images.size());
354 for (const NcsOp& ncs_op : ncs)
355 if (!ncs_op.given) {
356 // We need it to operates on fractional, not orthogonal coordinates.
357 FTransform f = frac.combine(ncs_op.tr.combine(orth));
358 images.emplace_back(f);
359 for (int i = 0; i < cs_count; ++i)
360 images.emplace_back(images[i].combine(f));
361 }
362 }
363
364 std::vector<FTransform> get_ncs_transforms() const {
365 std::vector<FTransform> ncs;
366 for (size_t n = cs_count; n < images.size(); n += cs_count + 1)
367 ncs.push_back(images[n]);
368 return ncs;
369 }
370
372 return Position(orth.apply(f));
373 }
375 return Fractional(frac.apply(o));
376 }
377
379 // The shift (fract.vec) can be non-zero in non-standard settings,
380 // just do not apply it here.
388
393 r.minimum = orthogonalize(f.minimum);
394 r.maximum = orthogonalize(f.maximum);
395 if (alpha != 90. || beta == 90. || gamma == 90.) {
396 r.extend(orthogonalize({f.minimum.x, f.minimum.y, f.maximum.z}));
397 r.extend(orthogonalize({f.minimum.x, f.maximum.y, f.maximum.z}));
398 r.extend(orthogonalize({f.minimum.x, f.maximum.y, f.minimum.z}));
399 r.extend(orthogonalize({f.maximum.x, f.maximum.y, f.minimum.z}));
400 r.extend(orthogonalize({f.maximum.x, f.minimum.y, f.minimum.z}));
401 r.extend(orthogonalize({f.maximum.x, f.minimum.y, f.maximum.z}));
402 }
403 return r;
404 }
405
406 Transform op_as_transform(const Op& op) const {
408 return orth.combine(frac_tr.combine(frac));
409 }
410
411 double distance_sq(const Fractional& pos1, const Fractional& pos2) const {
412 Fractional diff = (pos1 - pos2).wrap_to_zero();
413 return orthogonalize_difference(diff).length_sq();
414 }
415 double distance_sq(const Position& pos1, const Position& pos2) const {
417 }
418
419 double volume_per_image() const {
420 return is_crystal() ? volume / (1 + images.size()) : NAN;
421 }
422
423 // Helper function. PBC = periodic boundary conditions.
425 int neg_shift[3] = {0, 0, 0};
426 if (is_crystal()) {
427 for (int j = 0; j < 3; ++j)
428 neg_shift[j] = iround(diff.at(j));
429 diff.x -= neg_shift[0];
430 diff.y -= neg_shift[1];
431 diff.z -= neg_shift[2];
432 }
434 double dsq = orth_diff.length_sq();
435 if (dsq < image.dist_sq) {
436 image.dist_sq = dsq;
437 for (int j = 0; j < 3; ++j)
438 image.pbc_shift[j] = -neg_shift[j];
439 return true;
440 }
441 return false;
442 }
443
444 NearestImage find_nearest_image(const Position& ref, const Position& pos, Asu asu) const {
446 if (asu == Asu::Different)
447 image.dist_sq = INFINITY;
448 else
449 image.dist_sq = ref.dist_sq(pos);
450 if (asu == Asu::Same)
451 return image;
455 if (asu == Asu::Different &&
456 image.pbc_shift[0] == 0 && image.pbc_shift[1] == 0 && image.pbc_shift[2] == 0)
457 image.dist_sq = INFINITY;
458 for (int n = 0; n != static_cast<int>(images.size()); ++n)
459 if (search_pbc_images(images[n].apply(fpos) - fref, image))
460 image.sym_idx = n + 1;
461 return image;
462 }
463
464 void apply_transform(Fractional& fpos, int image_idx, bool inverse) const {
465 if (image_idx > 0) {
466 const FTransform& t = images.at(image_idx - 1);
467 if (!inverse)
468 fpos = t.apply(fpos);
469 else
470 fpos = FTransform(t.inverse()).apply(fpos);
471 }
472 }
473
475 int image_idx) const {
477 sym_image.dist_sq = INFINITY;
478 sym_image.sym_idx = image_idx;
479 apply_transform(fpos, image_idx, false);
481 return sym_image;
482 }
484 int image_idx) const {
485 return find_nearest_pbc_image(fractionalize(ref), fractionalize(pos), image_idx);
486 }
487
489 const Fractional& fpos) const {
491 return orthogonalize_difference((fpos - fref).wrap_to_zero()) + ref;
492 }
493
495 int image_idx, bool inverse=false) const {
497 apply_transform(fpos, image_idx, inverse);
498 return orthogonalize_in_pbc(ref, fpos);
499 }
500
503 int is_special_position(const Fractional& fpos, double max_dist) const {
504 const double max_dist_sq = max_dist * max_dist;
505 int n = 0;
506 for (const FTransform& image : images) {
507 Fractional fdiff = (image.apply(fpos) - fpos).wrap_to_zero();
508 if (orthogonalize_difference(fdiff).length_sq() < max_dist_sq)
509 ++n;
510 }
511 return n;
512 }
513 int is_special_position(const Position& pos, double max_dist = 0.8) const {
515 }
516
519 // The indices are integers, but they may be stored as floating-point
520 // numbers (MTZ format) so we use double to avoid conversions.
521 double calculate_1_d2_double(double h, double k, double l) const {
522 double arh = ar * h;
523 double brk = br * k;
524 double crl = cr * l;
525 return arh * arh + brk * brk + crl * crl + 2 * (arh * brk * cos_gammar +
526 arh * crl * cos_betar +
527 brk * crl * cos_alphar);
528 }
529 double calculate_1_d2(const Miller& hkl) const {
530 return calculate_1_d2_double(hkl[0], hkl[1], hkl[2]);
531 }
532
535 double calculate_d(const Miller& hkl) const {
536 return 1.0 / std::sqrt(calculate_1_d2(hkl));
537 }
538
540 double calculate_stol_sq(const Miller& hkl) const {
541 return 0.25 * calculate_1_d2(hkl);
542 }
543
546 // the order in SMat33 is ... m12 m13 m23 -> a.a b.b c.c a.b a.c b.c
547 return {a*a, b*b, c*c, a*orth.mat[0][1], a*orth.mat[0][2], b*c*cos_alpha()};
548 }
549
553
556 auto acosd = [](double x) { return deg(std::acos(x)); };
557 return UnitCell(ar, br, cr,
559 }
560
561 Miller get_hkl_limits(double dmin) const {
562 return {{int(a / dmin), int(b / dmin), int(c / dmin)}};
563 }
564
565 Mat33 primitive_orth_matrix(char centring_type) const {
566 if (centring_type == 'P')
567 return orth.mat;
568 Mat33 c2p = rot_as_mat33(centred_to_primitive(centring_type));
569 return orth.mat.multiply(c2p);
570 }
571};
572
573} // namespace gemmi
574#endif
constexpr double deg(double angle)
Definition math.hpp:31
int iround(double d)
Definition math.hpp:37
Op::Rot centred_to_primitive(char centring_type)
std::array< int, 3 > Miller
A synonym for convenient passing of hkl.
Definition unitcell.hpp:128
Mat33 rot_as_mat33(const Op::Rot &rot)
Definition unitcell.hpp:17
Vec3 operator*(double d, const Vec3 &v)
Definition math.hpp:104
constexpr double rad(double angle)
Definition math.hpp:32
constexpr float sq(float x)
Definition math.hpp:34
Vec3_< double > Vec3
Definition math.hpp:101
void fail(const std::string &msg)
Definition fail.hpp:59
Vec3 tran_as_vec3(const Op &op)
Definition unitcell.hpp:26
Like Transform, but apply() arg is Fractional (not Vec3 - for type safety).
Definition unitcell.hpp:112
FTransform(const Transform &t)
Definition unitcell.hpp:113
Fractional apply(const Fractional &p) const
Definition unitcell.hpp:114
Fractional coordinates.
Definition unitcell.hpp:50
Fractional wrap_to_unit() const
Definition unitcell.hpp:60
void move_toward_zero_by_one()
Definition unitcell.hpp:69
Fractional(const Vec3 &v)
Definition unitcell.hpp:53
Fractional operator-(const Fractional &o) const
Definition unitcell.hpp:54
Fractional round() const
Definition unitcell.hpp:66
Fractional operator+(const Fractional &o) const
Definition unitcell.hpp:57
Fractional()=default
Fractional wrap_to_zero() const
Definition unitcell.hpp:63
std::vector< Op > sym_ops
Definition symmetry.hpp:438
Vec3 column_copy(int i) const
Definition math.hpp:139
bool approx(const Mat33 &other, double epsilon) const
Definition math.hpp:186
Vec3 multiply(const Vec3 &p) const
Definition math.hpp:156
std::size_t operator()(const Miller &hkl) const noexcept
Definition unitcell.hpp:131
Non-crystallographic symmetry operation (such as in the MTRIXn record)
Definition unitcell.hpp:120
std::string id
Definition unitcell.hpp:121
Transform tr
Definition unitcell.hpp:123
Position apply(const Position &p) const
Definition unitcell.hpp:124
Result of find_nearest_image.
Definition unitcell.hpp:79
std::string symmetry_code(bool underscore) const
Returns a string such as 1555 or 1_555.
Definition unitcell.hpp:90
double dist() const
Definition unitcell.hpp:84
bool same_asu() const
Definition unitcell.hpp:85
std::array< std::array< int, 3 >, 3 > Rot
Definition symmetry.hpp:55
Tran tran
Definition symmetry.hpp:59
static constexpr int DEN
Definition symmetry.hpp:54
Op inverse() const
Definition symmetry.hpp:196
static constexpr Op identity()
Definition symmetry.hpp:177
Coordinates in Angstroms - orthogonal (Cartesian) coordinates.
Definition unitcell.hpp:32
Position operator*(double d) const
Definition unitcell.hpp:39
Position operator/(double d) const
Definition unitcell.hpp:40
Position(const Vec3 &v)
Definition unitcell.hpp:35
Position()=default
Position & operator+=(const Position &o)
Definition unitcell.hpp:42
Position operator-(const Position &o) const
Definition unitcell.hpp:37
Position & operator*=(double d)
Definition unitcell.hpp:43
Position operator+(const Position &o) const
Definition unitcell.hpp:38
Position operator-() const
Definition unitcell.hpp:36
Position & operator-=(const Position &o)
Definition unitcell.hpp:41
Position & operator/=(double d)
Definition unitcell.hpp:44
std::array< T, 6 > elements_voigt() const
Definition math.hpp:266
Vec3 apply(const Vec3 &x) const
Definition math.hpp:380
Transform combine(const Transform &b) const
Definition math.hpp:382
Transform inverse() const
Definition math.hpp:375
Unit cell.
Definition unitcell.hpp:139
double calculate_d(const Miller &hkl) const
Calculate d-spacing.
Definition unitcell.hpp:535
double distance_sq(const Fractional &pos1, const Fractional &pos2) const
Definition unitcell.hpp:411
NearestImage find_nearest_image(const Position &ref, const Position &pos, Asu asu) const
Definition unitcell.hpp:444
UnitCell changed_basis_backward(const Op &op, bool set_images)
Definition unitcell.hpp:298
bool operator==(const UnitCell &o) const
Definition unitcell.hpp:166
Transform frac
Definition unitcell.hpp:151
std::vector< FTransform > get_ncs_transforms() const
Definition unitcell.hpp:364
UnitCell reciprocal() const
Returns reciprocal unit cell.
Definition unitcell.hpp:555
UnitCell(const std::array< double, 6 > &v)
Definition unitcell.hpp:145
UnitCell()=default
double calculate_u_eq(const SMat33< double > &ani) const
The equivalent isotropic displacement factor.
Definition unitcell.hpp:252
Position find_nearest_pbc_position(const Position &ref, const Position &pos, int image_idx, bool inverse=false) const
Definition unitcell.hpp:494
void calculate_properties()
Definition unitcell.hpp:186
SMat33< double > metric_tensor() const
https://dictionary.iucr.org/Metric_tensor
Definition unitcell.hpp:545
double ar
reciprocal parameters a*, b*, c*, alpha*, beta*, gamma*
Definition unitcell.hpp:154
Fractional fractionalize(const Position &o) const
Definition unitcell.hpp:374
double calculate_stol_sq(const Miller &hkl) const
Calculate (sin(theta)/lambda)^2 = d*^2/4.
Definition unitcell.hpp:540
NearestImage find_nearest_pbc_image(const Fractional &fref, Fractional fpos, int image_idx) const
Definition unitcell.hpp:474
void set_matrices_from_fract(const Transform &f)
Definition unitcell.hpp:265
double distance_sq(const Position &pos1, const Position &pos2) const
Definition unitcell.hpp:415
Transform op_as_transform(const Op &op) const
Definition unitcell.hpp:406
Mat33 calculate_matrix_B() const
B matrix following convention from Busing & Levy (1967), not from cctbx.
Definition unitcell.hpp:240
void set(double a_, double b_, double c_, double alpha_, double beta_, double gamma_)
Definition unitcell.hpp:280
UnitCell(double a_, double b_, double c_, double alpha_, double beta_, double gamma_)
Definition unitcell.hpp:141
bool is_compatible_with_groupops(const GroupOps &gops, double eps=1e-3)
Definition unitcell.hpp:318
Miller get_hkl_limits(double dmin) const
Definition unitcell.hpp:561
bool is_crystal() const
Definition unitcell.hpp:164
double cos_alpha() const
Definition unitcell.hpp:236
void apply_transform(Fractional &fpos, int image_idx, bool inverse) const
Definition unitcell.hpp:464
void set_from_vectors(const Vec3 &va, const Vec3 &vb, const Vec3 &vc)
Definition unitcell.hpp:293
Mat33 primitive_orth_matrix(char centring_type) const
Definition unitcell.hpp:565
Position orthogonalize(const Fractional &f) const
Definition unitcell.hpp:371
double volume_per_image() const
Definition unitcell.hpp:419
void add_ncs_images_to_cs_images(const std::vector< NcsOp > &ncs)
Definition unitcell.hpp:352
double calculate_1_d2_double(double h, double k, double l) const
Calculate 1/d^2 for specified hkl reflection.
Definition unitcell.hpp:521
NearestImage find_nearest_pbc_image(const Position &ref, const Position &pos, int image_idx) const
Definition unitcell.hpp:483
bool search_pbc_images(Fractional &&diff, NearestImage &image) const
Definition unitcell.hpp:424
UnitCell changed_basis_forward(const Op &op, bool set_images)
Definition unitcell.hpp:314
double calculate_1_d2(const Miller &hkl) const
Definition unitcell.hpp:529
std::vector< FTransform > images
Definition unitcell.hpp:158
Position orthogonalize_difference(const Fractional &delta) const
orthogonalize_difference(a-b) == orthogonalize(a) - orthogonalize(b)
Definition unitcell.hpp:381
bool is_compatible_with_spacegroup(const SpaceGroup *sg, double eps=1e-3)
Definition unitcell.hpp:333
void set_cell_images_from_spacegroup(const SpaceGroup *sg)
Definition unitcell.hpp:337
int is_special_position(const Position &pos, double max_dist=0.8) const
Definition unitcell.hpp:513
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:503
SMat33< double > reciprocal_metric_tensor() const
Definition unitcell.hpp:550
bool operator!=(const UnitCell &o) const
Definition unitcell.hpp:170
bool is_similar(const UnitCell &o, double rel, double deg) const
Definition unitcell.hpp:179
Box< Position > orthogonalize_box(const Box< Fractional > &f) const
Returns box containing fractional box (a cuboid in fractional coordinates can be a parallelepiped in ...
Definition unitcell.hpp:391
Fractional fractionalize_difference(const Position &delta) const
the inverse of orthogonalize_difference
Definition unitcell.hpp:385
Transform orth
Definition unitcell.hpp:150
Position orthogonalize_in_pbc(const Position &ref, const Fractional &fpos) const
Definition unitcell.hpp:488
bool approx(const UnitCell &o, double epsilon) const
Definition unitcell.hpp:172