Skip to content

Commit

Permalink
epsilon_factor() now takes centering vectors into account
Browse files Browse the repository at this point in the history
  • Loading branch information
wojdyr committed Jul 21, 2020
1 parent 49f0d16 commit 9f8ccd0
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 6 deletions.
2 changes: 2 additions & 0 deletions docs/hkl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ used with a number of vectorized functions:
array([ True, True, True, ..., False, False, False])
>>> gops.epsilon_factor_array(hkl) # vectorized epsilon_factor()
array([1, 1, 1, ..., 1, 1, 1], dtype=int32)
>>> gops.epsilon_factor_without_centering_array(hkl) # epsilon_factor_without_centering()
array([1, 1, 1, ..., 1, 1, 1], dtype=int32)
>>> gops.systematic_absences(hkl) # vectorized is_systematically_absent()
array([False, False, False, ..., False, False, False])
>>> mtz.cell.calculate_d_array(hkl) # vectorized calculate_d()
Expand Down
16 changes: 13 additions & 3 deletions docs/symmetry.rst
Original file line number Diff line number Diff line change
Expand Up @@ -536,14 +536,24 @@ Similarly, we can check for systematic absences:
>>> new_ops.is_systematically_absent([1, 3, 2])
False

Another property, the epsilon factor ε, tells how many times the point group symmetry
Another property, the epsilon factor ε, tells how many times the symmetry
operations map the reflection onto itself:

.. doctest::

>>> new_ops.epsilon_factor([1, 2, 3])
>>> new_ops.epsilon_factor([1, 3, 2])
2
>>> new_ops.epsilon_factor([2, 0, 2])
4

We also have a function that calculates ε ignoring centering vectors
(equivalent to the ``epsilon()`` function in cctbx):

.. doctest::

>>> new_ops.epsilon_factor_without_centering([1, 3, 2])
1
>>> new_ops.epsilon_factor([1, 0, 3])
>>> new_ops.epsilon_factor_without_centering([2, 0, 2])
2

ASU
Expand Down
5 changes: 4 additions & 1 deletion include/gemmi/symmetry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,14 +401,17 @@ struct GroupOps {
return false;
}

int epsilon_factor(const Op::Miller& hkl) const {
int epsilon_factor_without_centering(const Op::Miller& hkl) const {
Op::Miller denh = {{Op::DEN * hkl[0], Op::DEN * hkl[1], Op::DEN * hkl[2]}};
int epsilon = 0;
for (const Op& op : sym_ops)
if (op.apply_to_hkl_without_division(hkl) == denh)
++epsilon;
return epsilon;
}
int epsilon_factor(const Op::Miller& hkl) const {
return epsilon_factor_without_centering(hkl) * cen_ops.size();
}

static bool has_phase_shift(const Op::Tran& c, const Op::Miller& hkl) {
return (hkl[0] * c[0] + hkl[1] * c[1] + hkl[2] * c[2]) % Op::DEN != 0;
Expand Down
5 changes: 5 additions & 0 deletions python/sym.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,15 @@ void add_symmetry(py::module& m) {
.def("centric_flag_array", [](const GroupOps& g, py::array_t<int> hkl) {
return miller_function<bool>(g, &GroupOps::is_reflection_centric, hkl);
})
.def("epsilon_factor_without_centering", &GroupOps::epsilon_factor_without_centering)
.def("epsilon_factor", &GroupOps::epsilon_factor)
.def("epsilon_factor_array", [](const GroupOps& g, py::array_t<int> hkl) {
return miller_function<int>(g, &GroupOps::epsilon_factor, hkl);
})
.def("epsilon_factor_without_centering_array", [](const GroupOps& g,
py::array_t<int> hkl) {
return miller_function<int>(g, &GroupOps::epsilon_factor_without_centering, hkl);
})
.def("is_systematically_absent", &GroupOps::is_systematically_absent)
.def("systematic_absences", [](const GroupOps& g, py::array_t<int> hkl) {
return miller_function<bool>(g, &GroupOps::is_systematically_absent, hkl);
Expand Down
9 changes: 7 additions & 2 deletions tests/test_symmetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,15 @@ def test_reflection_properties(self):
gops = sg.operations()
self.assertTrue(gops.is_reflection_centric([3,0,3]))
self.assertFalse(gops.is_reflection_centric([3,3,3]))
self.assertEqual(gops.epsilon_factor([3,0,3]), 1)
self.assertEqual(gops.epsilon_factor([0,3,0]), 2)
self.assertEqual(gops.epsilon_factor([3,0,3]), 2)
self.assertEqual(gops.epsilon_factor([0,3,0]), 4)
self.assertFalse(gops.is_systematically_absent([1,2,3]))
self.assertTrue(gops.is_systematically_absent([1,2,4]))
sg = gemmi.SpaceGroup('F 4 3 2')
gops = sg.operations()
self.assertEqual(gops.epsilon_factor([2,0,0]), 16)
self.assertEqual(gops.epsilon_factor([3,3,3]), 12)
self.assertEqual(gops.epsilon_factor_without_centering([2,0,0]), 4)

if __name__ == '__main__':
unittest.main()

0 comments on commit 9f8ccd0

Please sign in to comment.