예제 #1
0
def random_ellipsoid(box, size, min_axis):

    # return a random ellipsoid record of the form:
    # [ ELLIPSOID, x_pos, y_pos, z_pos, size, x0, y0, z0, x1, y1, z2, x2, y2, z2 ]
    # where the xyz vectors are orthogonal and of length 1.0 or less.
    
    box = box - size
    tmp0 = cpv.random_vector()
    tmp1 = cpv.random_vector()
    tmp2 = cpv.cross_product(tmp1, tmp0)
    tmp3 = cpv.cross_product(tmp1, tmp2)
    tmp4 = cpv.cross_product(tmp2, tmp3)
    tmp2 = cpv.normalize(tmp2)
    tmp3 = cpv.normalize(tmp3)
    tmp4 = cpv.normalize(tmp4)
    primary = cpv.scale(tmp2, random())
    secondary = cpv.scale(tmp3,random())
    tertiary = cpv.scale(tmp4,random())
    factor = 1.0 / max( cpv.length(primary), cpv.length(secondary), cpv.length(tertiary))
    primary = cpv.scale(primary, factor)
    secodary = cpv.scale(secondary, factor)
    tertiary = cpv.scale(tertiary, factor)
    return [ ELLIPSOID,
             size + random() * box, size + random() * box, size + random() * box,
             max(random() * size, min_axis),
             ] + primary + secondary + tertiary
예제 #2
0
def visualize_orientation(direction,
                          center=[0.0] * 3,
                          scale=1.0,
                          symmetric=False,
                          color='green',
                          color2='red'):
    '''
DESCRIPTION

    Draw an arrow. Helper function for "helix_orientation" etc.
    '''
    from pymol import cgo

    color_list = cmd.get_color_tuple(color)
    color2_list = cmd.get_color_tuple(color2)

    if symmetric:
        scale *= 0.5
    end = cpv.add(center, cpv.scale(direction, scale))
    radius = 0.3

    obj = [cgo.SAUSAGE]
    obj.extend(center)
    obj.extend(end)
    obj.extend([
        radius,
        0.8,
        0.8,
        0.8,
    ])
    obj.extend(color_list)

    if symmetric:
        start = cpv.sub(center, cpv.scale(direction, scale))
        obj.append(cgo.SAUSAGE)
        obj.extend(center)
        obj.extend(start)
        obj.extend([
            radius,
            0.8,
            0.8,
            0.8,
        ])
        obj.extend(color2_list)

    coneend = cpv.add(
        end, cpv.scale(direction, 4.0 * radius / cpv.length(direction)))
    obj.append(cgo.CONE)
    obj.extend(end)
    obj.extend(coneend)
    obj.extend([
        radius * 1.75,
        0.0,
    ])
    obj.extend(color_list * 2)
    obj.extend([
        1.0,
        1.0,  # Caps
    ])
    cmd.load_cgo(obj, get_unused_name('oriVec'), zoom=0)
예제 #3
0
    def pdbBox(line):
        ''' Parses a gro box line and returns a pdb CRYST1 line '''
        from math import degrees
        from chempy.cpv import length, get_angle

        v = [10*float(i) for i in line.split()] + 6*[0] # Padding for rectangular boxes
        v1, v2, v3 = (v[0], v[3], v[4]), (v[5], v[1], v[6]), (v[7], v[8], v[2])

        a = length(v1)
        b = length(v2)
        c = length(v3)

        alpha = degrees(get_angle(v2, v3))
        beta = degrees(get_angle(v1, v3))
        gamma = degrees(get_angle(v1, v2))

        return _pdbBoxLine % (a, b, c, alpha, beta, gamma)
예제 #4
0
    def pdbBox(line):
        ''' Parses a gro box line and returns a pdb CRYST1 line '''
        from math import degrees
        from chempy.cpv import length, get_angle

        v = [10*float(i) for i in line.split()] + 6*[0] # Padding for rectangular boxes
        v1, v2, v3 = (v[0], v[3], v[4]), (v[5], v[1], v[6]), (v[7], v[8], v[2])

        a = length(v1)
        b = length(v2)
        c = length(v3)

        alpha = degrees(get_angle(v2, v3))
        beta = degrees(get_angle(v1, v3))
        gamma = degrees(get_angle(v1, v2))

        return _pdbBoxLine % (a, b, c, alpha, beta, gamma)
예제 #5
0
def visualize_orientation(direction, center=[0.0]*3, scale=1.0, symmetric=False, color='green', color2='red'):
    '''
DESCRIPTION

    Draw an arrow. Helper function for "helix_orientation" etc.
    '''
    from pymol import cgo

    color_list = cmd.get_color_tuple(color)
    color2_list = cmd.get_color_tuple(color2)

    if symmetric:
        scale *= 0.5
    end = cpv.add(center, cpv.scale(direction, scale))
    radius = 0.3

    obj = [cgo.SAUSAGE]
    obj.extend(center)
    obj.extend(end)
    obj.extend([
        radius,
        0.8, 0.8, 0.8,
    ])
    obj.extend(color_list)

    if symmetric:
        start = cpv.sub(center, cpv.scale(direction, scale))
        obj.append(cgo.SAUSAGE)
        obj.extend(center)
        obj.extend(start)
        obj.extend([
            radius,
            0.8, 0.8, 0.8,
        ])
        obj.extend(color2_list)

    coneend = cpv.add(end, cpv.scale(direction, 4.0*radius/cpv.length(direction)))
    obj.append(cgo.CONE)
    obj.extend(end)
    obj.extend(coneend)
    obj.extend([
        radius * 1.75,
        0.0,
    ])
    obj.extend(color_list * 2)
    obj.extend([
        1.0, 1.0, # Caps
    ])
    cmd.load_cgo(obj, get_unused_name('oriVec'), zoom=0)
예제 #6
0
 def scramble(self,mode):
     if self.cmd.count_atoms(self.sculpt_object):
         sc_tmp = "_scramble_tmp"
         if mode == 0:
             self.cmd.select(sc_tmp,self.sculpt_object+
                         " and not (fixed or restrained)")
         if mode == 1:
             self.cmd.select(sc_tmp,self.sculpt_object+
                         " and not (fixed)")
         extent = self.cmd.get_extent(sc_tmp)
         center = self.cmd.get_position(sc_tmp)
         radius = 1.25*cpv.length(cpv.sub(extent[0],extent[1]))
         self.cmd.alter_state(self.cmd.get_state(), sc_tmp,
                              "(x,y,z)=rsp(pos,rds)",
             space= { 'rsp' :  cpv.random_displacement,
                      'pos' : center,
                      'rds' : radius })
         self.cmd.delete(sc_tmp)
예제 #7
0
 def scramble(self,mode):
     if self.cmd.count_atoms(self.sculpt_object):
         sc_tmp = "_scramble_tmp"
         if mode == 0:
             self.cmd.select(sc_tmp,self.sculpt_object+
                         " and not (fixed or restrained)")
         if mode == 1:
             self.cmd.select(sc_tmp,self.sculpt_object+
                         " and not (fixed)")
         extent = self.cmd.get_extent(sc_tmp)
         center = self.cmd.get_position(sc_tmp)
         radius = 1.25*cpv.length(cpv.sub(extent[0],extent[1]))
         self.cmd.alter_state(self.cmd.get_state(), sc_tmp,
                              "(x,y,z)=rsp(pos,rds)",
             space= { 'rsp' :  cpv.random_displacement,
                      'pos' : center,
                      'rds' : radius })
         self.cmd.delete(sc_tmp)
def helix_orientation_hbond(selection, visualize=1, cutoff=3.5, quiet=0):
    '''
DESCRIPTION

    Get the center and direction of a helix as vectors. Will only work
    for alpha helices and gives slightly different results than
    helix_orientation. Averages direction of O(i)->N(i+4) hydrogen bonds.

USAGE

    helix_orientation selection [, visualize [, cutoff]]

ARGUMENTS

    cutoff = float: maximal hydrogen bond distance {default: 3.5}

SEE ALSO

    helix_orientation
    '''
    visualize, quiet, cutoff = int(visualize), int(quiet), float(cutoff)
    stored.x = dict()
    cmd.iterate_state(STATE, '(%s) and name N+O' % (selection),
                      'stored.x.setdefault(resv, dict())[name] = x,y,z')
    vec_list = []
    for resi in stored.x:
        resi_other = resi + 4
        if 'O' in stored.x[resi] and resi_other in stored.x:
            if 'N' in stored.x[resi_other]:
                vec = cpv.sub(stored.x[resi_other]['N'], stored.x[resi]['O'])
                if cpv.length(vec) < cutoff:
                    vec_list.append(vec)
    if len(vec_list) == 0:
        print 'warning: count == 0'
        raise CmdException
    vec = _vec_sum(vec_list)
    vec = cpv.normalize(vec)
    return _common_orientation(selection, vec, visualize, quiet)
def helix_orientation_hbond(selection, visualize=1, cutoff=3.5, quiet=0):
    '''
DESCRIPTION

    Get the center and direction of a helix as vectors. Will only work
    for alpha helices and gives slightly different results than
    helix_orientation. Averages direction of O(i)->N(i+4) hydrogen bonds.

USAGE

    helix_orientation selection [, visualize [, cutoff]]

ARGUMENTS

    cutoff = float: maximal hydrogen bond distance {default: 3.5}

SEE ALSO

    helix_orientation
    '''
    visualize, quiet, cutoff = int(visualize), int(quiet), float(cutoff)
    stored.x = dict()
    cmd.iterate_state(STATE, '(%s) and name N+O' % (selection),
                      'stored.x.setdefault(resv, dict())[name] = x,y,z')
    vec_list = []
    for resi in stored.x:
        resi_other = resi + 4
        if 'O' in stored.x[resi] and resi_other in stored.x:
            if 'N' in stored.x[resi_other]:
                vec = cpv.sub(stored.x[resi_other]['N'], stored.x[resi]['O'])
                if cpv.length(vec) < cutoff:
                    vec_list.append(vec)
    if len(vec_list) == 0:
        print 'warning: count == 0'
        raise CmdException
    vec = _vec_sum(vec_list)
    vec = cpv.normalize(vec)
    return _common_orientation(selection, vec, visualize, quiet)
예제 #10
0
    def compute_surface_normals():
        '''
        Compute average normals from all adjacent triangles
        on each vertex
        '''
        from functools import reduce

        # don't use cpv.normalize which has an RSMALL4 limit
        normalize = lambda v: cpv.scale(v, 1. / cpv.length(v))

        for face in table['face']:
            if 'vertex_index' in face:
                indices = face['vertex_index']
            elif 'vertex_indices' in face:
                indices = face['vertex_indices']
            else:
                return

            f_vert = [vertices[i] for i in indices]
            f_xyz = [(v['x'], v['y'], v['z']) for v in f_vert]

            try:
                normal = normalize(cpv.cross_product(
                    cpv.sub(f_xyz[1], f_xyz[0]),
                    cpv.sub(f_xyz[2], f_xyz[1])))
            except ZeroDivisionError:
                continue

            for v in f_vert:
                v.setdefault('normals', []).append(normal)

        for v in vertices:
            try:
                v['nx'], v['ny'], v['nz'] = normalize(
                        reduce(cpv.add, v.pop('normals')))
            except (KeyError, ZeroDivisionError):
                continue
예제 #11
0
    def compute_surface_normals():
        '''
        Compute average normals from all adjacent triangles
        on each vertex
        '''
        from functools import reduce

        # don't use cpv.normalize which has an RSMALL4 limit
        normalize = lambda v: cpv.scale(v, 1. / cpv.length(v))

        for face in table['face']:
            if 'vertex_index' in face:
                indices = face['vertex_index']
            elif 'vertex_indices' in face:
                indices = face['vertex_indices']
            else:
                return

            f_vert = [vertices[i] for i in indices]
            f_xyz = [(v['x'], v['y'], v['z']) for v in f_vert]

            try:
                normal = normalize(cpv.cross_product(
                    cpv.sub(f_xyz[1], f_xyz[0]),
                    cpv.sub(f_xyz[2], f_xyz[1])))
            except ZeroDivisionError:
                continue

            for v in f_vert:
                v.setdefault('normals', []).append(normal)

        for v in vertices:
            try:
                v['nx'], v['ny'], v['nz'] = normalize(
                        reduce(cpv.add, v.pop('normals')))
            except (KeyError, ZeroDivisionError):
                continue
예제 #12
0
def angle_between_domains(selection1, selection2, method='align',
        state1=STATE, state2=STATE, visualize=1, quiet=1):
    '''
DESCRIPTION

    Angle by which a molecular selection would be rotated when superposing
    on a selection2.

    Do not use for measuring angle between helices, since the alignment of
    the helices might involve a rotation around the helix axis, which will
    result in a larger angle compared to the angle between helix axes.

USAGE

    angle_between_domains selection1, selection2 [, method ]

ARGUMENTS

    selection1 = string: atom selection of first helix

    selection2 = string: atom selection of second helix

    method = string: alignment command like "align" or "super" {default: align}

EXAMPLE

    fetch 3iplA 3iplB, async=0
    select domain1, resi 1-391
    select domain2, resi 392-475
    align 3iplA and domain1, 3iplB and domain1
    angle_between_domains 3iplA and domain2, 3iplB and domain2

SEE ALSO

    align, super, angle_between_helices
    '''
    import math

    try:
        import numpy
    except ImportError:
        print ' Error: numpy not available'
        raise CmdException

    state1, state2 = int(state1), int(state2)
    visualize, quiet = int(visualize), int(quiet)

    if cmd.is_string(method):
        try:
            method = cmd.keyword[method][0]
        except KeyError:
            print 'no such method:', method
            raise CmdException

    mobile_tmp = get_unused_name('_')
    cmd.create(mobile_tmp, selection1, state1, 1,  zoom=0)
    try:
        method(mobile=mobile_tmp, target=selection2, mobile_state=1,
                target_state=state2, quiet=quiet)
        mat = cmd.get_object_matrix(mobile_tmp)
    except:
        print ' Error: superposition with method "%s" failed' % (method.__name__)
        raise CmdException
    finally:
        cmd.delete(mobile_tmp)

    try:
        # Based on transformations.rotation_from_matrix
        # Copyright (c) 2006-2012, Christoph Gohlke

        R33 = [mat[i:i+3] for i in [0,4,8]]
        R33 = numpy.array(R33, float)

        # direction: unit eigenvector of R33 corresponding to eigenvalue of 1
        w, W = numpy.linalg.eig(R33.T)
        i = w.real.argmax()
        direction = W[:, i].real

        # rotation angle depending on direction
        m = direction.argmax()
        i,j,k,l = [
            [2,1,1,2],
            [0,2,0,2],
            [1,0,0,1]][m]
        cosa = (R33.trace() - 1.0) / 2.0
        sina = (R33[i, j] + (cosa - 1.0) * direction[k] * direction[l]) / direction[m]

        angle = math.atan2(sina, cosa)
        angle = abs(math.degrees(angle))
    except:
        print ' Error: rotation from matrix failed'
        raise CmdException

    if not quiet:
        try:
            # make this import optional to support running this script standalone
            from .querying import centerofmass, gyradius
        except (ValueError, ImportError):
            gyradius = None
            try:
                # PyMOL 1.7.1.6+
                centerofmass = cmd.centerofmass
            except AttributeError:
                centerofmass = lambda s: cpv.scale(cpv.add(*cmd.get_extent(s)), 0.5)

        center1 = centerofmass(selection1)
        center2 = centerofmass(selection2)
        print ' Angle: %.2f deg, Displacement: %.2f angstrom' % (angle, cpv.distance(center1, center2))

        if visualize:
            center1 = numpy.array(center1, float)
            center2 = numpy.array(center2, float)
            center = (center1 + center2) / 2.0

            if gyradius is not None:
                rg = numpy.array(gyradius(selection1), float)
            else:
                rg = 10.0

            h1 = numpy.cross(center2 - center1, direction)
            h2 = numpy.dot(R33, h1)
            h1 *= rg / cpv.length(h1)
            h2 *= rg / cpv.length(h2)

            for pos in [center1, center2, center1 + h1, center1 + h2]:
                cmd.pseudoatom(mobile_tmp, pos=list(pos), state=1)

            # measurement object for angle and displacement
            name = get_unused_name('measurement')
            cmd.distance(name, *['%s`%d' % (mobile_tmp, i) for i in [1,2]])
            cmd.angle(name, *['%s`%d' % (mobile_tmp, i) for i in [3,1,4]])

            # CGO arrow for axis of rotation
            visualize_orientation(direction, center1, rg, color='blue')

            cmd.delete(mobile_tmp)

    return angle
예제 #13
0
def angle_between_domains(selection1,
                          selection2,
                          method='align',
                          state1=STATE,
                          state2=STATE,
                          visualize=1,
                          quiet=1):
    '''
DESCRIPTION

    Angle by which a molecular selection would be rotated when superposing
    on a selection2.

    Do not use for measuring angle between helices, since the alignment of
    the helices might involve a rotation around the helix axis, which will
    result in a larger angle compared to the angle between helix axes.

USAGE

    angle_between_domains selection1, selection2 [, method ]

ARGUMENTS

    selection1 = string: atom selection of first helix

    selection2 = string: atom selection of second helix

    method = string: alignment command like "align" or "super" {default: align}

EXAMPLE

    fetch 3iplA 3iplB, bsync=0
    select domain1, resi 1-391
    select domain2, resi 392-475
    align 3iplA and domain1, 3iplB and domain1
    angle_between_domains 3iplA and domain2, 3iplB and domain2

SEE ALSO

    align, super, angle_between_helices
    '''
    import math

    try:
        import numpy
    except ImportError:
        print(' Error: numpy not available')
        raise CmdException

    state1, state2 = int(state1), int(state2)
    visualize, quiet = int(visualize), int(quiet)

    if cmd.is_string(method):
        try:
            method = cmd.keyword[method][0]
        except KeyError:
            print('no such method:', method)
            raise CmdException

    mobile_tmp = get_unused_name('_')
    cmd.create(mobile_tmp, selection1, state1, 1, zoom=0)
    try:
        method(mobile=mobile_tmp,
               target=selection2,
               mobile_state=1,
               target_state=state2,
               quiet=quiet)
        mat = cmd.get_object_matrix(mobile_tmp)
    except:
        print(' Error: superposition with method "%s" failed' %
              (method.__name__))
        raise CmdException
    finally:
        cmd.delete(mobile_tmp)

    try:
        # Based on transformations.rotation_from_matrix
        # Copyright (c) 2006-2012, Christoph Gohlke

        R33 = [mat[i:i + 3] for i in [0, 4, 8]]
        R33 = numpy.array(R33, float)

        # direction: unit eigenvector of R33 corresponding to eigenvalue of 1
        w, W = numpy.linalg.eig(R33.T)
        i = w.real.argmax()
        direction = W[:, i].real

        # rotation angle depending on direction
        m = direction.argmax()
        i, j, k, l = [[2, 1, 1, 2], [0, 2, 0, 2], [1, 0, 0, 1]][m]
        cosa = (R33.trace() - 1.0) / 2.0
        sina = (R33[i, j] +
                (cosa - 1.0) * direction[k] * direction[l]) / direction[m]

        angle = math.atan2(sina, cosa)
        angle = abs(math.degrees(angle))
    except:
        print(' Error: rotation from matrix failed')
        raise CmdException

    if not quiet:
        try:
            # make this import optional to support running this script standalone
            from .querying import centerofmass, gyradius
        except (ValueError, ImportError):
            gyradius = None
            try:
                # PyMOL 1.7.1.6+
                centerofmass = cmd.centerofmass
            except AttributeError:
                centerofmass = lambda s: cpv.scale(cpv.add(*cmd.get_extent(s)),
                                                   0.5)

        center1 = centerofmass(selection1)
        center2 = centerofmass(selection2)
        print(' Angle: %.2f deg, Displacement: %.2f angstrom' %
              (angle, cpv.distance(center1, center2)))

        if visualize:
            center1 = numpy.array(center1, float)
            center2 = numpy.array(center2, float)
            center = (center1 + center2) / 2.0

            if gyradius is not None:
                rg = numpy.array(gyradius(selection1), float)
            else:
                rg = 10.0

            h1 = numpy.cross(center2 - center1, direction)
            h2 = numpy.dot(R33, h1)
            h1 *= rg / cpv.length(h1)
            h2 *= rg / cpv.length(h2)

            for pos in [center1, center2, center1 + h1, center1 + h2]:
                cmd.pseudoatom(mobile_tmp, pos=list(pos), state=1)

            # measurement object for angle and displacement
            name = get_unused_name('measurement')
            cmd.distance(name, *['%s`%d' % (mobile_tmp, i) for i in [1, 2]])
            cmd.angle(name, *['%s`%d' % (mobile_tmp, i) for i in [3, 1, 4]])

            # CGO arrow for axis of rotation
            visualize_orientation(direction, center1, rg, color='blue')

            cmd.delete(mobile_tmp)

    return angle