def test_superpose(self):
        # create a few test sets with random data points, including degenerate
        # situations. (e.g. one point, two points, linear points)
        references = [  # a list of 2-tuples: (points, degenerate)
            (numpy.random.normal(0, 5, (n, 3)), False) for n in xrange(4, 40)
        ] + [
            #(numpy.array([[0,0,1]], float), True),
            #(numpy.array([[0,0,0],[0,0,1]], float), True),
            #(numpy.array([[0,0,0],[0,0,1],[0,0,2]], float), True),
            #(numpy.array([[0,0,0],[0,0,1],[0,0,2],[0,0,4]], float), True),
            #(numpy.random.normal(0, 5, (3, 3)), True)
        ]

        # Do a random transformation on the points
        randomized = []
        for points, degenerate in references:
            #points[:] -= points.mean(axis=0)
            axis = random_unit(3)
            angle = numpy.random.uniform(0, numpy.pi * 2)
            transformation = Complete()
            transformation.set_rotation_properties(angle, axis, False)
            transformation.t[:] = numpy.random.normal(0, 5, 3)
            randomized.append(
                (numpy.array([transformation.vector_apply(p)
                              for p in points]), transformation))

        for (ref_points, degenerate), (tr_points,
                                       transf) in zip(references, randomized):
            check_transf = superpose(ref_points, tr_points)
            # check whether the rotation matrix is orthogonal
            self.assertArraysAlmostEqual(
                numpy.dot(check_transf.r, check_transf.r.transpose()),
                numpy.identity(3, float), 1e-5)
            # first check whether check_transf brings the tr_points back to the ref_points
            check_points = numpy.dot(
                tr_points, check_transf.r.transpose()) + check_transf.t
            self.assertArraysAlmostEqual(ref_points,
                                         check_points,
                                         1e-5,
                                         doabs=True)
            if not degenerate:
                # if the set of points is not degenerate, check whether transf and check_transf
                # are each other inverses
                tmp = Complete()
                tmp.apply_before(transf)
                tmp.apply_before(check_transf)
                self.assertArraysAlmostEqual(
                    numpy.dot(transf.r, check_transf.r),
                    numpy.identity(3, float), 1e-5)
                self.assertArrayAlmostZero(tmp.t, 1e-5)

        # Add some distortion to the transformed points
        randomized = []
        for tr_points, transf in randomized:
            tr_points[:] += numpy.random.normal(0, 1.0, len(tr_points))

        # Do a blind test
        for (ref_points, degenerate), (tr_points,
                                       transf) in zip(references, randomized):
            superpose(ref_points, tr_points)
    def test_superpose(self):
        # create a few test sets with random data points, including degenerate
        # situations. (e.g. one point, two points, linear points)
        references = [ # a list of 2-tuples: (points, degenerate)
            (numpy.random.normal(0, 5, (n, 3)), False) for n in xrange(4, 40)
        ] + [
            #(numpy.array([[0,0,1]], float), True),
            #(numpy.array([[0,0,0],[0,0,1]], float), True),
            #(numpy.array([[0,0,0],[0,0,1],[0,0,2]], float), True),
            #(numpy.array([[0,0,0],[0,0,1],[0,0,2],[0,0,4]], float), True),
            #(numpy.random.normal(0, 5, (3, 3)), True)
        ]

        # Do a random transformation on the points
        randomized = []
        for points, degenerate in references:
            #points[:] -= points.mean(axis=0)
            axis = random_unit(3)
            angle = numpy.random.uniform(0, numpy.pi*2)
            transformation = Complete()
            transformation.set_rotation_properties(angle, axis, False)
            transformation.t[:] = numpy.random.normal(0, 5, 3)
            randomized.append((
                numpy.array([transformation.vector_apply(p) for p in points]),
                transformation
            ))

        for (ref_points, degenerate), (tr_points, transf) in zip(references, randomized):
            check_transf = superpose(ref_points, tr_points)
            # check whether the rotation matrix is orthogonal
            self.assertArraysAlmostEqual(numpy.dot(check_transf.r, check_transf.r.transpose()), numpy.identity(3, float), 1e-5)
            # first check whether check_transf brings the tr_points back to the ref_points
            check_points = numpy.dot(tr_points, check_transf.r.transpose()) + check_transf.t
            self.assertArraysAlmostEqual(ref_points, check_points, 1e-5, doabs=True)
            if not degenerate:
                # if the set of points is not degenerate, check whether transf and check_transf
                # are each other inverses
                tmp = Complete()
                tmp.apply_before(transf)
                tmp.apply_before(check_transf)
                self.assertArraysAlmostEqual(numpy.dot(transf.r, check_transf.r), numpy.identity(3, float), 1e-5)
                self.assertArrayAlmostZero(tmp.t, 1e-5)


        # Add some distortion to the transformed points
        randomized = []
        for tr_points, transf in randomized:
            tr_points[:] += numpy.random.normal(0, 1.0, len(tr_points))

        # Do a blind test
        for (ref_points, degenerate), (tr_points, transf) in zip(references, randomized):
            superpose(ref_points, tr_points)
Example #3
0
def coords_to_zeobuilder(org_coords, opt_coords, atoms, parent, graph=None):
    if graph == None:
        atomgroups = [numpy.arange(len(atoms))]
    else:
        atomgroups = graph.independent_nodes

    for group in atomgroups:
        group_org = org_coords[group]
        group_opt = opt_coords[group]
        # Transform the guessed geometry as to overlap with the original geometry
        transf = superpose(group_org, group_opt)
        group_opt = numpy.dot(group_opt, transf.r.transpose()) + transf.t

        # Put coordinates of guessed geometry back into Zeobuilder model
        for i,atomindex in enumerate(group):
            translation = Translation()
            atom = graph.molecule.atoms[atomindex]
            # Make sure atoms in subframes are treated properly
            transf = atom.parent.get_frame_relative_to(parent)
            org_pos = atom.transformation.t
            opt_pos = transf.vector_apply_inverse(group_opt[i])

            translation = Translation()
            translation.t = opt_pos - org_pos
            primitive.Transform(atom, translation)
Example #4
0
def coords_to_zeobuilder(org_coords, opt_coords, atoms, parent):
    # Transform the guessed geometry as to overlap with the original geometry
    transf = superpose(org_coords, opt_coords)
    opt_coords = numpy.dot(opt_coords, transf.r.transpose()) + transf.t

    # Put coordinates of guess geometry back into Zeobuilder model
    for i in xrange(len(atoms)):
        translation = Translation()
        atom = atoms[i]
        # Make sure atoms in subframes are treated properly
        transf = atom.parent.get_frame_relative_to(parent)
        org_pos = atom.transformation.t
        opt_pos = transf.vector_apply_inverse(opt_coords[i])
        translation.t = opt_pos - org_pos
        primitive.Transform(atom, translation)
Example #5
0
def fit_geometry(ref_coordinates, mtr, mtw, do_geom=False, do_transform=False, weights=None):
    """Fits a trajectorie of cartesian coordinates to a reference geometry

       This is the well-known rmsd fit typically performed on a trajectory after
       a long solute/solvent simulation (on the solute). It is based on the
       Kabsch algorithm:
       http://en.wikipedia.org/wiki/Kabsch_algorithm
       http://dx.doi.org/10.1107/S0567739476001873

       This implementation has a few features that are sorely missing in
       comparable software tools. One can optionally use the atomic masses as
       weights, which is a better approximation when one is interested in
       removing globale linear and angular momentum.

       Arguments:
         ref_coordinates  --  the reference coordinates to fit to (Nx3 array)
         mtr  --  A MultiTracksReader that iterates of the frames of the
                  trajectory.
         mtw  --  A MultiTracksWriter that writes out the rmsd, and optionally
                  the rotated and translated geometry (do_geom=True), and the
                  rotation matrix and translation vector. (do_transform=True)
         do_geom  --  When True, the rotated and translated geometry is also
                      written out
         do_transform  --  When True, the rotation matrix and translation vector
                           are also written
         weights  --  The weights to be used in the Kabsch algorithm
    """
    for frame in mtr:
        transform = superpose(ref_coordinates, frame[0], weights)
        new_coordinates = numpy.dot(frame[0], transform.r.transpose()) + transform.t
        rmsd = ((new_coordinates - ref_coordinates)**2).mean()
        row = [rmsd]
        if do_geom:
            row.append(new_coordinates)
        if do_transform:
            row.append(transform.t)
            row.append(transform.r)
        mtw.dump_row(tuple(row))
    mtw.finish()