示例#1
0
    def fromHDF5(cls, store, dataset):
        from CDTK.SpaceGroups import space_groups
        from CDTK.Crystal import UnitCell
        space_group = space_groups[dataset.attrs['space_group']]
        cell = UnitCell(dataset.attrs['a'],
                        dataset.attrs['b'],
                        dataset.attrs['c'],
                        dataset.attrs['alpha'],
                        dataset.attrs['beta'],
                        dataset.attrs['gamma'])
        self = cls(ReflectionSet(cell, space_group))
        self._reflections = dataset[...]
        try:
            self._absences = dataset.attrs['systematic_absences']
        except KeyError:
            self._absences = np.zeros((0,), dtype=self._dtype)

        r1, r2, r3 = cell.reciprocalBasisVectors()
        sv = self._reflections['h'][:, np.newaxis]*r1.array + \
             self._reflections['k'][:, np.newaxis]*r2.array + \
             self._reflections['l'][:, np.newaxis]*r3.array
        sva = self._absences['h'][:, np.newaxis]*r1.array + \
              self._absences['k'][:, np.newaxis]*r2.array + \
              self._absences['l'][:, np.newaxis]*r3.array
        s = np.concatenate([np.sqrt(np.sum(sv**2, axis=1)),
                            np.sqrt(np.sum(sva**2, axis=1))])
        self.s_min = s.min()
        self.s_max = s.max()
        return self
示例#2
0
 def __setstate__(self, state):
     from CDTK.SpaceGroups import space_groups
     from CDTK.Crystal import UnitCell
     cell_basis, space_group_number, \
                 self.s_min, self.s_max, \
                 self.completeness_range, \
                 self._reflections, \
                 self._absences = state
     self.cell = UnitCell(*cell_basis)
     self.space_group = space_groups[space_group_number]
     self.crystal = Crystal(self.cell, self.space_group)
示例#3
0
    def setupReflectionSet(self):
        from CDTK.Crystal import UnitCell
        from CDTK.SpaceGroups import space_groups
        from CDTK.Reflections import ReflectionSet
        from CDTK.ReflectionData import ExperimentalAmplitudes, \
                                        ExperimentalIntensities
        from CDTK import Units

        if len(self.cell) == 0 or len(self.symmetry) == 0:
            self.parseStructureFile()
        if len(self.cell) == 0:
            raise MMCIFError("cell parameters missing")
        if len(self.symmetry) == 0:
            raise MMCIFError("symmetry parameters missing")

        cell = UnitCell(
            float(self.cell['length_a']) * Units.Ang,
            float(self.cell['length_b']) * Units.Ang,
            float(self.cell['length_c']) * Units.Ang,
            float(self.cell['angle_alpha']) * Units.deg,
            float(self.cell['angle_beta']) * Units.deg,
            float(self.cell['angle_gamma']) * Units.deg)
        try:
            sg_key = int(self.symmetry['Int_Tables_number'])
        except (KeyError, ValueError):
            sg_key = self.symmetry['space_group_name_H-M'].strip()
        space_group = space_groups[sg_key]
        self.reflections = ReflectionSet(cell, space_group)
示例#4
0
    def test_hdf5(self):
        cell = UnitCell(3., 3., 4., 90. * Units.deg, 90. * Units.deg,
                        120. * Units.deg)
        res_max = 0.5
        res_min = 10.
        reflections = ReflectionSet(cell,
                                    space_groups['P 31'],
                                    res_max,
                                    res_min,
                                    compact=self.compact)
        frozen = reflections.freeze()

        with HDF5Store('test.h5', 'w') as store:
            store.store('reflections', reflections)
            retrieved = store.retrieve('reflections')
            store.store('frozen_reflections', frozen)

        self.assert_(retrieved is reflections)

        with HDF5Store('test.h5', 'r') as store:
            retrieved = store.retrieve('reflections')
            retrieved_again = store.retrieve('reflections')
            retrieved_frozen = store.retrieve('frozen_reflections')

        self.assert_(retrieved_again is retrieved)
        self.assert_(isinstance(retrieved, ReflectionSet))
        self.assert_(isinstance(retrieved_frozen, ReflectionSet))
        self.assert_(isinstance(retrieved, FrozenReflectionSet))
        self.assert_(isinstance(retrieved_frozen, FrozenReflectionSet))

        self._compare(reflections, retrieved, False)
        self._compare(reflections, retrieved_frozen, False)
示例#5
0
 def __setstate__(self, state):
     from CDTK.SpaceGroups import space_groups
     from CDTK.Crystal import UnitCell
     cell_basis, space_group_number, \
                 self.s_min, self.s_max, self.compact, \
                 self.completeness_range, \
                 reflections, absences = state
     self.cell = UnitCell(*cell_basis)
     self.space_group = space_groups[space_group_number]
     self.crystal = Crystal(self.cell, self.space_group)
     self.minimal_reflection_list = []
     self.reflection_map = {}
     self.systematic_absences = set()
     for h, k, l, index in reflections:
         r = Reflection(h, k, l, self.crystal, index)
         for re in r.symmetryEquivalents():
             hkl = (re.h, re.k, re.l)
             if not self.compact:
                 self.reflection_map[hkl] = re
             if hkl == (h, k, l):
                 self.minimal_reflection_list.append(re)
                 if self.compact:
                     self.reflection_map[hkl] = re
                     break
     for h, k, l in absences:
         r = Reflection(h, k, l, self.crystal, None)
         for re in r.symmetryEquivalents():
             hkl = (re.h, re.k, re.l)
             if not self.compact:
                 self.reflection_map[hkl] = re
             if hkl == (h, k, l):
                 self.systematic_absences.add(re)
                 if self.compact:
                     self.reflection_map[(h, k, l)] = re
                     break
示例#6
0
    def test_pickle(self):
        cell = UnitCell(3., 3., 4., 90. * Units.deg, 90. * Units.deg,
                        120. * Units.deg)
        res_max = 0.5
        res_min = 10.
        reflections = ReflectionSet(cell,
                                    space_groups['P 31'],
                                    res_max,
                                    res_min,
                                    compact=self.compact)
        self.assert_(reflections.isComplete())

        string = cPickle.dumps(reflections)
        unpickled = cPickle.loads(string)
        self.assert_(unpickled.isComplete())
        self.assertEqual(len(reflections.reflection_map),
                         len(unpickled.reflection_map))
        self._compare(reflections, unpickled)

        frozen = reflections.freeze()
        self.assert_(frozen.isComplete())
        self._compare(reflections, frozen)

        string = cPickle.dumps(frozen)
        unpickled = cPickle.loads(string)
        self.assert_(unpickled.isComplete())
        self.assert_((frozen._reflections == unpickled._reflections).any())
        self.assert_((frozen._absences == unpickled._absences).any())
        self._compare(frozen, unpickled)
示例#7
0
 def test_basis(self):
     for params, rb, sg, nb in datasets:
         cell = UnitCell(*params)
         sg = space_groups[sg]
         trs = cartesianCoordinateSymmetryTransformations(cell, sg)
         basis = symmetricTensorBasis(cell, sg)
         assert len(basis) == nb
         for t in basis:
             for tr in trs:
                 t_rot = t.applyRotationMatrix(tr.tensor.array)
                 assert largestAbsoluteElement((t_rot - t).array) < 1.e-12
示例#8
0
 def test_geometry(self):
     for params, rb, sg in datasets:
         cell1 = UnitCell(*params)
         basis = cell1.basisVectors()
         reciprocal_basis = cell1.reciprocalBasisVectors()
         for i in range(3):
             self.assert_((reciprocal_basis[i]-rb[i]).length()
                          < 1.e-6)
         for i in range(3):
             for j in range(3):
                 p = basis[i]*reciprocal_basis[j]
                 if i == j:
                     self.assertAlmostEqual(p, 1., 10)
                 else:
                     self.assertAlmostEqual(p, 0., 10)
         cell2 = UnitCell(*tuple(basis))
         self.assertAlmostEqual(cell1.a, cell2.a, 5)
         self.assertAlmostEqual(cell1.b, cell2.b, 5)
         self.assertAlmostEqual(cell1.c, cell2.c, 5)
         self.assertAlmostEqual(cell1.alpha, cell2.alpha, 5)
         self.assertAlmostEqual(cell1.beta, cell2.beta, 5)
         self.assertAlmostEqual(cell1.gamma, cell2.gamma, 5)
示例#9
0
 def test_P31(self):
     cell = UnitCell(3., 3., 4.,
                     90.*Units.deg, 90.*Units.deg, 120.*Units.deg)
     res_max = 0.5
     res_min = 10.
     reflections = ReflectionSet(cell, space_groups['P 31'],
                                 res_max, res_min)
     sf = StructureFactor(reflections)
     value = 1.1-0.8j
     for r in reflections:
         for re in r.symmetryEquivalents():
             sf[re] = value
             self.assert_(N.absolute(sf[re]-value) < 1.e-14)
             ri = reflections[(-re.h, -re.k, -re.l)]
             self.assert_(N.absolute(sf[ri]-N.conjugate(value)) < 1.e-13)
示例#10
0
    def test_P1(self):
        cell = UnitCell(Vector(1., 0., 0.), Vector(0., 1., 0.),
                        Vector(0., 0., 1.))
        res_max = 0.5
        res_min = 10.
        reflections = ReflectionSet(cell,
                                    space_groups['P 1'],
                                    res_max,
                                    res_min,
                                    compact=self.compact)
        self.assert_(reflections.isComplete())
        nr = sum([r.n_symmetry_equivalents for r in reflections]) + \
             sum([r.n_symmetry_equivalents
                  for r in reflections.systematic_absences])
        self.assertEqual(reflections.totalReflectionCount(), nr)
        self.assert_(reflections.totalReflectionCount() == 2 *
                     len(reflections.minimal_reflection_list))
        for r in reflections:
            self.assert_(len(r.symmetryEquivalents()) == 2)
            self.assert_(res_max <= r.resolution() <= res_min)
            self.assert_(not r.isCentric())
            self.assert_(r.symmetryFactor() == 1)
        self._shellTest(reflections)
        self._subsetTest(reflections)
        self._symmetryTest(reflections)
        self._intersectionTest(reflections)
        self._equalityTest(reflections)

        frozen = reflections.freeze()
        self.assert_(frozen is reflections.freeze())
        self.assert_(frozen is frozen.freeze())
        self.assert_(frozen.isComplete())
        self.assert_(frozen.totalReflectionCount() == 2 *
                     len(frozen._reflections))
        for r in frozen:
            self.assert_(reflections.hasReflection(r.h, r.k, r.l))
            self.assert_(len(r.symmetryEquivalents()) == 2)
            self.assert_(res_max <= r.resolution() <= res_min)
            self.assert_(not r.isCentric())
            self.assert_(r.symmetryFactor() == 1)
        for r in reflections:
            self.assert_(frozen.hasReflection(r.h, r.k, r.l))
            self.assert_(r.index == frozen[(r.h, r.k, r.l)].index)
        self._shellTest(frozen)
        self._subsetTest(frozen)
        self._symmetryTest(frozen)
        self._intersectionTest(frozen)
        self._equalityTest(frozen)
示例#11
0
 def test_symmetry_ops(self):
     for params, rb, sg in datasets:
         cell = UnitCell(*params)
         sg = space_groups[sg]
         transformations = cartesianCoordinateSymmetryTransformations(cell, sg)
         for t in transformations:
             # Check that the transformation is a rotation-translation.
             error = N.absolute(N.multiply.reduce(t.tensor.eigenvalues())-1.)
             self.assert_(error < 1.e-12)
             # Check that applying the transformation N times (where N is
             # the number of symmetry operations) yields a transformation
             # without rotation.
             ntimes = t
             for i in range(1, len(sg)):
                 ntimes = ntimes*t
             self.assert_(largestAbsoluteElement(
                            (ntimes.tensor-delta).array) < 1.e-12)
示例#12
0
 def test_conversions(self):
     for params, rb, sg in datasets:
         cell = UnitCell(*params)
         m_fc = cell.fractionalToCartesianMatrix()
         m_cf = cell.cartesianToFractionalMatrix()
         for x in fractional_coordinates:
             r = cell.fractionalToCartesian(x)
             rr = N.dot(m_fc, x)
             self.assert_(largestAbsoluteElement(r.array-rr) < 1.e-10)
             xx = cell.cartesianToFractional(r)
             self.assert_(largestAbsoluteElement(x-xx) < 1.e-15)
             xx = N.dot(m_cf, rr)
             self.assert_(largestAbsoluteElement(x-xx) < 1.e-15)
示例#13
0
    def test_P31(self):
        cell = UnitCell(3., 3., 4., 90. * Units.deg, 90. * Units.deg,
                        120. * Units.deg)
        res_max = 0.5
        res_min = 10.
        sg = space_groups['P 31']
        reflections = ReflectionSet(cell,
                                    sg,
                                    res_max,
                                    res_min,
                                    compact=self.compact)
        self.assert_(reflections.isComplete())
        nr = sum([r.n_symmetry_equivalents for r in reflections]) + \
             sum([r.n_symmetry_equivalents
                  for r in reflections.systematic_absences])
        self.assertEqual(reflections.totalReflectionCount(), nr)
        for r in reflections:
            self.assert_(res_max <= r.resolution() <= res_min)
        for r in reflections.systematic_absences:
            self.assertEqual(r.h, 0)
            self.assertEqual(r.k, 0)
            self.assertNotEqual(r.l % 3, 0)
        self._shellTest(reflections)
        self._subsetTest(reflections)
        self._symmetryTest(reflections)
        self._intersectionTest(reflections)
        self._equalityTest(reflections)

        frozen = reflections.freeze()
        self.assert_(frozen is reflections.freeze())
        self.assert_(frozen is frozen.freeze())
        self.assert_(frozen.isComplete())
        for r in frozen:
            self.assert_(reflections.hasReflection(r.h, r.k, r.l))
            self.assert_(res_max <= r.resolution() <= res_min)
        for r in reflections:
            self.assert_(frozen.hasReflection(r.h, r.k, r.l))
            self.assert_(r.index == frozen[(r.h, r.k, r.l)].index)
        self._shellTest(frozen)
        self._subsetTest(frozen)
        self._symmetryTest(frozen)
        self._intersectionTest(frozen)
        self._equalityTest(frozen)
示例#14
0
class FrozenReflectionSet(ReflectionSet):

    def __init__(self, reflection_set):
        self.cell = reflection_set.cell
        self.space_group = reflection_set.space_group
        self.crystal = reflection_set.crystal
        self.s_min = reflection_set.s_min
        self.s_max = reflection_set.s_max
        self.completeness_range = reflection_set.completeness_range
        self.compact = True

        rs = reflection_set.minimal_reflection_list
        self._reflections = np.zeros((len(rs),), dtype=self._dtype)
        for r in rs:
            self._reflections[r.index] = (r.h, r.k, r.l)

        rs = reflection_set.systematic_absences
        self._absences = np.zeros((len(rs),), dtype=self._dtype)
        for index, r in enumerate(rs):
            self._absences[index] = (r.h, r.k, r.l)

    _dtype = np.dtype([('h', np.int32),
                       ('k', np.int32),
                       ('l', np.int32)])

    def freeze(self):
        return self

    def addReflection(self, h, k, l):
        raise ValueError("Can't modify FrozenReflectionSet")

    def fillResolutionSphere(self, max_resolution=None, min_resolution=None):
        raise ValueError("Can't modify FrozenReflectionSet")

    def sRange(self):
        if len(self._reflections) == 0:
            raise ValueError("Empty ReflectionSet")
        return self.s_min, self.s_max

    def resolutionRange(self):
        if len(self._reflections) == 0:
            raise ValueError("Empty ReflectionSet")
        return 1./self.s_max, 1./self.s_min

    def maxHKL(self):
        if len(self._absences) == 0:
            max_hkl = np.zeros((3,), np.int)
        else:
            max_hkl = np.array([self._absences['h'].max(),
                                self._absences['k'].max(),
                                self._absences['l'].max()])
        for r in self:
            hkl = [(re.h, re.k, re.l) for re in r.symmetryEquivalents()]
            max_hkl = N.maximum(max_hkl, N.maximum.reduce(N.array(hkl)))
        return tuple(max_hkl)

    def __iter__(self):
        for i, (h, k, l) in enumerate(self._reflections):
            yield Reflection(h, k, l, self.crystal, i)

    def __len__(self):
        return len(self._reflections)

    def __getitem__(self, item):
        hkl = np.array(item, dtype=self._dtype)
        test = self._reflections == hkl
        if test.any():
            index = np.repeat(np.arange(len(self._reflections)), test)[0]
            return Reflection(hkl['h'], hkl['k'], hkl['l'], self.crystal, index)
        if (self._absences == hkl).any():
            return Reflection(hkl['h'], hkl['k'], hkl['l'], self.crystal, None)

        for hkl in self.crystal.space_group.\
                        symmetryEquivalentMillerIndices(np.array(item))[0]:
            for sign in [1., -1.]:
                hkl_sym = np.array(tuple(sign*hkl), dtype=self._dtype)
                test = self._reflections == hkl_sym
                if test.any():
                    index = np.repeat(np.arange(len(self._reflections)),
                                      test)[0]
                    r = Reflection(hkl_sym['h'], hkl_sym['k'], hkl_sym['l'],
                                   self.crystal, index)
                    for re in r.symmetryEquivalents():
                        if (re.h, re.k, re.l) == item:
                            return re
                if (self._absences == hkl_sym).any():
                    return Reflection(hkl_sym['h'], hkl_sym['k'], hkl_sym['l'],
                                      self.crystal, None)

        raise KeyError(item)

    def hasReflection(self, h, k, l):
        try:
            _ = self[(h, k, l)]
            return True
        except KeyError:
            hkl = np.array((h, k, l), dtype=self._dtype)
            return (self._absences == hkl).any()

    def totalReflectionCount(self):
        return sum(r.n_symmetry_equivalents for r in self) + \
               sum(r.n_symmetry_equivalents for r in self.systematic_absences)

    # Provide lists of reflections objects on demand, for compatibility
    # with ReflectionSet.
    @property
    def systematic_absences(self):
        return [Reflection(hkl['h'], hkl['k'], hkl['l'], self.crystal, None)
                for hkl in self._absences]

    @property
    def minimal_reflection_list(self):
        return [Reflection(hkl['h'], hkl['k'], hkl['l'], self.crystal, index)
                for index, hkl in enumerate(self._reflections)]

    def __getstate__(self):
        return (tuple(self.cell.basisVectors()),
                self.space_group.number,
                self.s_min, self.s_max,
                self.completeness_range,
                self._reflections,
                self._absences)

    def __setstate__(self, state):
        from CDTK.SpaceGroups import space_groups
        from CDTK.Crystal import UnitCell
        cell_basis, space_group_number, \
                    self.s_min, self.s_max, \
                    self.completeness_range, \
                    self._reflections, \
                    self._absences = state
        self.cell = UnitCell(*cell_basis)
        self.space_group = space_groups[space_group_number]
        self.crystal = Crystal(self.cell, self.space_group)

    def sVectorArray(self, cell=None):
        """
        :param cell: a unit cell, which defaults to the unit cell for
                     which the reflection set is defined.
        :type cell: CDTK.Crystal.UnitCell
        :return: an array containing the s vectors for all reflections
        :rtype: N.array
        """
        global _cache
        if cell is None:
            cell = self.cell
        cached_data = _cache.get(self, {})
        try:
            return cached_data[('sVectorArray', id(cell))]
        except KeyError:
            pass

        r1, r2, r3 = cell.reciprocalBasisVectors()
        sv = self._reflections['h'][:, np.newaxis]*r1.array + \
             self._reflections['k'][:, np.newaxis]*r2.array + \
             self._reflections['l'][:, np.newaxis]*r3.array

        cached_data[('sVectorArray', id(cell))] = sv
        _cache[self] = cached_data
        return sv

    def sVectorArrayAndPhasesForASU(self, cell=None):
        """
        Calculates the transformed s vectors and phases that are used
        for calculating the structure factor from the atoms in the
        asymmetric unit.

        :param cell: a unit cell, which defaults to the unit cell for
            which the reflection set is defined.
        :type cell: CDTK.Crystal.UnitCell
        :returns: a tuple (s, p), where s is an array containing the s vectors
            for all reflections and space group operations and p is an
            array with the corresponding phases
        :rtype: Scientific.N.array_type
        """
        global _cache
        if cell is None:
            cell = self.cell
        cached_data = _cache.get(self, {})
        try:
            return cached_data[('sVectorArrayAndPhasesForASU', id(cell))]
        except KeyError:
            pass

        sg = self.space_group
        ntrans = len(sg)
        nr = len(self._reflections)
        sv = N.zeros((ntrans, nr, 3), N.Float)
        p = N.zeros((ntrans, nr), N.Complex)
        twopii = 2.j*N.pi
        r1, r2, r3 = cell.reciprocalBasisVectors()
        r1 = r1.array
        r2 = r2.array
        r3 = r3.array
        for index, r in enumerate(self._reflections):
            hkl_list = sg.symmetryEquivalentMillerIndices(r.view('3i4'))[0]
            rh, rk, rl = r
            for i in range(ntrans):
                h, k, l = hkl_list[i]
                sv[i, index] = h*r1+k*r2+l*r3
                tr_num, tr_den = sg.transformations[i][1:]
                st = rh*float(tr_num[0])/float(tr_den[0]) \
                     + rk*float(tr_num[1])/float(tr_den[1]) \
                     + rl*float(tr_num[2])/float(tr_den[2])
                p[i, index] = N.exp(twopii*st)

        cached_data[('sVectorArrayAndPhasesForASU', id(cell))] = (sv, p)
        _cache[self] = cached_data
        return sv, p

    def symmetryAndCentricityArrays(self):
        """
        :return: an array containing the symmetry factors and centricity flags
                 for all reflections
        :rtype: N.array
        """
        sm = N.zeros((len(self._reflections), 2), N.Int)
        for r in self:
            sm[r.index, 0] = r.symmetryFactor()
            sm[r.index, 1] = r.isCentric()
        return sm

    def storeHDF5(self, store, path):
        import h5py
        import numpy as np

        # Sort Miller indices in order to have a standardized
        # representation on disk.
        rs = self._reflections
        si = np.argsort(rs, order=('h', 'k', 'l'))
        rs = np.take(rs, si)

        dataset = store.root.require_dataset(path, shape=rs.shape,
                                             dtype=rs.dtype, exact=True)
        dataset[...] = rs
        a1, a2, a3 = self.cell.basisVectors()
        dataset.attrs['a'] = a1.length()
        dataset.attrs['b'] = a2.length()
        dataset.attrs['c'] = a3.length()
        dataset.attrs['alpha'] = a2.angle(a3)
        dataset.attrs['beta'] = a1.angle(a3)
        dataset.attrs['gamma'] = a1.angle(a2)
        dataset.attrs['space_group'] = self.space_group.number
        if len(self._absences) > 0:
            dataset.attrs['systematic_absences'] = self._absences
        store.stamp(dataset, 'ReflectionSet')
        return dataset, {'immutable': True, 'sort_indices': si}

    @classmethod
    def fromHDF5(cls, store, dataset):
        from CDTK.SpaceGroups import space_groups
        from CDTK.Crystal import UnitCell
        space_group = space_groups[dataset.attrs['space_group']]
        cell = UnitCell(dataset.attrs['a'],
                        dataset.attrs['b'],
                        dataset.attrs['c'],
                        dataset.attrs['alpha'],
                        dataset.attrs['beta'],
                        dataset.attrs['gamma'])
        self = cls(ReflectionSet(cell, space_group))
        self._reflections = dataset[...]
        try:
            self._absences = dataset.attrs['systematic_absences']
        except KeyError:
            self._absences = np.zeros((0,), dtype=self._dtype)

        r1, r2, r3 = cell.reciprocalBasisVectors()
        sv = self._reflections['h'][:, np.newaxis]*r1.array + \
             self._reflections['k'][:, np.newaxis]*r2.array + \
             self._reflections['l'][:, np.newaxis]*r3.array
        sva = self._absences['h'][:, np.newaxis]*r1.array + \
              self._absences['k'][:, np.newaxis]*r2.array + \
              self._absences['l'][:, np.newaxis]*r3.array
        s = np.concatenate([np.sqrt(np.sum(sv**2, axis=1)),
                            np.sqrt(np.sum(sva**2, axis=1))])
        self.s_min = s.min()
        self.s_max = s.max()
        return self
示例#15
0
    def test_P43212(self):
        cell = UnitCell(Vector(1., 0., 0.), Vector(0., 1., 0.),
                        Vector(0., 0., 1.5))
        res_max = 0.5
        res_min = 10.
        sg = space_groups['P 43 21 2']
        reflections = ReflectionSet(cell,
                                    sg,
                                    res_max,
                                    res_min,
                                    compact=self.compact)
        self.assert_(reflections.isComplete())
        nr = sum([r.n_symmetry_equivalents for r in reflections]) + \
             sum([r.n_symmetry_equivalents
                  for r in reflections.systematic_absences])
        self.assertEqual(reflections.totalReflectionCount(), nr)
        for r in reflections:
            self.assert_(res_max <= r.resolution() <= res_min)
            is_centric = r.isCentric()
            if r.h == 0 or r.k == 0 or r.l == 0:
                self.assert_(is_centric)
            elif r.h == r.k:
                self.assert_(is_centric)
            else:
                self.assert_(not is_centric)
            eps = r.symmetryFactor()
            if r.l == 0 and (r.h == r.k or r.h == -r.k):
                self.assert_(eps == 2)
            elif int(r.h == 0) + int(r.k == 0) + int(r.l == 0) == 2:
                if r.l != 0:
                    self.assert_(eps == 4)
                else:
                    self.assert_(eps == 2)
            else:
                self.assert_(eps == 1)
        for r in reflections.systematic_absences:
            self.assertEqual(int(r.h == 0) + int(r.k == 0) + int(r.l == 0), 2)
            if r.h != 0:
                self.assertEqual(r.h % 2, 1)
            if r.k != 0:
                self.assertEqual(r.k % 2, 1)
            if r.l != 0:
                self.assertNotEqual(r.l % 4, 0)
        self._shellTest(reflections)
        self._subsetTest(reflections)
        self._symmetryTest(reflections)
        self._intersectionTest(reflections)
        self._equalityTest(reflections)

        frozen = reflections.freeze()
        self.assert_(frozen is reflections.freeze())
        self.assert_(frozen is frozen.freeze())
        self.assert_(frozen.isComplete())
        for r in frozen:
            self.assert_(reflections.hasReflection(r.h, r.k, r.l))
            self.assert_(res_max <= r.resolution() <= res_min)
        for r in reflections:
            self.assert_(frozen.hasReflection(r.h, r.k, r.l))
            self.assert_(r.index == frozen[(r.h, r.k, r.l)].index)
        self._shellTest(frozen)
        self._subsetTest(frozen)
        self._symmetryTest(frozen)
        self._intersectionTest(frozen)
        self._equalityTest(frozen)