Example #1
0
def superpositionFit(confs):
    """
    :param confs: the weight, reference position, and alternate
                  position for each atom
    :type confs: sequence of (float, Vector, Vector)
    :returns: the quaternion representing the rotation,
              the center of mass in the reference configuration,
              the center of mass in the alternate configuraton,
              and the RMS distance after the optimal superposition
    """
    w_sum = 0.
    wr_sum = N.zeros((3,), N.Float)
    for w, r_ref, r in confs:
        w_sum += w
        wr_sum += w*r_ref.array
    ref_cms = wr_sum/w_sum
    pos = N.zeros((3,), N.Float)
    possq = 0.
    cross = N.zeros((3, 3), N.Float)
    for w, r_ref, r in confs:
        w = w/w_sum
        r_ref = r_ref.array-ref_cms
        r = r.array
        pos = pos + w*r
        possq = possq + w*N.add.reduce(r*r) \
                      + w*N.add.reduce(r_ref*r_ref)
        cross = cross + w*r[:, N.NewAxis]*r_ref[N.NewAxis, :]
    k = N.zeros((4, 4), N.Float)
    k[0, 0] = -cross[0, 0]-cross[1, 1]-cross[2, 2]
    k[0, 1] = cross[1, 2]-cross[2, 1]
    k[0, 2] = cross[2, 0]-cross[0, 2]
    k[0, 3] = cross[0, 1]-cross[1, 0]
    k[1, 1] = -cross[0, 0]+cross[1, 1]+cross[2, 2]
    k[1, 2] = -cross[0, 1]-cross[1, 0]
    k[1, 3] = -cross[0, 2]-cross[2, 0]
    k[2, 2] = cross[0, 0]-cross[1, 1]+cross[2, 2]
    k[2, 3] = -cross[1, 2]-cross[2, 1]
    k[3, 3] = cross[0, 0]+cross[1, 1]-cross[2, 2]
    for i in range(1, 4):
        for j in range(i):
            k[i, j] = k[j, i]
    k = 2.*k
    for i in range(4):
        k[i, i] = k[i, i] + possq - N.add.reduce(pos*pos)
    from Scientific import LA
    e, v = LA.eigenvectors(k)
    i = N.argmin(e)
    v = v[i]
    if v[0] < 0: v = -v
    if e[i] <= 0.:
        rms = 0.
    else:
        rms = N.sqrt(e[i])
    from Scientific.Geometry import Quaternion
    return Quaternion.Quaternion(v), Vector(ref_cms), \
           Vector(pos), rms
Example #2
0
def superpositionFit(confs):
    """
    :param confs: the weight, reference position, and alternate
                  position for each atom
    :type confs: sequence of (float, Vector, Vector)
    :returns: the quaternion representing the rotation,
              the center of mass in the reference configuration,
              the center of mass in the alternate configuraton,
              and the RMS distance after the optimal superposition
    """
    w_sum = 0.
    wr_sum = N.zeros((3, ), N.Float)
    for w, r_ref, r in confs:
        w_sum += w
        wr_sum += w * r_ref.array
    ref_cms = wr_sum / w_sum
    pos = N.zeros((3, ), N.Float)
    possq = 0.
    cross = N.zeros((3, 3), N.Float)
    for w, r_ref, r in confs:
        w = w / w_sum
        r_ref = r_ref.array - ref_cms
        r = r.array
        pos = pos + w * r
        possq = possq + w*N.add.reduce(r*r) \
                      + w*N.add.reduce(r_ref*r_ref)
        cross = cross + w * r[:, N.NewAxis] * r_ref[N.NewAxis, :]
    k = N.zeros((4, 4), N.Float)
    k[0, 0] = -cross[0, 0] - cross[1, 1] - cross[2, 2]
    k[0, 1] = cross[1, 2] - cross[2, 1]
    k[0, 2] = cross[2, 0] - cross[0, 2]
    k[0, 3] = cross[0, 1] - cross[1, 0]
    k[1, 1] = -cross[0, 0] + cross[1, 1] + cross[2, 2]
    k[1, 2] = -cross[0, 1] - cross[1, 0]
    k[1, 3] = -cross[0, 2] - cross[2, 0]
    k[2, 2] = cross[0, 0] - cross[1, 1] + cross[2, 2]
    k[2, 3] = -cross[1, 2] - cross[2, 1]
    k[3, 3] = cross[0, 0] + cross[1, 1] - cross[2, 2]
    for i in range(1, 4):
        for j in range(i):
            k[i, j] = k[j, i]
    k = 2. * k
    for i in range(4):
        k[i, i] = k[i, i] + possq - N.add.reduce(pos * pos)
    from Scientific import LA
    e, v = LA.eigenvectors(k)
    i = N.argmin(e)
    v = v[i]
    if v[0] < 0: v = -v
    if e[i] <= 0.:
        rms = 0.
    else:
        rms = N.sqrt(e[i])
    from Scientific.Geometry import Quaternion
    return Quaternion.Quaternion(v), Vector(ref_cms), \
           Vector(pos), rms
Example #3
0
 def findTransformationAsQuaternion(self, conf1, conf2=None):
     universe = self.universe()
     if conf1.universe != universe:
         raise ValueError("conformation is for a different universe")
     if conf2 is None:
         conf1, conf2 = conf2, conf1
     else:
         if conf2.universe != universe:
             raise ValueError("conformation is for a different universe")
     ref = conf1
     conf = conf2
     weights = universe.masses()
     weights = weights / self.mass()
     ref_cms = self.centerOfMass(ref).array
     pos = Numeric.zeros((3, ), Numeric.Float)
     possq = 0.
     cross = Numeric.zeros((3, 3), Numeric.Float)
     for a in self.atomList():
         r = a.position(conf).array
         r_ref = a.position(ref).array - ref_cms
         w = weights[a]
         pos = pos + w * r
         possq = possq + w*Numeric.add.reduce(r*r) \
                       + w*Numeric.add.reduce(r_ref*r_ref)
         cross = cross + w * r[:,
                               Numeric.NewAxis] * r_ref[Numeric.NewAxis, :]
     k = Numeric.zeros((4, 4), Numeric.Float)
     k[0, 0] = -cross[0, 0] - cross[1, 1] - cross[2, 2]
     k[0, 1] = cross[1, 2] - cross[2, 1]
     k[0, 2] = cross[2, 0] - cross[0, 2]
     k[0, 3] = cross[0, 1] - cross[1, 0]
     k[1, 1] = -cross[0, 0] + cross[1, 1] + cross[2, 2]
     k[1, 2] = -cross[0, 1] - cross[1, 0]
     k[1, 3] = -cross[0, 2] - cross[2, 0]
     k[2, 2] = cross[0, 0] - cross[1, 1] + cross[2, 2]
     k[2, 3] = -cross[1, 2] - cross[2, 1]
     k[3, 3] = cross[0, 0] + cross[1, 1] - cross[2, 2]
     for i in range(1, 4):
         for j in range(i):
             k[i, j] = k[j, i]
     k = 2. * k
     for i in range(4):
         k[i, i] = k[i, i] + possq - Numeric.add.reduce(pos * pos)
     from Scientific import LA
     e, v = LA.eigenvectors(k)
     i = Numeric.argmin(e)
     v = v[i]
     if v[0] < 0: v = -v
     if e[i] <= 0.:
         rms = 0.
     else:
         rms = Numeric.sqrt(e[i])
     return Quaternion.Quaternion(v), Vector(ref_cms), \
            Vector(pos), rms
 def findTransformationAsQuaternion(self, conf1, conf2 = None):
     universe = self.universe()
     if conf1.universe != universe:
         raise ValueError("conformation is for a different universe")
     if conf2 is None:
         conf1, conf2 = conf2, conf1
     else:
         if conf2.universe != universe:
             raise ValueError("conformation is for a different universe")
     ref = conf1
     conf = conf2
     weights = universe.masses()
     weights = weights/self.mass()
     ref_cms = self.centerOfMass(ref).array
     pos = Numeric.zeros((3,), Numeric.Float)
     possq = 0.
     cross = Numeric.zeros((3, 3), Numeric.Float)
     for a in self.atomList():
         r = a.position(conf).array
         r_ref = a.position(ref).array-ref_cms
         w = weights[a]
         pos = pos + w*r
         possq = possq + w*Numeric.add.reduce(r*r) \
                       + w*Numeric.add.reduce(r_ref*r_ref)
         cross = cross + w*r[:, Numeric.NewAxis]*r_ref[Numeric.NewAxis, :]
     k = Numeric.zeros((4, 4), Numeric.Float)
     k[0, 0] = -cross[0, 0]-cross[1, 1]-cross[2, 2]
     k[0, 1] = cross[1, 2]-cross[2, 1]
     k[0, 2] = cross[2, 0]-cross[0, 2]
     k[0, 3] = cross[0, 1]-cross[1, 0]
     k[1, 1] = -cross[0, 0]+cross[1, 1]+cross[2, 2]
     k[1, 2] = -cross[0, 1]-cross[1, 0]
     k[1, 3] = -cross[0, 2]-cross[2, 0]
     k[2, 2] = cross[0, 0]-cross[1, 1]+cross[2, 2]
     k[2, 3] = -cross[1, 2]-cross[2, 1]
     k[3, 3] = cross[0, 0]+cross[1, 1]-cross[2, 2]
     for i in range(1, 4):
         for j in range(i):
             k[i, j] = k[j, i]
     k = 2.*k
     for i in range(4):
         k[i, i] = k[i, i] + possq - Numeric.add.reduce(pos*pos)
     from Scientific import LA
     e, v = LA.eigenvectors(k)
     i = Numeric.argmin(e)
     v = v[i]
     if v[0] < 0: v = -v
     if e[i] <= 0.:
         rms = 0.
     else:
         rms = Numeric.sqrt(e[i])
     return Quaternion.Quaternion(v), Vector(ref_cms), \
            Vector(pos), rms
    def __init__(self, trajectory, object, first=0, last=None, skip=1,
                 reference = None):
        self.trajectory = trajectory
        universe = trajectory.universe
        if last is None: last = len(trajectory)
        first_conf = trajectory.configuration[first]
        offset = universe.contiguousObjectOffset([object], first_conf, True)
        if reference is None:
            reference = first_conf
        reference = universe.contiguousObjectConfiguration([object], reference)
        steps = (last-first+skip-1)/skip
        mass = object.mass()
        ref_cms = object.centerOfMass(reference)
        atoms = object.atomList()

        possq = N.zeros((steps,), N.Float)
        cross = N.zeros((steps, 3, 3), N.Float)
        rcms = N.zeros((steps, 3), N.Float)

        # cms of the CONTIGUOUS object made of CONTINUOUS atom trajectories 
        for a in atoms:
            r = trajectory.readParticleTrajectory(a, first, last, skip,
                                                  "box_coordinates").array
            w = a._mass/mass
            N.add(rcms, w*r, rcms)
            if offset is not None:
                N.add(rcms, w*offset[a].array, rcms)
        
        # relative coords of the CONTIGUOUS reference
        r_ref = N.zeros((len(atoms), 3), N.Float)
        for a in range(len(atoms)):
            r_ref[a] = atoms[a].position(reference).array - ref_cms.array

        # main loop: storing data needed to fill M matrix 
        for a in range(len(atoms)):
            r = trajectory.readParticleTrajectory(atoms[a],
                                                  first, last, skip,
                                                  "box_coordinates").array
            r = r - rcms # (a-b)**2 != a**2 - b**2
            if offset is not None:
                N.add(r, offset[atoms[a]].array,r)
            trajectory._boxTransformation(r, r)
            w = atoms[a]._mass/mass
            N.add(possq, w*N.add.reduce(r*r, -1), possq)
            N.add(possq, w*N.add.reduce(r_ref[a]*r_ref[a],-1),
                        possq)
            N.add(cross, w*r[:,:,N.NewAxis]*r_ref[N.NewAxis,
                                                              a,:],cross)
        self.trajectory._boxTransformation(rcms, rcms)

        # filling matrix M (formula no 40)
        k = N.zeros((steps, 4, 4), N.Float)
        k[:, 0, 0] = -cross[:, 0, 0]-cross[:, 1, 1]-cross[:, 2, 2]
        k[:, 0, 1] = cross[:, 1, 2]-cross[:, 2, 1]
        k[:, 0, 2] = cross[:, 2, 0]-cross[:, 0, 2]
        k[:, 0, 3] = cross[:, 0, 1]-cross[:, 1, 0]
        k[:, 1, 1] = -cross[:, 0, 0]+cross[:, 1, 1]+cross[:, 2, 2]
        k[:, 1, 2] = -cross[:, 0, 1]-cross[:, 1, 0]
        k[:, 1, 3] = -cross[:, 0, 2]-cross[:, 2, 0]
        k[:, 2, 2] = cross[:, 0, 0]-cross[:, 1, 1]+cross[:, 2, 2]
        k[:, 2, 3] = -cross[:, 1, 2]-cross[:, 2, 1]
        k[:, 3, 3] = cross[:, 0, 0]+cross[:, 1, 1]-cross[:, 2, 2]
        del cross
        for i in range(1, 4):
            for j in range(i):
                k[:, i, j] = k[:, j, i]
        N.multiply(k, 2., k)
        for i in range(4):
            N.add(k[:,i,i], possq, k[:,i,i])
        del possq

        quaternions = N.zeros((steps, 4), N.Float)
        fit = N.zeros((steps,), N.Float)
        from Scientific.LA import eigenvectors
        for i in range(steps):
            e, v = eigenvectors(k[i])
            j = N.argmin(e)
            if e[j] < 0.:
                fit[i] = 0.
            else:
                fit[i] = N.sqrt(e[j])
            if v[j,0] < 0.: quaternions[i] = -v[j] # eliminate jumps
            else: quaternions[i] = v[j]
        self.fit = fit
        self.cms = rcms
        self.quaternions = quaternions