Beispiel #1
0
def methylCC(molecule, Nuc=None, resids=None, segids=None, filter_str=None):
    """
    Superimposes the C-X bond attached to a methyl carbon, and can separate
    methyl rotation from re-orientation of the overall methyl group
    
    Note- we only return one copy of the C–C bond, so a frame index is necessary
    """
    if not (Nuc.lower() == 'ivl' or Nuc.lower() == 'ivla'
            or Nuc.lower() == 'ch3'):
        print('Nuc must be ivl, ivla, or ch3 for the methylCC frame')
        return
    elif Nuc is None:
        Nuc = 'ch3'
    selC1, _ = selt.protein_defaults(Nuc, molecule, resids, segids, filter_str)
    selC1 = selC1[::3]  #Above line returns 3 copies of each carbon

    sel0 = molecule.mda_object.atoms
    sel0 = sel0.residues[np.isin(sel0.residues.resids, selC1.resids)].atoms

    selC2=sum([sel0.select_atoms('not name H* and around 1.6 atom {0} {1} {2}'\
                                 .format(s.segid,s.resid,s.name)) for s in selC1])

    def sub():
        box = molecule.mda_object.dimensions[:3]
        v = selC1.positions - selC2.positions
        v = vft.pbc_corr(v.T, box)
        return v

    return sub
Beispiel #2
0
def LabZ(molecule,
         sel1=None,
         sel2=None,
         Nuc=None,
         resids=None,
         segids=None,
         filter_str=None):
    """Motion projected to the Z-axis of the Lab frame. Use only for systems
    that remain aligned along z
    """
    if Nuc is not None:
        sel1, sel2 = selt.protein_defaults(Nuc, molecule, resids, segids,
                                           filter_str)
    else:
        sel1 = selt.sel_simple(molecule, sel1, resids, segids, filter_str)
        sel2 = selt.sel_simple(molecule, sel2, resids, segids, filter_str)
    uni = molecule.mda_object

    def sub():
        box = uni.dimensions[0:3]
        v = sel1.positions - sel2.positions
        v = vft.pbc_corr(v.T, box)
        v[:2] = 0
        return v

    return sub
Beispiel #3
0
def bond(molecule,
         sel1=None,
         sel2=None,
         sel3=None,
         Nuc=None,
         resids=None,
         segids=None,
         filter_str=None):
    """Bond defines the frame. 
    sel1/sel2   :   Defines the z-axis of the frame (the bond itself). Follows 
                    the argument rules of sel_simple (sel2 should usually be
                    the heteroatom) 
    Nuc         :   Automatically sets sel1 and sel2 for a given nucleus definition
    sel3        :   sel2 and sel3 will define the xz-plane of the bond frame. 
                    This is optional: however, if this frame is the PAS of the
                    bond responsible for relaxation, then frames may not 
                    function correctly if this is not provided. By default, sel3
                    is set to None and is omitted. However, if called from within
                    mol.
    resids, segids, filter_str apply additional filters to sel1, sel2, and sel3
    if defined.
    """
    if Nuc is not None:
        sel1, sel2 = selt.protein_defaults(Nuc, molecule, resids, segids,
                                           filter_str)
    else:
        sel1 = selt.sel_simple(molecule, sel1, resids, segids, filter_str)
        sel2 = selt.sel_simple(molecule, sel2, resids, segids, filter_str)

    if isinstance(sel3, str) and sel3 == 'auto':
        uni = sel1.universe
        resids = np.unique(sel1.resids)
        sel0 = uni.residues[np.isin(uni.residues.resids, resids)].atoms
        sel3 = selt.find_bonded(sel2, sel0, exclude=sel1, n=1,
                                sort='cchain')[0]
    elif sel3 is not None:
        sel3 = selt.sel_simple(molecule, sel3, resids, segids, filter_str)

    uni = molecule.mda_object

    if sel3 is None:

        def sub():
            box = uni.dimensions[0:3]
            v = sel1.positions - sel2.positions
            v = vft.pbc_corr(v.T, box)
            return v
    else:

        def sub():
            box = uni.dimensions[0:3]
            vZ = sel1.positions - sel2.positions
            vXZ = sel3.positions - sel2.positions
            vZ = vft.pbc_corr(vZ.T, box)
            vXZ = vft.pbc_corr(vXZ.T, box)
            return vZ, vXZ

    return sub
Beispiel #4
0
def bond_rotate(molecule,
                sel1=None,
                sel2=None,
                sel3=None,
                Nuc=None,
                resids=None,
                segids=None,
                filter_str=None):
    """
    Rotation around a given bond, defined by sel1 and sel2. Has a very similar
    effect to simply using bond with the same sel1 and sel2. However, an addition
    selection is created to a third atom. Then, the vector between sel1 and
    sel2 defines the rotation axis. However, rotation around this axis caused
    by more distant motions is removed, because a third selection (sel3) is
    used with sel2 to create a second vector, which then remains in the xz plane
    
    (if only sel1 and sel2 are specified for rotation, then some rotation further
    up a carbon chain, for example, may not move the vector between sel1 and sel2,
    but does cause rotation of the inner bonds- in most cases it is not clear if
    this is happening, but becomes particularly apparent when rotation appears
    on double bonds, where rotation should be highly restricted)
    
    sel3 may be defined, but is not required. If it is not provided, a third 
    atom will be found that is bound to sel2 (this frame won't work if sel2 is
    not bound to any other atom). 
    """

    if Nuc is not None:
        sel1, sel2 = selt.protein_defaults(Nuc, molecule, resids, segids,
                                           filter_str)
    else:
        sel1 = selt.sel_simple(molecule, sel1, resids, segids, filter_str)
        sel2 = selt.sel_simple(molecule, sel2, resids, segids, filter_str)

    if sel3 is not None:
        sel3 = selt.sel_simple(molecule, sel3, resids, segids, filter_str)
    else:
        resids = np.unique(sel1.resids)
        i = np.isin(sel1.universe.residues.resids,
                    resids)  #Filter for atoms in the same residues
        sel0 = sel1.universe.residues[i].atoms
        sel3 = selt.find_bonded(sel2, sel0, sel1, n=1, sort='cchain')[0]

    uni = molecule.mda_object

    def sub():
        box = uni.dimensions[0:3]
        v1 = sel1.positions - sel2.positions
        v2 = sel2.positions - sel3.positions
        v1 = vft.pbc_corr(v1.T, box)
        v2 = vft.pbc_corr(v2.T, box)
        return v1, v2

    return sub
Beispiel #5
0
def chain_rotate(molecule,
                 sel=None,
                 Nuc=None,
                 resids=None,
                 segids=None,
                 filter_str=None):
    """
    Creates a frame for which a chain of atoms (usually carbons) is aligned
    such that the vector formed by the previous and next heteroatom (not 1H)
    are aligned along z.
    
    Note that the frame is selected with a single initial selection, and the
    function automatically searches for the surrounding atoms. In case a methyl
    carbon is included, the rotation is defined by the carbon itself and its
    nearest neighbor, instead of the surrounding two atoms (which would then
    have to include a methyl proton)
    """

    uni = molecule.mda_object

    "Get the initial selection"
    if Nuc is not None:
        sel, _ = selt.protein_defaults(Nuc, molecule, resids, segids,
                                       filter_str)
    else:
        sel = selt.sel_simple(molecule, sel, resids, segids, filter_str)

    "Get all atoms in the residues included in the initial selection"
    resids = np.unique(sel.resids)
    sel0 = uni.residues[np.isin(uni.residues.resids, resids)].atoms

    "Get bonded"
    sel1, sel2 = selt.find_bonded(sel, sel0=sel0, n=2, sort='cchain')

    "Replace 1H with the original selection"
    i = sel2.types == 'H'

    sel20 = sel2
    sel2 = uni.atoms[:0]
    for s2, s, i0 in zip(sel20, sel, i):
        if i0:
            sel2 += s
        else:
            sel2 += s2

    def sub():
        box = uni.dimensions[0:3]
        v = sel2.positions - sel1.positions
        v = vft.pbc_corr(v.T, box)
        return v

    return sub
Beispiel #6
0
    def select_atoms(self,
                     sel1=None,
                     sel2=None,
                     sel1in=None,
                     sel2in=None,
                     Nuc=None,
                     resids=None,
                     segids=None,
                     filter_str=None):
        """
        Selects the atoms to be used for bond definitions. 
        sel1/sel2 : A string or an atom group (MDanalysis) defining the 
                    first/second atom in the bond
        sel1in/sel2in : Index to re-assign sel1/sel2 possibly to multiple bonds
                        (example: if using string assignment, maybe to calculate
                        for multiple H's bonded to the same C)
        Nuc : Keyword argument for selecting a particular type of bond 
              (for example, N, C, CA would selection NH, C=O bonds, or CA-HA 
              bonds, respectively)
        resids : Filter the selection defined by the above arguments for only
                 certain residues
        segids : Filter the selection defined by the above arguments for only 
                 certain segments
        filter_str : Filter the selection by a string (MDAnalysis string selection)
        """

        if Nuc is None:
            "Apply sel1 and sel2 selections directly"
            if sel1 is not None:
                self.sel1 = selt.sel_simple(self, sel1, resids, segids,
                                            filter_str)
                if sel1in is not None:
                    self.sel1 = self.sel1[sel1in]
            if sel2 is not None:
                self.sel2 = selt.sel_simple(self, sel2, resids, segids,
                                            filter_str)
                if sel2in is not None:
                    self.sel2 = self.sel2[sel2in]
        else:
            self.sel1, self.sel2 = selt.protein_defaults(
                Nuc, self, resids, segids, filter_str)

        if self.sel1 is not None and self.sel2 is not None and self.sel1.n_atoms == self.sel2.n_atoms:
            self.set_selection()

            "An attempt to generate a unique label under various conditions"
            count, cont = 0, True
            while cont:
                if count == 0:  #One bond per residue- just take the residue number
                    label = self.sel1.resids
                elif count == 1:  #Multiple segments with same residue numbers
                    label = np.array([
                        '{0}_{1}'.format(s.segid, s.resid) for s in self.sel1
                    ])
                elif count == 2:  #Same segment, but multiple bonds on the same residue (include names)
                    label = np.array([
                        '{0}_{1}_{2}'.format(s1.resid, s1.name, s2.name)
                        for s1, s2 in zip(self.sel1, self.sel2)
                    ])
                elif count == 3:  #Multiple bonds per residue, and multiple segments
                    label=np.array(['{0}_{1}_{2}_{3}'.format(s1.segid,s1.resid,s1.name,s2.name) \
                                    for s1,s2 in zip(self.sel1,self.sel2)])
                "We give up after this"
                count = count + 1
                if np.unique(label).size == label.size or count == 4:
                    cont = False

            self.label = label
Beispiel #7
0
def MOIbeta(molecule,
            sel,
            sel1=None,
            sel2=None,
            Nuc=None,
            index=None,
            resids=None,
            segids=None,
            filter_str=None):
    """
    Separates out rotation within the moment of inertia frame (should be used in
    conjunction with MOIz). That is, we identify rotational motion, where the z-axis
    is the direction of the Moment of Inertia vector. 
    
    The user must provide one or more selections to define the moment of inertia 
    (sel). The user must also provide the selections to which the MOI is applied
    (sel1 and sel2, or Nuc). Additional filters will be used as normal, applied 
    to all selections (resids,segids,filter_str). In case multiple MOI selections
    are provided (in a list), the user must provide an index, to specifify which
    bond goes with which MOI selection. This should usually be the same variable
    as provided for the frame_index when using MOIz (and one will usually not
    use a frame_index when setting up this frame)
    
    MOIxy(sel,sel1=None,sel2=None,Nuc=None,index=None,resids=None,segids=None,filter_str=None)
    """

    sel = selt.sel_lists(molecule, sel, resids, segids, filter_str)

    if Nuc is not None:
        sel1, sel2 = selt.protein_defaults(Nuc, molecule, resids, segids,
                                           filter_str)
    else:
        sel1 = selt.sel_simple(molecule, sel1, resids, segids, filter_str)
        sel2 = selt.sel_simple(molecule, sel2, resids, segids, filter_str)

    uni = molecule.mda_object
    uni.trajectory[0]

    sel = selt.sel_lists(molecule, sel, resids, segids, filter_str)
    uni = molecule.mda_object
    uni.trajectory[0]

    box = uni.dimensions[:3]

    for k, s in enumerate(sel):
        vr = s.positions
        i0 = vft.sort_by_dist(vr)
        sel[k] = sel[k][i0]

    vref = list()
    for s in sel:
        v0 = vft.pbc_pos(s.positions.T, box)
        vref.append(vft.principle_axis_MOI(v0)[:, 0])

    def MOIsub():
        v = list()
        box = uni.dimensions[:3]
        for s, vr in zip(sel, vref):
            v0 = vft.pbc_pos(s.positions.T, box)
            v1 = vft.principle_axis_MOI(v0)[:, 0]
            v.append(v1 * np.sign(np.dot(v1, vr)))
        return np.array(v).T

#    for k,s in enumerate(sel):
#        vr=s.positions
#        i0=vft.sort_by_dist(vr)
#        sel[k]=sel[k][i0]

    if index is None:
        if len(sel) == 1:
            index = np.zeros(sel1.n_atoms, dtype=int)
        elif len(sel) == sel1.n_atoms:
            index = np.arange(sel1.n_atoms, dtype=int)
        else:
            print('index must be defined')
            return

#    vref=list()
#    box=uni.dimensions[:3]
#    for s in sel:
#        v0=vft.pbc_pos(s.positions.T,box)
#        vref.append(vft.principle_axis_MOI(v0)[:,0])

    def sub():
        vnorm = MOIsub()
        #Pre-allocate output vector, to point along z
        vZ = np.zeros([3, sel1.n_atoms])
        vZ[2] = 1  #If a bond not in index, then vZ just on Z
        #        vXZ=np.zeros([3,sel1.n_atoms])
        #        vXZ[0]=1    #If a bond not in index, then vXZ just along x

        sc = np.array(vft.getFrame(vnorm)).T
        v00 = vft.norm(vft.pbc_corr((sel1.positions - sel2.positions).T, box))

        for k, (vn, sc0) in enumerate(zip(vnorm.T, sc)):
            v0 = v00[:, k == index]
            cb = v0[0] * vn[0] + v0[1] * vn[1] + v0[2] * vn[
                2]  #Angle between MOI and bond
            cb[cb > 1] = 1.0
            sb = np.sqrt(1 - cb**2)
            v0 = np.concatenate(([sb], [np.zeros(sb.shape)], [cb]), axis=0)
            "Here, we keep the vector fixed in the xz plane of the MOI frame"
            vZ[:, k == index] = vft.R(v0, *sc0)
#            vZ[:,k==index]=v0
#            vXZ[:,k==index]=np.atleast_2d(vn).T.repeat(v0.shape[1],1)

        return vZ

    return sub
Beispiel #8
0
def MOIxy(molecule,
          sel,
          sel1=None,
          sel2=None,
          Nuc=None,
          index=None,
          resids=None,
          segids=None,
          filter_str=None):
    """
    Separates out rotation within the moment of inertia frame (should be used in
    conjunction with MOIz). That is, we identify rotational motion, where the z-axis
    is the direction of the Moment of Inertia vector. 
    
    The user must provide one or more selections to define the moment of inertia 
    (sel). The user must also provide the selections to which the MOI is applied
    (sel1 and sel2, or Nuc). Additional filters will be used as normal, applied 
    to all selections (resids,segids,filter_str). In case multiple MOI selections
    are provided (in a list), the user must provide an index, to specifify which
    bond goes with which MOI selection. This should usually be the same variable
    as provided for the frame_index when using MOIz (and one will usually not
    use a frame_index when setting up this frame)
    
    MOIxy(sel,sel1=None,sel2=None,Nuc=None,index=None,resids=None,segids=None,filter_str=None)
    """

    sel = selt.sel_lists(molecule, sel, resids, segids, filter_str)

    if Nuc is not None:
        sel1, sel2 = selt.protein_defaults(Nuc, molecule, resids, segids,
                                           filter_str)
    else:
        sel1 = selt.sel_simple(molecule, sel1, resids, segids, filter_str)
        sel2 = selt.sel_simple(molecule, sel2, resids, segids, filter_str)

    uni = molecule.mda_object
    uni.trajectory[0]

    for k, s in enumerate(sel):
        vr = s.positions
        i0 = vft.sort_by_dist(vr)
        sel[k] = sel[k][i0]

    if index is None:
        if len(sel) == 1:
            index = np.zeros(sel1.n_atoms, dtype=int)
        elif len(sel) == sel1.n_atoms:
            index = np.arange(sel1.n_atoms, dtype=int)
        else:
            print('index must be defined')
            return

    def sub():
        vnorm = list()
        box = uni.dimensions[:3]
        for s in sel:
            v0 = vft.pbc_pos(s.positions.T, box)
            vnorm.append(vft.principle_axis_MOI(v0)[:, 0])
        vnorm = np.array(vnorm)

        #Pre-allocate output vector, to point along z
        v1 = np.zeros([3, sel1.n_atoms])
        v1[2] = 1
        v2 = v1.copy()

        v0 = vft.pbc_corr((sel1.positions - sel2.positions).T, box)
        for k, vn in enumerate(vnorm):
            v1[:, k == index] = vft.projXY(v0[:, k == index], vn)
            v2[:, k == index] = np.array([vn]).T.repeat((k == index).sum(),
                                                        axis=1)

        return v1, v2

    return sub
Beispiel #9
0
def librations0(molecule,
                sel1=None,
                sel2=None,
                Nuc=None,
                resids=None,
                segids=None,
                filter_str=None):
    """
    Defines a frame for which librations are visible. That is, for a given bond,
    defined by sel1 and sel2, we search for two other atoms bound to the 
    heteroatom (by distance). The reference frame is then defined by the 
    heteroatom and the additional two atoms, leaving primarily librational
    motion of the bond. We preferentially select the other two atoms for larger
    masses, but they may also be protons (for example, a methyl H–C bond will 
    be referenced to the next carbon but also another one of the protons of 
    the methyl group)
    
    In case the heteroatom only has two bound partners, the second atom in the
    bond will also be used for alignment, reducing the effect motion
    (not very common in biomolecules)
    
    librations(sel1,sel2,Nuc,resids,segids,filter_str)
    """
    if Nuc is not None:
        sel1, sel2 = selt.protein_defaults(Nuc, molecule, resids, segids,
                                           filter_str)
    else:
        sel1 = selt.sel_simple(molecule, sel1, resids, segids, filter_str)
        sel2 = selt.sel_simple(molecule, sel2, resids, segids, filter_str)

    if sel1.masses.sum() < sel2.masses.sum():
        sel1, sel2 = sel2, sel1  #Make sel1 the heteroatom

    resids = np.unique(sel1.resids)
    i = np.isin(sel1.universe.residues.resids,
                resids)  #Filter for atoms in the same residues
    sel0 = sel1.universe.residues[i].atoms
    sel2, sel3, sel4, sel5 = selt.find_bonded(sel1, sel0, n=4, sort='mass')

    def vfun():
        v = list()
        for v1, v2, v3, v4, v5 in zip(sel1, sel2, sel3, sel4, sel5):
            v0 = np.array([
                v2.position - v1.position, v3.position - v1.position,
                v4.position - v1.position, v5.position - v1.position
            ])
            box = uni.dimensions[:3]
            v.append(vft.pbc_corr(v0.T, box))
        return v

    uni = molecule.mda_object
    uni.trajectory.rewind()

    vref = vfun()

    def sub():
        R = list()
        vecs = vfun()
        R = [vft.RMSalign(vr, v) for v, vr in zip(vecs, vref)]
        return vft.R2vec(R)

    return sub