示例#1
0
 def calculateFromAsymmetricUnitAtoms(self, atom_iterator, space_group,
                                      cell=None):
     if cell is None:
         cell = self.cell
     st = cartesianCoordinateSymmetryTransformations(cell, space_group)
     it = ((atom_id, element, tr(position), 0., occupancy)
           for atom_id, element, position, adp, occupancy in atom_iterator
           for tr in st)
     self.calculateFromUnitCellAtoms(it, cell)
示例#2
0
 def symmetryTransformations(self):
     """
     :returns: a list of transformation objects representing the symmetry
               operations that must be applied to the asymmetric unit in
               order to obtain the contents of the unit cell
     :rtype: list of Scientific.Geometry.Transformation.Transformation
     """
     return cartesianCoordinateSymmetryTransformations(
         self.cell, self.space_group)
示例#3
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
示例#4
0
 def _countContacts(self):
     sg = self.re.reflection_set.space_group
     cell = self.re.reflection_set.cell
     symops = cartesianCoordinateSymmetryTransformations(cell, sg)
     unit_cell = []
     for tr in symops:
         for index in range(self.re.natoms):
             unit_cell.append((index, tr(Vector(self.re.positions[index]))))
     self.contacts = N.zeros((self.re.natoms), N.Int)
     for i in range(self.re.natoms):
         index1, p1 = unit_cell[i]
         for j in range(i + 1, len(unit_cell)):
             index2, p2 = unit_cell[j]
             r = cell.minimumImageDistanceVector(p1, p2).length()
             if r < 0.7:
                 self.contacts[index1] += 1
                 self.contacts[index2] += 1
示例#5
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)
示例#6
0
 def calculateFromAsymmetricUnitAtoms(self, atom_iterator, space_group,
                                      cell=None):
     """
     :param atom_iterator: an iterator or sequence that yields
                           for each atom in the asymmetric unit a
                           tuple of (atom_id, chemical element,
                           position vector, position fluctuation,
                           occupancy). The position fluctuation
                           can be a symmetric tensor (ADP tensor)
                           or a scalar (implicitly multiplied by
                           the unit tensor).
     :param space_group: the space group of the crystal
     :type space_group: CDTK.SpaceGroups.SpaceGroup
     :type atom_iterator: iterable
     :param cell: a unit cell, which defaults to the unit cell for
                  which the map object is defined. If a different
                  unit cell is given, the map is calculated for
                  this cell in fractional coordinates and converted
                  to Cartesian coordinates using the unit cell of
                  the map object. This is meaningful only if the two
                  unit cells are very similar, such as for unit cells
                  corresponding to different steps in a constant-pressure
                  Molecular Dynamics simulation.
     :type cell: CDTK.Crystal.UnitCell
     """
     if cell is None:
         cell = self.cell
     st = cartesianCoordinateSymmetryTransformations(cell, space_group)
     def check(adp):
         # Only isotropic B factors are handled for now
         if not isinstance(adp, float):
             raise NotImplementedError("Symmetry transformation of ADPs"
                                       " not yet implemented")
         return adp
     it = ((atom_id, element, tr(position), check(adp), occupancy)
           for atom_id, element, position, adp, occupancy in atom_iterator
           for tr in st)
     self.calculateFromUnitCellAtoms(it, cell)
示例#7
0
class AtomSubsetRefinementEngine(RefinementEngine):
    """
    RefinementEngine for an atom subset
    
    An AtomSubsetRefinementEngine works as a driver for an all-atom
    RefinementEngine. It works on a subset of the atoms (e.g. the
    C-alpha atoms of a protein). Every change of the parameters of these
    atoms is extended to the remaining atoms by an interpolation scheme.
    The idea behind this approach is that both atom displacements and atomic
    ADPs are slowly-varying functions of position when considered at low
    resolutions.
    
    A typical refinement protocol based on this class would be the
    following:

     1. Create a RefinementEngine for the all-atom refinement task.
     2. Create an AtomSubsetRefinementEngine for a suitable atom subset.
     3. Refine at the subset level.
     4. Refine at the all-atom level using the all-atom RefinementEngine.

    The interpolation scheme for atom displacements and atomic ADPs assigns
    values to each atom that is not in the subset based on the values for
    the atoms that are in the subset as well as their images constructed by
    applying the symmetry operations of the space group. The weight of each
    atom in the interpolation is a function of its minimum-image distance
    vector from the target atom. The default weights are given by the
    inverse of the squared length of the distance vector.
    """
    def __init__(self,
                 all_atom_refinement_engine,
                 subset_atom_ids,
                 distance_power=4):
        """
        :param all_atom_refinement_engine: the underlying all-atom
                                           refinement engine
        :type all_atom_refinement_engine: CDTK.Refinement.RefinementEngine
        :param subset_atom_ids: the ids of the atoms that are part of the
                                subset to be used in refinement
        :type subset_atom_ids: sequence
        :param distance_power: the power of the length of the distance
                               vector in the calculation of the weight
        :type distance_power: int
        """
        assert isinstance(all_atom_refinement_engine, RefinementEngine)
        self.re = all_atom_refinement_engine
        self.ids = subset_atom_ids
        self.power = distance_power
        try:
            self.aa_indices = [self.re.id_dict[id] for id in self.ids]
        except KeyError, e:
            raise ValueError("Atom %s is not used in refinement engine %s" %
                             (str(e.args[0]), str(all_atom_refinement_engine)))
        self.natoms = len(self.ids)
        self.id_dict = dict(zip(self.ids, range(self.natoms)))
        self.positions = N.take(self.re.positions, self.aa_indices)
        self.position_updates = 0. * self.positions
        self.adps = N.take(self.re.adps, self.aa_indices)
        self.occupancies = N.take(self.re.occupancies, self.aa_indices)

        sg = self.re.reflection_set.space_group
        cell = self.re.reflection_set.cell
        symops = cartesianCoordinateSymmetryTransformations(cell, sg)
        unit_cell_subset = []
        for id in self.ids:
            for tr in symops:
                index = self.id_dict[id]
                rm = tr.tensor.array
                rmt = symmetricTensorRotationMatrix(rm)
                unit_cell_subset.append(
                    (index, rm, rmt, tr(Vector(self.positions[index]))))

        self.position_interpolation = N.zeros(
            (self.re.natoms, 3, self.natoms, 3), N.Float)
        self.adp_interpolation = N.zeros((self.re.natoms, 6, self.natoms, 6),
                                         N.Float)
        for i in range(self.re.natoms):
            if i in self.aa_indices:
                si = self.aa_indices.index(i)
                for k in range(3):
                    self.position_interpolation[i, k, si, k] = 1.
                for k in range(6):
                    self.adp_interpolation[i, k, si, k] = 1.
            else:
                nb = []
                r = Vector(self.re.positions[i])
                for sindex, rot_v, rot_adp, position in unit_cell_subset:
                    d = cell.minimumImageDistanceVector(r, position)
                    nb.append((d, sindex, rot_v, rot_adp))
                self._interpolate(i, nb)
        self.position_interpolation.shape = (3 * self.re.natoms,
                                             3 * self.natoms)
        self.adp_interpolation.shape = (6 * self.re.natoms, 6 * self.natoms)

        self.state_valid = False