예제 #1
0
 def dashed_cylinder_command(self, tokens):
     if len(tokens) not in (9, 10) or (len(tokens) == 10
                                       and tokens[9] != 'open'):
         raise ValueError(
             "Expected 'count x1 y1 z1 x2 y2 z2 radius [open]' after %s" %
             tokens[0])
     count = self.parse_int(tokens[1])
     data = [self.parse_float(x) for x in tokens[2:9]]
     p0 = array(data[0:3])
     p1 = array(data[3:6])
     radius = data[6]
     if len(tokens) < 10:
         closed = True
     else:
         closed = False
     self.num_objects += 1
     if self.cur_description is not None:
         description = self.cur_description
     else:
         description = 'object %d: dashed cylinder' % self.num_objects
     vertices, normals, triangles = get_dashed_cylinder(
         count,
         radius,
         p0,
         p1,
         closed=closed,
         xform=self.transforms[-1],
         pure=self.pure[-1])
     shape = AtomicShapeInfo(vertices, normals, triangles,
                             _cvt_color(self.cur_color), self.cur_atoms,
                             description)
     self.shapes.append(shape)
예제 #2
0
 def polygon_command(self, tokens):
     # TODO: use GLU to tesselate polygon
     #     for now, find center and make a triangle fan
     if len(tokens) % 3 != 1:
         raise UserError("Expected 'x1 y1 z1 ... xN yN zN' after %s" %
                         tokens[0])
     data = [self.parse_float(x) for x in tokens[1:]]
     vertices = array(data, dtype=float32)
     n = len(data) // 3
     vertices.shape = (n, 3)
     if n < 3:
         raise UserError("Need at least 3 vertices in a polygon")
     self.num_objects += 1
     if self.cur_description is not None:
         description = self.cur_description
     else:
         description = 'object %d: polygon' % self.num_objects
     from chimerax.geometry import Plane
     plane = Plane(vertices)
     loops = ((0, len(vertices) - 1), )
     t = surface.triangulate_polygon(loops, plane.normal, vertices)
     normals = empty(vertices.shape, dtype=float32)
     normals[:] = plane.normal
     triangles = array(t, dtype=int32)
     shape = AtomicShapeInfo(vertices, normals, triangles,
                             _cvt_color(self.cur_color), self.cur_atoms,
                             description)
     self.shapes.append(shape)
예제 #3
0
def orient_planar_ring(nd, atoms, ring_indices):
    shapes = []
    r = atoms[0].residue
    # TODO:
    # if not r.fill_display or r.fill_mode != r.Thick:
    #     # can't show orientation of thin nor aromatic ring
    #     return shapes
    pts = [a.coord for a in atoms]
    bonds = bonds_between(atoms)
    # if chimera.Bond.Wire in [b.draw_mode for b in bonds]:
    #     radius = 0
    # else:
    if 1:
        radius = min([b.radius for b in bonds])
    if radius == 0:
        # can't show orientation of thin ring
        return shapes

    color = r.ring_color
    # non-zero radius
    planeEq = Plane(pts)
    offset = planeEq.normal * radius
    for r in ring_indices:
        center = numpy.average([pts[i] for i in r], axis=0) + offset
        va, na, ta = get_sphere(radius, center)
        shapes.append(AtomicShapeInfo(va, na, ta, color, str(atoms)))
    return shapes
예제 #4
0
 def cone_command(self, tokens):
     if len(tokens) not in (8, 9) or (len(tokens) == 9
                                      and tokens[8] != 'open'):
         raise ValueError(
             "Expected 'x1 y1 z1 x2 y2 z2 radius [open]' after %s" %
             tokens[0])
     data = [self.parse_float(x) for x in tokens[1:8]]
     p0 = array(data[0:3])
     p1 = array(data[3:6])
     radius = data[6]
     if len(tokens) < 9:
         bottom = True
     else:
         bottom = False
     self.num_objects += 1
     if self.cur_description is not None:
         description = self.cur_description
     else:
         description = 'object %d: cone' % self.num_objects
     vertices, normals, triangles = get_cone(radius,
                                             p0,
                                             p1,
                                             bottom=bottom,
                                             xform=self.transforms[-1],
                                             pure=self.pure[-1])
     shape = AtomicShapeInfo(vertices, normals, triangles,
                             _cvt_color(self.cur_color), self.cur_atoms,
                             description)
     self.shapes.append(shape)
예제 #5
0
def draw_tube(nd, residue, name, params):
    shapes = []
    if params.anchor == RIBOSE:
        show_gly = False
    else:
        show_gly = params.show_gly
    if params.anchor == RIBOSE or show_gly:
        aname = "C1'"
    else:
        tag = standard_bases[name]['tag']
        aname = _BaseAnchors[tag]
        if not aname:
            return False
    a = residue.find_atom(aname)
    if not a or not a.display:
        return shapes
    ep0 = a.coord
    if params.radius is None:
        radius = a.structure.bond_radius
    else:
        radius = params.radius

    color = residue.ring_color

    # calculate position between C3' and C4' on ribbon
    c3p = residue.find_atom("C3'")
    if not c3p:
        return shapes
    c4p = residue.find_atom("C4'")
    if not c4p:
        return shapes
    c3p_coord = c3p.ribbon_coord
    c4p_coord = c4p.ribbon_coord
    if c3p_coord is None or c4p_coord is None:
        ep1 = (c3p.coord + c4p.coord) / 2
    else:
        ep1 = (c3p_coord + c4p_coord) / 2

    description = '%s ribose' % residue

    va, na, ta = get_cylinder(radius, ep0, ep1, bottom=False)
    shapes.append(AtomicShapeInfo(va, na, ta, color, None, description))
    va, na, ta = get_sphere(radius, ep0)
    shapes.append(AtomicShapeInfo(va, na, ta, color, None, description))
    return shapes
예제 #6
0
 def draw_command(self, tokens):
     if len(tokens) != 4:
         raise ValueError("Expected 'x y z' after %s" % tokens[0])
     data = [self.parse_float(x) for x in tokens[1:4]]
     xyz = array(data[0:3])
     radius = self.LINE_RADIUS
     p0 = self.cur_pos
     if tokens[0] in ('.draw', '.d'):
         p1 = xyz
     else:
         p1 = p0 + xyz
     self.num_objects += 1
     if self.cur_description is not None:
         description = self.cur_description
     else:
         description = 'object %d: vector' % self.num_objects
     vertices, normals, triangles = get_sphere(radius,
                                               p1,
                                               self.transforms[-1],
                                               pure=self.pure[-1])
     vertices2, normals2, triangles2 = get_cylinder(
         radius,
         p0,
         p1,
         closed=False,
         xform=self.transforms[-1],
         pure=self.pure[-1])
     if self.cur_pos_is_move:
         vertices3, normals3, triangles3 = get_sphere(radius,
                                                      p0,
                                                      self.transforms[-1],
                                                      pure=self.pure[-1])
         vertices, normals, triangles = combine_triangles(
             ((vertices, normals, triangles),
              (vertices2, normals2, triangles2), (vertices3, normals3,
                                                  triangles3)))
     else:
         vertices, normals, triangles = combine_triangles(
             ((vertices, normals, triangles), (vertices2, normals2,
                                               triangles2)))
     shape = AtomicShapeInfo(vertices, normals, triangles,
                             _cvt_color(self.cur_color), self.cur_atoms,
                             description)
     self.shapes.append(shape)
     self.cur_pos = p1
     self.cur_pos_is_move = False
예제 #7
0
 def sphere_command(self, tokens):
     if len(tokens) != 5:
         raise UserError("Expected 'x y z radius' after %s" % tokens[0])
     data = [self.parse_float(x) for x in tokens[1:5]]
     center = array(data[0:3])
     radius = data[3]
     self.num_objects += 1
     if self.cur_description is not None:
         description = self.cur_description
     else:
         description = 'object %d: sphere' % self.num_objects
     vertices, normals, triangles = get_sphere(radius,
                                               center,
                                               self.transforms[-1],
                                               pure=self.pure[-1])
     shape = AtomicShapeInfo(vertices, normals, triangles,
                             _cvt_color(self.cur_color), self.cur_atoms,
                             description)
     self.shapes.append(shape)
예제 #8
0
 def box_command(self, tokens):
     if len(tokens) != 7:
         raise ValueError("Expected 'x1 y1 z1 x2 y2 z2' after %s" %
                          tokens[0])
     data = [self.parse_float(x) for x in tokens[1:7]]
     llb = array(data[0:3])
     urf = array(data[3:6])
     self.num_objects += 1
     if self.cur_description is not None:
         description = self.cur_description
     else:
         description = 'object %d: box' % self.num_objects
     vertices, normals, triangles = get_box(llb,
                                            urf,
                                            self.transforms[-1],
                                            pure=self.pure[-1])
     shape = AtomicShapeInfo(vertices, normals, triangles,
                             _cvt_color(self.cur_color), self.cur_atoms,
                             description)
     self.shapes.append(shape)
예제 #9
0
 def marker_command(self, tokens):
     if len(tokens) != 4:
         raise ValueError("Expected 'x y z' after %s" % tokens[0])
     data = [self.parse_float(x) for x in tokens[1:4]]
     center = array(data[0:3])
     self.num_objects += 1
     if self.cur_description is not None:
         description = self.cur_description
     else:
         description = 'object %d: marker' % self.num_objects
     llb = center - 0.5
     urf = center + 0.5
     vertices, normals, triangles = get_box(llb,
                                            urf,
                                            self.transforms[-1],
                                            pure=self.pure[-1])
     shape = AtomicShapeInfo(vertices, normals, triangles,
                             _cvt_color(self.cur_color), self.cur_atoms,
                             description)
     self.shapes.append(shape)
     self.cur_pos = center
     self.cur_pos_is_move = False
예제 #10
0
 def arrow_command(self, tokens):
     if len(tokens) not in (7, 8, 9, 10):
         raise ValueError(
             "Expected 'x1 y1 z1 x2 y2 z2 [r1 [r2 [rho]]]' after %s" %
             tokens[0])
     data = [self.parse_float(x) for x in tokens[1:]]
     r1 = data[6] if len(tokens) > 7 else 0.1
     r2 = data[7] if len(tokens) > 8 else 4 * r1
     rho = data[8] if len(tokens) > 9 else 0.75
     p1 = array(data[0:3])
     p2 = array(data[3:6])
     junction = p1 + rho * (p2 - p1)
     self.num_objects += 1
     if self.cur_description is not None:
         description = self.cur_description
     else:
         description = 'object %d: arrow' % self.num_objects
     vertices, normals, triangles = get_cylinder(r1,
                                                 p1,
                                                 junction,
                                                 closed=True,
                                                 xform=self.transforms[-1],
                                                 pure=self.pure[-1])
     vertices2, normals2, triangles2 = get_cone(r2,
                                                junction,
                                                p2,
                                                bottom=True,
                                                xform=self.transforms[-1],
                                                pure=self.pure[-1])
     vertices, normals, triangles = combine_triangles(
         ((vertices, normals, triangles), (vertices2, normals2,
                                           triangles2)))
     shape = AtomicShapeInfo(vertices, normals, triangles,
                             _cvt_color(self.cur_color), self.cur_atoms,
                             description)
     self.shapes.append(shape)
예제 #11
0
def draw_slab(nd, residue, name, params):
    shapes = []
    standard = standard_bases[name]
    ring_atom_names = standard["ring atom names"]
    atoms = get_ring(residue, ring_atom_names)
    if not atoms:
        return shapes
    plane = Plane([a.coord for a in atoms])
    info = find_dimensions(params.dimensions)
    tag = standard['tag']
    slab_corners = info[tag]
    origin = residue.find_atom(anchor(info[ANCHOR], tag)).coord
    origin = plane.nearest(origin)

    pts = [plane.nearest(a.coord) for a in atoms[0:2]]
    y_axis = pts[0] - pts[1]
    normalize_vector(y_axis)
    x_axis = numpy.cross(y_axis, plane.normal)
    xf = Place(matrix=((x_axis[0], y_axis[0], plane.normal[0], origin[0]),
                       (x_axis[1], y_axis[1], plane.normal[1], origin[1]),
                       (x_axis[2], y_axis[2], plane.normal[2], origin[2])))
    xf = xf * standard["correction factor"]

    color = residue.ring_color
    half_thickness = params.thickness / 2

    llx, lly = slab_corners[0]
    llz = -half_thickness
    urx, ury = slab_corners[1]
    urz = half_thickness
    center = (llx + urx) / 2, (lly + ury) / 2, 0
    if params.shape == 'box':
        llb = (llx, lly, llz)
        urf = (urx, ury, urz)
        xf2 = xf
        va, na, ta = box_geometry(llb, urf)
        pure_rotation = True
    elif params.shape == 'muffler':
        radius = (urx - llx) / 2 * _SQRT2
        xf2 = xf * translation(center)
        xf2 = xf2 * scale((1, 1, half_thickness * _SQRT2 / radius))
        height = ury - lly
        va, na, ta = get_cylinder(radius, numpy.array((0, -height / 2, 0)),
                                  numpy.array((0, height / 2, 0)))
        pure_rotation = False
    elif params.shape == 'ellipsoid':
        # need to reach anchor atom
        xf2 = xf * translation(center)
        sr = (ury - lly) / 2 * _SQRT3
        xf2 = xf2 * scale(
            ((urx - llx) / 2 * _SQRT3 / sr, 1, half_thickness * _SQRT3 / sr))
        va, na, ta = get_sphere(sr, (0, 0, 0))
        pure_rotation = False
    else:
        raise RuntimeError('unknown base shape')

    description = '%s %s' % (residue, tag)
    xf2.transform_points(va, in_place=True)
    xf2.transform_normals(na, in_place=True, is_rotation=pure_rotation)
    shapes.append(AtomicShapeInfo(va, na, ta, color, atoms, description))

    if not params.orient:
        return shapes

    # show slab orientation by putting "bumps" on surface
    if tag == PYRIMIDINE:
        center = (llx + urx) / 2.0, (lly + ury) / 2, half_thickness
        va, na, ta = get_sphere(half_thickness, center)
        xf.transform_points(va, in_place=True)
        xf.transform_normals(na, in_place=True, is_rotation=True)
        shapes.append(AtomicShapeInfo(va, na, ta, color, atoms, description))
    else:
        # purine
        center = (llx + urx) / 2.0, lly + (ury - lly) / 3, half_thickness
        va, na, ta = get_sphere(half_thickness, center)
        xf.transform_points(va, in_place=True)
        xf.transform_normals(na, in_place=True, is_rotation=True)
        shapes.append(AtomicShapeInfo(va, na, ta, color, atoms, description))
        center = (llx + urx) / 2.0, lly + (ury - lly) * 2 / 3, half_thickness
        va, na, ta = get_sphere(half_thickness, center)
        xf.transform_points(va, in_place=True)
        xf.transform_normals(na, in_place=True, is_rotation=True)
        shapes.append(AtomicShapeInfo(va, na, ta, color, atoms, description))
    return shapes
예제 #12
0
def make_ladder(nd, residues, params):
    """generate links between residues that are hydrogen bonded together"""
    # returns set of residues whose bases are drawn as rungs and
    # and have their atoms hidden
    all_shapes = []

    # Create list of atoms from residues for donors and acceptors
    mol = residues[0].structure

    # make a set for quick inclusion test
    residue_set = set(residues)

    pbg = mol.pseudobond_group(mol.PBG_HYDROGEN_BONDS, create_type=None)
    if not pbg:
        bonds = ()
    else:
        bonds = (p.atoms for p in pbg.pseudobonds)

    # only make one rung between residues even if there is more than one
    # h-bond
    depict_bonds = {}
    for a0, a1 in bonds:
        r0 = a0.residue
        r1 = a1.residue
        if r0 not in residue_set or r1 not in residue_set:
            continue
        non_base = (BackboneRiboseRE.match(a0.name),
                    BackboneRiboseRE.match(a1.name))
        if params.skip_nonbase_Hbonds and any(non_base):
            continue
        if r0.connects_to(r1):
            # skip covalently bonded residues
            continue
        if r1 < r0:
            r0, r1 = r1, r0
            non_base = (non_base[1], non_base[0])
        c3p0 = _c3pos(r0)
        if not c3p0:
            continue
        c3p1 = _c3pos(r1)
        if not c3p1:
            continue
        if params.rung_radius and not any(non_base):
            radius = params.rung_radius
        # elif r0.ribbon_display and r1.ribbon_display:
        #     mgr = mol.ribbon_xs_mgr
        #     radius = min(mgr.scale_nucleic)
        else:
            # TODO: radius = a0.structure.stickScale \
            #     * chimera.Molecule.DefaultBondRadius
            radius = a0.structure.bond_radius
        key = (r0, r1)
        if key in depict_bonds:
            prev_radius = depict_bonds[key][2]
            if prev_radius >= radius:
                continue
        depict_bonds[key] = (c3p0, c3p1, radius, non_base)

    matched_residues = set()
    if not params.stubs_only:
        for (r0, r1), (c3p0, c3p1, radius, non_base) in depict_bonds.items():
            a0 = r0.find_atom("C2")
            a1 = r1.find_atom("C2")
            r0color = r0.ring_color
            r1color = r1.ring_color
            # choose mid-point to make purine larger
            try:
                is_purine0 = standard_bases[nucleic3to1(
                    r0.name)]['tag'] == PURINE
                is_purine1 = standard_bases[nucleic3to1(
                    r1.name)]['tag'] == PURINE
            except KeyError:
                is_purine0 = False
                is_purine1 = False
            if any(non_base) or is_purine0 == is_purine1:
                mid = 0.5
            elif is_purine0:
                mid = purine_pyrimidine_ratio
            else:
                mid = 1.0 - purine_pyrimidine_ratio
            midpt = c3p0[1] + mid * (c3p1[1] - c3p0[1])
            va, na, ta = get_cylinder(radius, c3p0[1], midpt, top=False)
            all_shapes.append(
                AtomicShapeInfo(va, na, ta, r0color, r0.atoms, str(r0)))
            va, na, ta = get_cylinder(radius, c3p1[1], midpt, top=False)
            all_shapes.append(
                AtomicShapeInfo(va, na, ta, r1color, r1.atoms, str(r1)))
            if not non_base[0]:
                matched_residues.add(r0)
            if not non_base[1]:
                matched_residues.add(r1)

    if not params.show_stubs:
        if params.hide:
            return all_shapes, matched_residues
        return all_shapes, ()
    # draw stubs for unmatched nucleotide residues
    for r in residues:
        if r in matched_residues:
            continue
        c3p = _c3pos(r)
        if not c3p:
            continue
        ep0 = c3p[1]
        a = r.find_atom("C2")
        color = r.ring_color
        ep1 = None
        name = nucleic3to1(r.name)
        if name not in standard_bases:
            continue
        is_purine = standard_bases[name]['tag'] == PURINE
        if is_purine:
            a = r.find_atom('N1')
            if a:
                ep1 = a.coord
        else:
            # pyrimidine
            a = r.find_atom('N3')
            if a:
                ep1 = a.coord
        if ep1 is None:
            # find farthest atom from C3'
            dist_atom = (0, None)
            for a in r.atoms:
                dist = distance_squared(ep0, a.coord)
                if dist > dist_atom[0]:
                    dist_atom = (dist, a)
            ep1 = dist_atom[1].coord
        va, na, ta = get_cylinder(params.rung_radius, ep0, ep1)
        all_shapes.append(AtomicShapeInfo(va, na, ta, color, r.atoms, str(r)))
        # make exposed end rounded (TODO: use a hemisphere)
        va, na, ta = get_sphere(params.rung_radius, ep1)
        all_shapes.append(AtomicShapeInfo(va, na, ta, color, r.atoms, str(r)))
        matched_residues.add(r)
    if params.hide:
        return all_shapes, matched_residues
    return all_shapes, ()