8#ifndef GEMMI_SYMMETRY_HPP_
9#define GEMMI_SYMMETRY_HPP_
31 static constexpr int DEN = 24;
32 typedef std::array<std::array<int, 3>, 3>
Rot;
33 typedef std::array<int, 3>
Tran;
39 bool is_hkl()
const {
return notation ==
'h'; }
42 return is_hkl() ? *
this :
Op{rot, {0,0,0},
'h'};
45 return is_hkl() ?
Op{rot, {0,0,0},
'x'} : *
this;
54 for (
int i = 0;
i != 3; ++
i) {
58 t[
i] = ((
t[
i] + 1) % DEN) + DEN - 1;
65 tran = wrapped_tran();
70 for (
int i = 0;
i != 3; ++
i)
80 return {{{-rot[0][0], -rot[0][1], -rot[0][2]},
81 {-rot[1][0], -rot[1][1], -rot[1][2]},
82 {-rot[2][0], -rot[2][1], -rot[2][2]}}};
86 return {{{rot[0][0], rot[1][0], rot[2][0]},
87 {rot[0][1], rot[1][1], rot[2][1]},
88 {rot[0][2], rot[1][2], rot[2][2]}}};
94 return rot[0][0] * (rot[1][1] * rot[2][2] - rot[1][2] * rot[2][1])
95 - rot[0][1] * (rot[1][0] * rot[2][2] - rot[1][2] * rot[2][0])
96 + rot[0][2] * (rot[1][0] * rot[2][1] - rot[1][1] * rot[2][0]);
102 int tr_den = rot[0][0] + rot[1][1] + rot[2][2];
104 const int table[] = {0, 0, 2, 3, 4, 6, 1};
105 if (std::abs(
det) == DEN * DEN * DEN && tr * DEN ==
tr_den && std::abs(tr) <= 3)
106 return det > 0 ? table[3 + tr] : -table[3 - tr];
111 if (is_hkl() != b.
is_hkl())
112 fail(
"can't combine real- and reciprocal-space Op");
114 for (
int i = 0;
i != 3; ++
i) {
115 r.tran[
i] = tran[
i] * Op::DEN;
116 for (
int j = 0;
j != 3; ++
j) {
117 r.rot[
i][
j] = (rot[
i][0] * b.
rot[0][
j] +
118 rot[
i][1] * b.
rot[1][
j] +
119 rot[
i][2] * b.
rot[2][
j]) / Op::DEN;
122 r.tran[
i] /= Op::DEN;
124 r.notation = notation;
128 std::array<double, 3>
apply_to_xyz(
const std::array<double, 3>& xyz)
const {
130 fail(
"can't apply reciprocal-space Op to xyz");
131 std::array<double, 3>
out;
132 for (
int i = 0;
i != 3; ++
i)
133 out[
i] = (rot[
i][0] * xyz[0] + rot[
i][1] * xyz[1] + rot[
i][2] * xyz[2] +
143 for (
int i = 0;
i != 3; ++
i)
144 r[
i] = (rot[0][
i] * hkl[0] + rot[1][
i] * hkl[1] + rot[2][
i] * hkl[2]);
148 return {{ hkl[0] / DEN, hkl[1] / DEN, hkl[2] / DEN }};
151 return divide_hkl_by_DEN(apply_to_hkl_without_division(hkl));
155 constexpr double mult = -2 * 3.1415926535897932384626433832795 / Op::DEN;
156 return mult * (hkl[0] * tran[0] + hkl[1] * tran[1] + hkl[2] * tran[2]);
160 std::array<std::array<int, 4>, 4>
t;
161 for (
int i = 0;
i < 3; ++
i)
162 t[
i] = { rot[
i][0], rot[
i][1], rot[
i][2], tran[
i] };
163 t[3] = { 0, 0, 0, 1 };
168 std::array<std::array<double, 4>, 4>
t;
169 double m = 1.0 / Op::DEN;
170 for (
int i = 0;
i < 3; ++
i)
171 t[
i] = {
m * rot[
i][0],
m * rot[
i][1],
m * rot[
i][2],
m * tran[
i] };
172 t[3] = { 0., 0., 0., 1. };
177 return {{{{DEN,0,0}, {0,DEN,0}, {0,0,DEN}}}, {0,0,0},
' '};
180 return {{{-DEN,0,0}, {0,-DEN,0}, {0,0,-DEN}}};
183 return std::tie(rot, tran) < std::tie(
rhs.rot,
rhs.tran);
210 for (
int i = 0;
i != 3; ++
i)
235 constexpr int d = 2 *
t;
237 switch (centring_type & ~0x20) {
238 case 'P':
return {{0, 0, 0}};
239 case 'A':
return {{0, 0, 0}, {0,
h,
h}};
240 case 'B':
return {{0, 0, 0}, {
h, 0,
h}};
241 case 'C':
return {{0, 0, 0}, {
h,
h, 0}};
242 case 'I':
return {{0, 0, 0}, {
h,
h,
h}};
243 case 'R':
return {{0, 0, 0}, {
d,
t,
t}, {
t,
d,
d}};
245 case 'H':
return {{0, 0, 0}, {
d,
t, 0}, {
t,
d, 0}};
246 case 'S':
return {{0, 0, 0}, {
t,
t,
d}, {
d,
t,
d}};
247 case 'T':
return {{0, 0, 0}, {
t,
d,
t}, {
d,
t,
d}};
248 case 'F':
return {{0, 0, 0}, {0,
h,
h}, {
h, 0,
h}, {
h,
h, 0}};
249 default:
fail(
"not a centring type: ", centring_type);
273 sym_ops.push_back({
neg, op.tran, op.notation});
283 for (
char c : {
'A',
'B',
'C',
'I',
'F',
'R',
'H',
'S',
'T'}) {
285 if (c ==
'R' || c ==
'H')
311 if (op.apply_to_hkl_without_division(hkl) ==
mhkl)
320 if (op.apply_to_hkl_without_division(hkl) ==
denh)
329 return (hkl[0] * c[0] + hkl[1] * c[1] + hkl[2] * c[2]) %
Op::DEN != 0;
338 if (op->apply_to_hkl_without_division(hkl) ==
denh) {
342 op->tran[2] + c[2]}}, hkl))
355 *op =
cob.combine(*op).combine(
inv).wrap();
378 *tr =
cob.combine(
cvec).combine(
inv).wrap().tran;
382 for (
int i =
static_cast<int>(
cen_ops.size()) - 1; i > 0; --i)
383 for (
int j = i - 1; j >= 0; --j)
395 ops.reserve(sym_ops.size() * cen_ops.size());
396 for (
const Op&
so : sym_ops)
398 ops.push_back(
so.add_centering(
co));
399 std::sort(
ops.begin(),
ops.end());
404 int n_cen = n / (
int) sym_ops.size();
405 int n_sym = n % (
int) sym_ops.size();
406 return sym_ops.at(n_sym).add_centering(cen_ops.at(n_cen));
410 if (cen_ops.size() != other.
cen_ops.size() ||
411 sym_ops.size() != other.
sym_ops.size())
417 if (cen_ops.size() != other.
cen_ops.size())
419 if (std::is_sorted(cen_ops.begin(), cen_ops.end()) &&
421 return cen_ops == other.
cen_ops;
422 std::vector<Op::Tran>
v1 = cen_ops;
423 std::vector<Op::Tran>
v2 = other.
cen_ops;
424 std::sort(
v1.begin(),
v1.end());
425 std::sort(
v2.begin(),
v2.end());
430 if (sym_ops.size() != other.
sym_ops.size())
433 std::vector<Op::Rot>
r(
g.sym_ops.size());
434 for (
size_t i = 0;
i !=
r.size(); ++
i)
435 r[
i] =
g.sym_ops[
i].rot;
436 std::sort(
r.begin(),
r.end());
446 int r[3] = {
T,
T,
T};
448 for (
int i = 0;
i != 3; ++
i)
449 if (op.tran[
i] != 0 && op.tran[
i] <
r[
i])
451 return {
T /
r[0],
T /
r[1],
T /
r[2]};
455 for (
const Op& op : sym_ops)
456 if (op.rot[u][v] != 0)
464 for (
Op& op :
r.sym_ops)
465 op.tran[0] = op.tran[1] = op.tran[2] = 0;
473 if (++n_sym == (
int) gops.
sym_ops.size()) {
479 return gops.
sym_ops.at(n_sym).translated(gops.
cen_ops.at(n_cen)).wrap();
482 return n_sym == other.
n_sym && n_cen == other.
n_cen;
488 Iter end()
const {
return {*
this, 0, (
int) cen_ops.size()}; }
491inline void GroupOps::add_missing_elements() {
493 if (sym_ops.empty() || sym_ops[0] != Op::identity())
495 if (sym_ops.size() == 1)
501 std::vector<Op>
gen(sym_ops.begin() + 1, sym_ops.end());
504 for (
Op g = sym_ops[1] * sym_ops[1];
g.rot !=
idrot;
g *= sym_ops[1]) {
505 sym_ops.push_back(
g);
507 fail(
"Too many elements in the group - bad generators");
513inline void GroupOps::add_missing_elements_part2(
const std::vector<Op>&
gen,
515 for (
size_t i = 1;
i <
gen.size(); ++
i) {
516 std::vector<Op>
coset_repr(1, Op::identity());
520 for (
size_t j = 0;
j != len; ++
j) {
521 for (
size_t n = 0; n !=
i + 1; ++n) {
523 if (find_by_rotation(
sg.rot) ==
nullptr) {
524 sym_ops.push_back(
sg);
526 sym_ops.push_back(
sg * sym_ops[
k]);
535 fail(
"Too many elements in the group - bad generators");
546 const Op identity = Op::identity();
548 go.sym_ops.push_back(identity);
549 for (
const Op& op :
ops)
550 if (
Op*
old_op =
go.find_by_rotation(op.rot)) {
552 if (op.rot == identity.
rot)
553 go.cen_ops.push_back(tran);
554 if (tran == identity.
tran)
557 go.sym_ops.push_back(op);
566 ops.add_missing_elements();
577 static const char*
names[7] = {
578 "triclinic",
"monoclinic",
"orthorhombic",
"tetragonal",
579 "trigonal",
"hexagonal",
"cubic"
585 C1=0,
Ci,
C2,
Cs,
C2h,
D2,
C2v,
D2h,
C4,
S4,
C4h,
D4,
C4v,
D2d,
D4h,
C3,
586 C3i,
D3,
C3v,
D3d,
C6,
C3h,
C6h,
D6,
C6v,
D3h,
D6h,
T,
Th,
O,
Td,
Oh
591 "1",
"-1",
"2",
"m",
"2/m",
"222",
"mm2",
"mmm",
592 "4",
"-4",
"4/m",
"422",
"4mm",
"-42m",
"4/mmm",
"3",
593 "-3",
"32",
"3m",
"-3m",
"6",
"-6",
"6/m",
"622",
594 "6mm",
"-62m",
"6/mmm",
"23",
"m-3",
"432",
"-43m",
"m-3m",
600enum class Laue :
unsigned char {
601 L1=0,
L2m,
Lmmm,
L4m,
L4mmm,
L3,
L3m,
L6m,
L6mmm,
Lm3,
Lm3m
607 Laue::L2m, Laue::L2m, Laue::L2m,
608 Laue::Lmmm, Laue::Lmmm, Laue::Lmmm,
609 Laue::L4m, Laue::L4m, Laue::L4m,
610 Laue::L4mmm, Laue::L4mmm, Laue::L4mmm, Laue::L4mmm,
612 Laue::L3m, Laue::L3m, Laue::L3m,
613 Laue::L6m, Laue::L6m, Laue::L6m,
614 Laue::L6mmm, Laue::L6mmm, Laue::L6mmm, Laue::L6mmm,
615 Laue::Lm3, Laue::Lm3,
616 Laue::Lm3m, Laue::Lm3m, Laue::Lm3m,
618 return laue[
static_cast<int>(
pg)];
624 PointGroup::Ci, PointGroup::C2h, PointGroup::D2h, PointGroup::C4h,
625 PointGroup::D4h, PointGroup::C3i, PointGroup::D3d, PointGroup::C6h,
626 PointGroup::D6h, PointGroup::Th, PointGroup::Oh
628 return pg[
static_cast<int>(
laue)];
637 CrystalSystem::Triclinic,
638 CrystalSystem::Monoclinic,
639 CrystalSystem::Orthorhombic,
640 CrystalSystem::Tetragonal, CrystalSystem::Tetragonal,
641 CrystalSystem::Trigonal, CrystalSystem::Trigonal,
642 CrystalSystem::Hexagonal, CrystalSystem::Hexagonal,
643 CrystalSystem::Cubic, CrystalSystem::Cubic
654 enum :
unsigned char {
S=0x20,
E=(0x20|0x40),
Y=0x80,
Z=(0x20|0x80) };
655 static const unsigned char indices[230] = {
656 0|
Z, 1|
Y, 2|
Z, 2|
S, 2|
Z, 3|
Y, 3, 3|
Y, 3, 4|
Y,
657 4, 4|
Y, 4, 4, 4, 5|
Z, 5|
S, 5|
S, 5|
S, 5|
S,
658 5|
Z, 5|
Z, 5|
Z, 5|
S, 6|
Y, 6, 6, 6, 6, 6,
659 6, 6, 6, 6, 6|
Y, 6, 6, 6|
Y, 6, 6,
660 6, 6|
Y, 6, 6|
Y, 6, 6, 7|
Y, 7, 7, 7,
661 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
662 7, 7, 7, 7, 7|
Y, 7, 7, 7, 7|
Y, 7,
663 7|
Y, 7, 7, 7, 8|
Z, 8|
E, 8|
S, 8|
E, 8|
Z, 8|
S,
664 9|
Y, 9|
Y, 10|
Y, 10, 10, 10, 10|
Y, 10, 11|
Z, 11|
S,
665 11|
E, 11|
E, 11|
S, 11|
S, 11|
E, 11|
E, 11|
Z, 11|
S, 12|
Y, 12,
666 12, 12, 12, 12, 12, 12, 12|
Y, 12, 12, 12,
667 13|
Y, 13, 13, 13, 13|
Y, 13, 13, 13, 13|
Y, 13,
668 13|
Y, 13, 14|
Y, 14, 14, 14, 14, 14, 14, 14,
669 14, 14, 14, 14, 14, 14, 14, 14, 14|
Y, 14,
670 14, 14, 15|
Z, 15|
E, 15|
E, 15|
Z, 16|
Y, 16|
Y, 17|
Z, 17|
Z,
671 17|
E, 17|
E, 17|
E, 17|
E, 17|
Z, 18|
Y, 18|
Y, 18, 18, 18|
Y,
672 18, 19|
Y, 19, 19|
Y, 19, 19|
Y, 19, 20|
Z, 20|
E, 20|
E,
673 20|
E, 20|
E, 20|
S, 21|
Y, 22|
Y, 22, 23|
Z, 23|
E, 23|
E, 23|
E,
674 23|
E, 23|
S, 24|
Y, 24, 24, 24, 25|
Y, 25, 25|
Y, 25,
675 26|
Y, 26, 26, 26, 27|
Z, 27|
Z, 27|
Z, 27|
S, 27|
S, 28|
Y,
676 28, 28|
Y, 28, 28|
Y, 28, 28, 29|
Z, 29|
S, 29|
Z, 29|
S,
677 29|
Z, 29|
E, 29|
E, 29|
S, 30|
Y, 30|
Y, 30|
Y, 30, 30, 30,
678 31|
Y, 31, 31, 31, 31|
Y, 31, 31, 31, 31|
Y, 31
708 constexpr int D = Op::DEN;
710 case 43:
return {
D/8,
D/8, 0};
711 case 80:
return {
D/4, 0, 0};
712 case 98:
return {
D/4, 0,
D/8};
713 case 109:
return {
D/4, 0, 0};
714 case 110:
return {
D/4, 0, 0};
715 case 122:
return {
D/4, 0,
D/8};
716 case 210:
return {
D/8,
D/8,
D/8};
717 default:
return {0, 0, 0};
727 constexpr int D = Op::DEN;
728 constexpr int H = Op::DEN / 2;
729 constexpr int T = Op::DEN / 3;
730 switch (centring_type) {
731 case 'P':
return {{{
D,0,0}, {0,
D,0}, {0,0,
D}}};
732 case 'A':
return {{{-
D,0,0}, {0,-
H,
H}, {0,
H,
H}}};
733 case 'B':
return {{{-
H,0,
H}, {0,-
D,0}, {
H,0,
H}}};
734 case 'C':
return {{{
H,
H,0}, {
H,-
H,0}, {0,0,-
D}}};
735 case 'I':
return {{{-
H,
H,
H}, {
H,-
H,
H}, {
H,
H,-
H}}};
736 case 'R':
return {{{2*
T,-
T,-
T}, {
T,
T,-2*
T}, {
T,
T,
T}}};
737 case 'H':
return {{{2*
T,-
T,0}, {
T,
T,0}, {0,0,
D}}};
738 case 'F':
return {{{0,
H,
H}, {
H,0,
H}, {
H,
H,0}}};
739 default:
fail(
"not a centring type: ", centring_type);
756 std::string
ret = hm;
772 size_t len = s.size();
773 if (len > 6 && s[2] ==
'1' && s[len - 2] ==
' ' && s[len - 1] ==
'1')
774 s = s[0] + s.substr(4, len - 4 - 2);
777 s.erase(std::remove(s.begin(), s.end(),
' '), s.end());
785 s += ccp4_lattice_type();
812 return qualifier[qualifier[0] ==
'-' ? 1 : 0];
826 if (is_centrosymmetric())
827 return Op::identity();
829 Op op{Op::inversion_rot(), {2*
t[0], 2*
t[1], 2*
t[2]},
'x'};
830 if (!is_reference_setting()) {
849 static const unsigned char ccp4_hkl_asu[230];
854 return &spacegroup_tables::main[0];
864 throw std::invalid_argument(
"Invalid space-group number: "
865 + std::to_string(ccp4));
871 if (
sg.number == number &&
sg.is_reference_setting())
873 throw std::invalid_argument(
"Invalid space-group number: "
874 + std::to_string(number));
883 double alpha=0.,
double gamma=0.,
884 const char*
prefer=
nullptr);
889 throw std::invalid_argument(
"Unknown space-group name: " + name);
894 return spacegroup_tables::main[0];
900 if ((c ==
sg.hall[0] || c ==
sg.hall[1]) &&
915 fail(
"Missing space group");
916 idx = spacegroup_tables::ccp4_hkl_asu[
sg->number - 1];
921 is_ref =
sg->is_reference_setting();
923 rot =
sg->basisop().rot;
929 return is_in_reference_setting(hkl[0], hkl[1], hkl[2]);
931 for (
int i = 0;
i != 3; ++
i)
932 r[
i] = rot[0][
i] * hkl[0] + rot[1][
i] * hkl[1] + rot[2][
i] * hkl[2];
933 return is_in_reference_setting(
r[0],
r[1],
r[2]);
939 case 0:
return l>0 || (
l==0 && (
h>0 || (
h==0 &&
k>=0)));
940 case 1:
return k>=0 && (
l>0 || (
l==0 &&
h>=0));
942 case 2:
return h>=0 &&
k>=0 &&
l>=0;
943 case 3:
return l>=0 && ((
h>=0 &&
k>0) || (
h==0 &&
k==0));
945 case 4:
return h>=
k &&
k>=0 &&
l>=0;
946 case 5:
return (
h>=0 &&
k>0) || (
h==0 &&
k==0 &&
l>=0);
948 case 6:
return h>=
k &&
k>=0 && (
k>0 ||
l>=0);
950 case 7:
return h>=
k &&
k>=0 && (
h>
k ||
l>=0);
951 case 8:
return h>=0 && ((
l>=
h &&
k>
h) || (
l==
h &&
k==
h));
952 case 9:
return k>=
l &&
l>=
h &&
h>=0;
953 case 10:
return k>0 || (
k==0 && (
h>0 || (
h==0 &&
l>=0)));
954 case 11:
return k>=0 && (
h>0 || (
h==0 &&
l>=0));
955 case 13:
return l>=0 && ((
k>=0 &&
h>0) || (
h==0 &&
k==0));
956 case 15:
return (
k>=0 &&
h>0) || (
h==0 &&
k==0 &&
l>=0);
957 case 18:
return k>=0 &&
l>=0 && ((
h>
k &&
h>
l) || (
h==
k &&
h>=
l));
958 case 19:
return h>=
k &&
k>=
l &&
l>=0;
965 case 0:
return "l>0 or (l=0 and (h>0 or (h=0 and k>=0)))";
966 case 1:
return "k>=0 and (l>0 or (l=0 and h>=0))";
968 case 2:
return "h>=0 and k>=0 and l>=0";
969 case 3:
return "l>=0 and ((h>=0 and k>0) or (h=0 and k=0))";
971 case 4:
return "h>=k and k>=0 and l>=0";
972 case 5:
return "(h>=0 and k>0) or (h=0 and k=0 and l>=0)";
974 case 6:
return "h>=k and k>=0 and (k>0 or l>=0)";
976 case 7:
return "h>=k and k>=0 and (h>k or l>=0)";
977 case 8:
return "h>=0 and ((l>=h and k>h) or (l=h and k=h))";
978 case 9:
return "k>=l and l>=h and h>=0";
979 case 10:
return "k>0 or (k==0 and (h>0 or (h=0 and l>=0)))";
980 case 11:
return "k>=0 and (h>0 or (h=0 and l>=0))";
981 case 13:
return "l>=0 and ((k>=0 and h>0) or (h=0 and k==0))";
982 case 15:
return "(k>=0 and h>0) or (h=0 and k==0 and l>=0)";
983 case 18:
return "k>=0 and l>=0 and ((h>k and h>l) or (h=k and h>=l))";
984 case 19:
return "h>=k and k>=l and l>=0";
991 std::pair<Op::Miller,int>
to_asu(
const Op::Miller& hkl,
const std::vector<Op>& sym_ops)
const {
993 for (
const Op& op : sym_ops) {
997 return {Op::divide_hkl_by_DEN(
new_hkl), isym};
1003 fail(
"Oops, maybe inconsistent GroupOps?");
1007 return to_asu(hkl, gops.
sym_ops);
1012 std::pair<Op::Miller,bool>
neg = {{0,0,0},
true};
1016 return {Op::divide_hkl_by_DEN(
new_hkl),
true};
1023 fail(
"Oops, maybe inconsistent GroupOps?");
1034 for (
int i = 0; i != 3; ++i)
1035 for (
int j = 0; j != 3; ++j)
1036 h = (h << 2) ^ (op.
rot[i][j] + 1);
1037 for (
int i = 0; i != 3; ++i)
1038 h = (h << 5) ^ op.
tran[i];
fail(), unreachable() and __declspec/__attribute__ macros
const SpaceGroup & get_spacegroup_p1()
GEMMI_DLL GroupOps generators_from_hall(const char *hall)
CrystalSystem crystal_system(Laue laue)
const SpaceGroup & get_spacegroup_reference_setting(int number)
GEMMI_DLL std::array< int, 4 > parse_triplet_part(const std::string &s, char ¬ation, double *decimal_fract=nullptr)
const SpaceGroup & get_spacegroup_by_name(const std::string &name)
unsigned char point_group_index_and_category(int space_group_number)
GEMMI_DLL Op parse_triplet(const std::string &s, char notation=' ')
const char * point_group_hm(PointGroup pg)
GEMMI_DLL void append_op_fraction(std::string &s, int w)
Op::Rot centred_to_primitive(char centring_type)
bool operator==(const Op &a, const Op &b)
GroupOps symops_from_hall(const char *hall)
PointGroup point_group(int space_group_number)
const SpaceGroup * find_spacegroup_by_number(int ccp4) noexcept
GEMMI_DLL Op seitz_to_op(const std::array< std::array< double, 4 >, 4 > &t)
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)
Vec3 operator*(double d, const Vec3 &v)
Laue pointgroup_to_laue(PointGroup pg)
GEMMI_DLL const char * get_basisop(int basisop_idx)
Op & operator*=(Op &a, const Op &b)
const SpaceGroup & get_spacegroup_by_number(int ccp4)
bool is_enantiomorphic(int space_group_number)
Op::Tran nonzero_inversion_center(int space_group_number)
Inversion center of the Euclidean normalizer that is not at the origin of reference settings.
std::vector< Op::Tran > centring_vectors(char centring_type)
const char * laue_class_str(Laue laue)
bool is_sohncke(int space_group_number)
void fail(const std::string &msg)
PointGroup laue_to_pointgroup(Laue laue)
const SpaceGroup * find_spacegroup_by_ops(const GroupOps &gops)
bool is_symmorphic(int space_group_number)
bool operator!=(const Op &a, const Op &b)
const char * crystal_system_str(CrystalSystem system)
bool operator==(const Iter &other) const
bool operator!=(const Iter &other) const
Op * find_by_rotation(const Op::Rot &r)
const Op * find_by_rotation(const Op::Rot &r) const
bool has_same_centring(const GroupOps &other) const
void change_basis_backward(const Op &inv)
std::vector< Op > sym_ops
bool is_systematically_absent(const Op::Miller &hkl) const
char find_centering() const
void add_missing_elements()
bool is_same_as(const GroupOps &other) const
void change_basis_forward(const Op &cob)
std::array< int, 3 > find_grid_factors() const
std::vector< Op::Tran > cen_ops
int epsilon_factor(const Op::Miller &hkl) const
void change_basis_impl(const Op &cob, const Op &inv)
bool is_centrosymmetric() const
void add_missing_elements_part2(const std::vector< Op > &gen, size_t max_size, bool ignore_bad_gen)
bool are_directions_symmetry_related(int u, int v) const
int epsilon_factor_without_centering(const Op::Miller &hkl) const
std::vector< Op > all_ops_sorted() const
bool has_same_rotations(const GroupOps &other) const
GroupOps derive_symmorphic() const
static bool has_phase_shift(const Op::Tran &c, const Op::Miller &hkl)
bool is_reflection_centric(const Op::Miller &hkl) const
Op & translate(const Tran &a)
std::array< std::array< double, 4 >, 4 > float_seitz() const
Miller apply_to_hkl(const Miller &hkl) const
std::array< std::array< int, 4 >, 4 > int_seitz() const
std::array< std::array< int, 3 >, 3 > Rot
static Miller divide_hkl_by_DEN(const Miller &hkl)
std::string triplet(char style=' ') const
std::array< double, 3 > apply_to_xyz(const std::array< double, 3 > &xyz) const
std::array< int, 3 > Miller
Op::Tran wrapped_tran() const
std::array< int, 3 > Tran
static Rot transpose(const Rot &rot)
Miller apply_to_hkl_without_division(const Miller &hkl) const
Rot transposed_rot() const
double phase_shift(const Miller &hkl) const
Op translated(const Tran &a) const
Op combine(const Op &b) const
static constexpr Op::Rot inversion_rot()
static constexpr Op identity()
Op add_centering(const Tran &a) const
bool operator<(const Op &rhs) const
bool is_in_reference_setting(int h, int k, int l) const
std::pair< Op::Miller, int > to_asu(const Op::Miller &hkl, const std::vector< Op > &sym_ops) const
Returns hkl in asu and MTZ ISYM - 2*n-1 for reflections in the positive asu (I+ of a Friedel pair),...
std::pair< Op::Miller, bool > to_asu_sign(const Op::Miller &hkl, const GroupOps &gops) const
Similar to to_asu(), but the second returned value is sign: true for + or centric.
bool is_in(const Op::Miller &hkl) const
std::pair< Op::Miller, int > to_asu(const Op::Miller &hkl, const GroupOps &gops) const
const char * condition_str() const
ReciprocalAsu(const SpaceGroup *sg, bool tnt=false)
const char * laue_str() const
const char * basisop_str() const
bool is_symmorphic() const
GroupOps operations() const
char monoclinic_unique_axis() const
returns 'a', 'b' or 'c' for monoclinic SG, '\0' otherwise
char ccp4_lattice_type() const
std::string short_name() const
const char * point_group_hm() const
Op change_of_hand_op() const
Returns change-of-hand operator. Compatible with similar sgtbx function.
const char * crystal_system_str() const
char centring_type() const
std::string pdb_name() const
bool is_centrosymmetric() const
Op centred_to_primitive() const
bool is_enantiomorphic() const
bool is_reference_setting() const
CrystalSystem crystal_system() const
PointGroup point_group() const
size_t operator()(const gemmi::Op &op) const