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
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 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)
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)
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
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)
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
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)
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)
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)
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)
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)
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)
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
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)