def orientPlanarRing(atoms, ringIndices=[], convex=True): r = atoms[0].residue if not r.fillDisplay or r.fillMode != chimera.Residue.Thick: # can't show orientation of thin nor aromatic ring return [] pts = [a.coord() for a in atoms] bonds = bondsBetween(atoms) if chimera.Bond.Wire in [b.drawMode for b in bonds]: radius = 0 else: radius = min([b.radius for b in bonds]) radius *= atoms[0].molecule.stickScale color_kwds = _atom_color(atoms[0]) if radius == 0: # can't show orientation of thin ring return [] # non-zero radius planeEq = chimera.Plane(pts) offset = planeEq.normal * radius result = [] for r in ringIndices: center = chimera.Point([pts[i] for i in r]) + offset t = vrml.Transform() t.translation = center.data() s = vrml.Sphere(radius=radius, **color_kwds) t.addChild(s) result.append(t) return result
def drawCylinder(radius, ep0, ep1, **kw): t = vrml.Transform() t.translation = chimera.Point([ep0, ep1]).data() delta = ep1 - ep0 height = delta.length axis = chimera.cross(cylAxis, delta) cos = (cylAxis * delta) / height angle = math.acos(cos) t.rotation = (axis[0], axis[1], axis[2], angle) c = vrml.Cylinder(radius=radius, height=height, **kw) t.addChild(c) return t
def Apply(self): molList = chimera.openModels.list(modelTypes=[chimera.Molecule]) selList = self.molecules.curselection() if len(selList) != 1: return molName, molId, molSubid = self.molList[int(selList[0])] for m in molList: if m.id == molId and m.subid == molSubid: mol = m break else: replyobj.error('No selected molecule') return base.initialize() wrl = vrml.Transform() helices = base.displayHelices(mol, self.helixColor, self.helixFixedRadius.get(), self.helixRadius.get(), self.helixSplit.get(), self.helixSplitRatio.get()) for node in helices: wrl.addChild(node) strands = base.displayStrands(mol, self.strandColor, self.strandFixedWidth.get(), self.strandWidth.get(), self.strandFixedThickness.get(), self.strandThickness.get(), self.strandSplit.get(), self.strandSplitRatio.get()) for node in strands: wrl.addChild(node) if self.displayTurns.get(): turns = base.displayTurns(mol, self.turnColor, self.turnWidth.get(), self.turnThickness.get()) for node in turns: wrl.addChild(node) base.deinitialize() if not helices and not strands and not turns: replyobj.error('No helices, sheets, nor turns found') return try: chimera.openModels.close(self.openModels[mol]) except KeyError: pass mList = chimera.openModels.open(vrml.vrml(wrl), type='VRML', sameAs=mol, identifyAs='%s - Pipes and Planks' % mol.name) self.openModels[mol] = mList[0] self.openModels[mList[0]] = None
def showStrand(strand, color, fixedWidth, width, fixedThickness, thickness, split, splitRatio): if len(strand) < 3: return [] # Find box axes, length, width and thickness coords, centroid, axes = findAxes(strand, ['O']) for c in coords: s, t, u = parametricVars(centroid, axes, c) t = math.fabs(t) u = math.fabs(u) try: minS = min(s, minS) maxS = max(s, maxS) sumT = sumT + t minU = min(u, minU) maxU = max(u, maxU) sumU = sumU + u except NameError: minS = maxS = s sumT = t minU = maxU = u sumU = u if split and maxU / minU > splitRatio: front, back = splitResidues(strand, ['O']) if back: # successful split return showStrand(front, color, fixedWidth, width, fixedThickness, thickness, split, splitRatio) \ + showStrand(back, color, fixedWidth, width, fixedThickness, thickness, split, splitRatio) length = maxS + -minS center = (maxS + minS) / 2 * axes[0] + centroid if not fixedWidth: width = sumT / len(coords) * 2 if not fixedThickness: thickness = sumU / len(coords) * 2 hl = length / 2 s, t, u = parametricVars(center, axes, coords[0]) if maxS - s > s - minS: ssMap[strand[0]] = (center - hl * axes[0], -axes[0], axes[1], axes[2]) ssMap[strand[-1]] = (center + hl * axes[0], axes[0], axes[1], axes[2]) else: ssMap[strand[0]] = (center + hl * axes[0], axes[0], axes[1], axes[2]) ssMap[strand[-1]] = (center - hl * axes[0], -axes[0], axes[1], axes[2]) mat = [ # Note that the X axis is mapped onto length axis # ... and Y is mapped onto width axis [axes[0][0], axes[1][0], axes[2][0]], [axes[0][1], axes[1][1], axes[2][1]], [axes[0][2], axes[1][2], axes[2][2]] ] matrixNormalize(mat) xf = chimera.Xform.xform(mat[0][0], mat[0][1], mat[0][2], 0, mat[1][0], mat[1][1], mat[1][2], 0, mat[2][0], mat[2][1], mat[2][2], 0) rotAxis, angle = xf.getRotation() angle = angle / 180.0 * math.pi transform = vrml.Transform() trans = vrml.Transform(translation=(center[0], center[1], center[2])) transform.addChild(trans) rot = vrml.Transform(rotation=(rotAxis.x, rotAxis.y, rotAxis.z, angle)) trans.addChild(rot) rgba = color.get().rgba() box = vrml.Box(size=(length, width, thickness), color=rgba[:3]) if rgba[3] < 1.0: box.transparency = 1.0 - rgba[3] rot.addChild(box) return [transform]
def showHelix(helix, color, fixedRadius, radius, split, splitRatio): if len(helix) < 3: return [] # Find cylinder axes, length and radius coords, centroid, axes = findAxes(helix, ['CA']) for c in coords: s, t, u = parametricVars(centroid, axes, c) d = math.sqrt(t * t + u * u) try: minS = min(s, minS) maxS = max(s, maxS) minD = min(d, minD) maxD = max(d, maxD) sumD = sumD + d except NameError: minS = maxS = s minD = maxD = d sumD = d if split and maxD / minD > splitRatio: front, back = splitResidues(helix, ['CA']) if back: # successful split return showHelix(front, color, fixedRadius, radius, split, splitRatio) \ + showHelix(back, color, fixedRadius, radius, split, splitRatio) if not fixedRadius: radius = sumD / len(coords) axisLength = maxS + -minS halfLength = axisLength / 2 center = (maxS + minS) / 2 * axes[0] + centroid s, t, u = parametricVars(center, axes, coords[0]) if maxS - s < s - minS: ssMap[helix[0]] = (center + halfLength * axes[0], axes[0], axes[1], axes[2]) ssMap[helix[-1]] = (center - halfLength * axes[0], -axes[0], axes[1], axes[2]) else: ssMap[helix[0]] = (center - halfLength * axes[0], -axes[0], axes[1], axes[2]) ssMap[helix[-1]] = (center + halfLength * axes[0], axes[0], axes[1], axes[2]) mat = [ # Note that the Y axis is mapped onto major axis [axes[1][0], axes[0][0], axes[2][0]], [axes[1][1], axes[0][1], axes[2][1]], [axes[1][2], axes[0][2], axes[2][2]] ] matrixNormalize(mat) xf = chimera.Xform.xform(mat[0][0], mat[0][1], mat[0][2], 0, mat[1][0], mat[1][1], mat[1][2], 0, mat[2][0], mat[2][1], mat[2][2], 0) rotAxis, angle = xf.getRotation() angle = angle / 180.0 * math.pi transform = vrml.Transform() trans = vrml.Transform(translation=(center[0], center[1], center[2])) transform.addChild(trans) rot = vrml.Transform(rotation=(rotAxis.x, rotAxis.y, rotAxis.z, angle)) trans.addChild(rot) rgba = color.get().rgba() cylinder = vrml.Cylinder(radius=radius, height=axisLength, color=rgba[:3]) if rgba[3] < 1.0: cylinder.transparency = 1.0 - rgba[3] rot.addChild(cylinder) return [transform]
def fill5Ring(atoms, c5p=None): pts = [a.coord() for a in atoms] bonds = bondsBetween(atoms) if chimera.Bond.Wire in [b.drawMode for b in bonds]: radius = 0 else: radius = min([b.radius for b in bonds]) radius *= atoms[0].molecule.stickScale color_kwds = _atom_color(atoms[0]) # see how planar ring is indices = (0, 1, 2, 3, 4, 0, 1, 2, 3, 4) distC5p = None fake_bonds = [(0, 5), (1, 5), (2, 5), (3, 5), (4, 5)] for i in range(5): atoms[i].pucker = 'plane' # Find twist plane. Note: due to floating point limitations, # dist3 and dist4 will virtually never be zero. for i in range(5): planeEq = chimera.Plane([pts[indices[j]] for j in range(i, i + 3)]) dist3 = planeEq.distance(pts[indices[i + 3]]) dist4 = planeEq.distance(pts[indices[i + 4]]) if c5p: distC5p = planeEq.distance(c5p.coord()) if dist3 == 0 or dist4 == 0 \ or (dist3 < 0 and dist4 > 0) or (dist3 > 0 and dist4 < 0): break abs_dist3 = abs(dist3) abs_dist4 = abs(dist4) if abs_dist3 < planar_cutoff and abs_dist4 < planar_cutoff: # planar, new_vertex is centroid of pts new_vertex = chimera.Point(pts) elif abs_dist3 < abs_dist4 and abs_dist4 / abs_dist3 >= envelope_ratio: # envelope, new_vertex is mid-point of separating edge new_vertex = chimera.Point([pts[indices[i]], pts[indices[i + 3]]]) atoms[indices[i + 4]].pucker = 'envelope' del fake_bonds[indices[i + 4]] elif abs_dist4 < abs_dist3 and abs_dist3 / abs_dist4 >= envelope_ratio: # envelope, new_vertex is mid-point of separating edge new_vertex = chimera.Point([pts[indices[i + 2]], pts[indices[i + 4]]]) atoms[indices[i + 3]].pucker = 'envelope' del fake_bonds[indices[i + 3]] else: # if (dist3 < 0 and dist4 > 0) or (dist3 > 0 and dist4 < 0): # twist, new_vertex is placed in twist plane near twist pts centroid = chimera.Point([ pts[indices[i + 1]], pts[indices[i + 3]], pts[indices[i + 4]] ]) new_vertex = planeEq.nearest(centroid) del fake_bonds[indices[i + 1]] if cmp(dist3, 0) == cmp(distC5p, 0): atoms[indices[i + 3]].pucker = 'endo' else: atoms[indices[i + 3]].pucker = 'exo' if cmp(dist4, 0) == cmp(distC5p, 0): atoms[indices[i + 4]].pucker = 'endo' else: atoms[indices[i + 4]].pucker = 'exo' pts.append(new_vertex) # new_vertex has index 5 triangles = ((0, 1, 5), (1, 2, 5), (2, 3, 5), (3, 4, 5), (4, 0, 5)) if radius == 0: f = TriangleNode(solid=False, coordList=[p.data() for p in pts], coordIndices=triangles, colorPerVertex=False, **color_kwds ) return [f] # non-zero radius f = vrml.Faces(**color_kwds) for t in triangles: # t is a list of 3 indices t = [pts[i] for i in t] # t is a list of 3 Points planeEq = chimera.Plane(t) offset = planeEq.normal * radius top = [(p + offset).data() for p in t] bot = [(p - offset).data() for p in t] f.addFace(top) if 1: # STL wants manifold objects for i in range(len(t) - 1): f.addFace([top[i], bot[i], bot[i + 1], top[i + 1]]) f.addFace([top[-1], bot[-1], bot[0], top[0]]) bot.reverse() f.addFace(bot) result = [f] for b in fake_bonds: node = drawCylinder(radius, pts[b[0]], pts[b[1]], **color_kwds) result.append(node) t = vrml.Transform() t.translation = pts[5].data() s = vrml.Sphere(radius=radius, **color_kwds) t.addChild(s) result.append(t) return result
def drawSlab(residue, style, thickness, orient, shape, showGly): try: t = residue.type if t in ('PSU', 'P'): n = 'P' elif t in ('NOS', 'I'): n = 'I' else: n = nucleic3to1[t] except KeyError: return None standard = standard_bases[n] ring_atom_names = standard["ring atom names"] atoms = getRing(residue, ring_atom_names) if not atoms: return None plane = chimera.Plane([a.coord() for a in atoms]) info = findStyle(style) type = standard['type'] slab_corners = info[type] origin = residue.findAtom(anchor(info[ANCHOR], type)).coord() origin = plane.nearest(origin) pts = [plane.nearest(a.coord()) for a in atoms[0:2]] yAxis = pts[0] - pts[1] yAxis.normalize() xAxis = chimera.cross(yAxis, plane.normal) xf = chimera.Xform.xform( xAxis[0], yAxis[0], plane.normal[0], origin[0], xAxis[1], yAxis[1], plane.normal[1], origin[1], xAxis[2], yAxis[2], plane.normal[2], origin[2] ) xf.multiply(standard["adjust"]) color_kwds = _atom_color(atoms[0]) na = vrml.Transform() na.translation = xf.getTranslation().data() axis, angle = xf.getRotation() na.rotation = (axis[0], axis[1], axis[2], math.radians(angle)) #xf.invert() # invert so xf maps residue space to standard space halfThickness = thickness / 2.0 t = vrml.Transform() na.addChild(t) llx, lly = slab_corners[0] urx, ury = slab_corners[1] t.translation = (llx + urx) / 2.0, (lly + ury) / 2.0, 0 if shape == 'box': b = vrml.Box(size=(urx - llx, ury - lly, 2.0 * halfThickness), **color_kwds) elif shape == 'tube': radius = (urx - llx) / 2 t.scale = 1, 1, halfThickness / radius b = vrml.Cylinder(radius=radius, height=(ury - lly), **color_kwds) elif shape == 'ellipsoid': # need to reach anchor atom t.scale = ((urx - llx) / 20 * _SQRT2, (ury - lly) / 20 * _SQRT2, .1 * halfThickness) b = vrml.Sphere(radius=10, **color_kwds) t.addChild(b) if showGly: c1p = residue.findAtom("C1'") ba = residue.findAtom(anchor(info[ANCHOR], type)) if c1p and ba: c1p.hide = False ba.hide = False if not orient: return na # show slab orientation by putting "bumps" on surface if standard['type'] == PYRIMIDINE: t = vrml.Transform() na.addChild(t) t.translation = (llx + urx) / 2.0, (lly + ury) / 2, halfThickness t.addChild(vrml.Sphere(radius=halfThickness, **color_kwds)) else: # purine t = vrml.Transform() na.addChild(t) t.translation = (llx + urx) / 2.0, lly + (ury - lly) / 3, halfThickness t.addChild(vrml.Sphere(radius=halfThickness, **color_kwds)) t = vrml.Transform() na.addChild(t) t.translation = (llx + urx) / 2.0, lly + (ury - lly) * 2 / 3, halfThickness t.addChild(vrml.Sphere(radius=halfThickness, **color_kwds)) return na