def pruneByChis(rots, res, log=False): from data import chiInfo if res.type not in chiInfo: return rots info = chiInfo[res.type] rotChiInfo = chiInfo[rots[0].residues[0].type] if log: replyobj.info("Chi angles for %s:" % res) for chiNum, resNames in enumerate(info): try: rotNames = rotChiInfo[chiNum] except IndexError: break atoms = [] try: for name in resNames: atoms.append(res.atomsMap[name][0]) except KeyError: break from chimera import dihedral origChi = dihedral(*tuple([a.coord() for a in atoms])) if log: replyobj.info(" %.1f" % origChi) pruned = [] nearest = None for rot in rots: atomsMap = rot.residues[0].atomsMap chi = dihedral( *tuple([atomsMap[name][0].coord() for name in rotNames])) delta = abs(chi - origChi) if delta > 180: delta = 360 - delta if branchSymmetry.get(res.type, -1) == chiNum: if delta > 90: delta = 180 - delta if not nearest or delta < nearDelta: nearest = rot nearDelta = delta if delta > 40: continue pruned.append(rot) if pruned: rots = pruned else: rots = [nearest] break if log: replyobj.info("\n") return rots
def rotate(molecule, at, alpha): if len(at) == 3: try: a1, a2, a3 = [a.coord() for a in at] except AttributeError: a1, a2, a3 = at axis_a = a1 - a2 axis_b = a3 - a2 delta = chimera.angle(a1, a2, a3) - alpha axis = chimera.cross(axis_a, axis_b) if axis.data() == (0.0, 0.0, 0.0): axis = chimera.cross(axis_a, axis_b + chimera.Vector(1, 0, 0)) logger.warning("Had to choose arbitrary normal vector") pivot = a2 elif len(at) == 4: try: a1, a2, a3, a4 = [a.coord() for a in at] except AttributeError: a1, a2, a3, a4 = at axis = a3 - a2 delta = chimera.dihedral(a1, a2, a3, a4) - alpha pivot = a3 else: raise ValueError( "Atom list must contain 3 (angle) or 4 (dihedral) atoms only") r = X.translation(pivot - ZERO) # move to origin r.multiply(X.rotation(axis, -delta)) # rotate r.multiply(X.translation(ZERO - pivot)) # return to orig pos for a in molecule.atoms: a.setCoord(r.apply(a.coord()))
def _angleLabel(self, atoms): pts = tuple([a.xformCoord() for a in atoms]) if len(pts) == 3: val = chimera.angle(*pts) else: val = chimera.dihedral(*pts) return "%.*f" % (prefs[ANGLE_PRECISION], val)
def getChi(res, chiNum): try: atoms = chiAtoms(res, chiNum) except AtomsMissingError: return None from chimera import dihedral return dihedral(*tuple([a.coord() for a in atoms]))
def getPhi(res): try: prevC, n, ca, c = phiAtoms(res) except AtomsMissingError: return None from chimera import dihedral return dihedral(prevC.coord(), n.coord(), ca.coord(), c.coord())
def getPsi(res): try: n, ca, c, nextN = psiAtoms(res) except AtomsMissingError: return None from chimera import dihedral return dihedral(n.coord(), ca.coord(), c.coord(), nextN.coord())
def evaluate(self, ind): atoms_coords = [a.xformCoord() for a in self.probes(ind)] try: angle = chimera.angle(*atoms_coords) except TypeError: # four atoms, means dihedral angle = chimera.dihedral(*atoms_coords) if self.threshold == 'planar': return abs(math.sin(math.radians(angle))) return abs(self.threshold - angle.real)
def interpInternal(c0map, c1map, f, cs, a0, a1, a2, a3): """Computer coordinate of atom a0 by interpolating dihedral angle defined by atoms (a0, a1, a2, a3)""" import chimera c00 = c0map[a0] c01 = c0map[a1] c02 = c0map[a2] c03 = c0map[a3] length0 = c00.distance(c01) angle0 = chimera.angle(c00, c01, c02) dihed0 = chimera.dihedral(c00, c01, c02, c03) c10 = c1map[a0] c11 = c1map[a1] c12 = c1map[a2] c13 = c1map[a3] length1 = c10.distance(c11) angle1 = chimera.angle(c10, c11, c12) dihed1 = chimera.dihedral(c10, c11, c12, c13) length = length0 + (length1 - length0) * f angle = angle0 + (angle1 - angle0) * f ddihed = dihed1 - dihed0 if ddihed > 180: ddihed -= 360 elif ddihed < -180: ddihed += 360 dihed = dihed0 + ddihed * f c1 = a1.coord(cs) c2 = a2.coord(cs) c3 = a3.coord(cs) from chimera import molEdit try: c0 = molEdit.findPt(c1, c2, c3, length, angle, dihed) except ValueError: print `a1`, a1 print `a2`, a2 print `a3`, a3 raise a0.setCoord(c0, cs)
def _tetCheck(tet, partner, hbondInfo, tetAcc): """Check if tet can still work""" tetPos = tet.xformCoord() partnerPos = partner.xformCoord() bonded = tet.primaryNeighbors() tetInfo = hbondInfo.get(tet, []) towards = [] # if there is a real bond to the tet, we want to check the # dihedral to the new position (using a 120 angle) rather than # the angle (109.5) since the vector from the tet to the not- # yet-added positions is probably not directly along the future bond if bonded: if debug: print "checking dihedral" chkFunc = lambda op, pp=partnerPos, tp=tetPos, \ bp=bonded[0].xformCoord(): chimera.dihedral( pp, tp, bp, op) / 30.0 else: if debug: print "checking angle" chkFunc = lambda op, pp=partnerPos, tp=tetPos: chimera.angle( pp, tp, op) / 27.375 for isAcc, other in tetInfo: if isAcc == tetAcc: # same "polarity"; pointing towards is good result = True else: # opposite "polarity"; pointing towards is bad result = False angleGroup = int(chkFunc(other.xformCoord())) if angleGroup in [1,2,5,6]: # in the tetrahedral "dead zones" if debug: print "tetCheck for", tet.oslIdent(), print "; dead zone for", other.oslIdent() return False if angleGroup == 0: if debug: print "tetCheck for", tet.oslIdent(), print "; pointing towards", other.oslIdent(), print "returning", result return result towards.append(other.xformCoord()) # further tests only for 2 of 4 filled... if bonded or len(towards) != 2: return True return _tet2check(tetPos, towards[0], towards[1], partnerPos)
def formDihedral(resBud, real1, tmplRes, a, b): res = resBud.residue inres = filter(lambda a, rb=resBud, r=res: a.residue == r and a != rb, real1.neighbors) if real1.residue != res or len(inres) < 1: raise AssertionError, "Can't form in-residue dihedral for" \ " %s of residue %s" % (bud, res.oslIdent()) real2 = inres[0] xyz0, xyz1, xyz2 = map(lambda a, tr=tmplRes: tr.atomsMap[a.name].coord(), (resBud, real1, real2)) xyz = a.coord() blen = b.length() ang = angle(xyz, xyz0, xyz1) dihed = dihedral(xyz, xyz0, xyz1, xyz2) return addDihedralAtom(a.name, a.element, resBud, real1, real2, blen, ang, dihed)
def patch_residue(residue): if getattr(residue, '_rotamer_torsions', None): return residue._rotamer_torsions = [] # BondRot objects cache alpha_carbon = next((a for a in residue.atoms if a.name == 'CA'), residue.atoms[0]) for chi in range(1, 5): try: atoms = chiAtoms(residue, chi) bond = atoms[1].bondsMap[atoms[2]] br = BondRot(bond) br.rotanchor = box.find_nearest(alpha_carbon, bond.atoms) br.chi = dihedral(*[a.coord() for a in atoms]) residue._rotamer_torsions.append(br) except AtomsMissingError: break except (chimera.error, ValueError) as v: if "cycle" in str(v) or "already used" in str(v): continue # discard bonds in cycles and used! break
def eval_built_conformer(res): from chimera import dihedral builtChi1 = dihedral(res.chiList[0][3].coord, res.chiList[0][2].coord, res.chiList[0][1].coord, res.chiList[0][0].coord) try: badFlag = in_well(res.peakList[0].peak1[0][1], builtChi1) except IndexError: badFlag = True badPeakFlag = False try: if res.peakList[0].peak1[0][0] < 1.0: badPeakFlag = True except IndexError: badFlag = True return badFlag, badPeakFlag, builtChi1
def dihedral(self, br): near, far = self.dihedEndAtoms(br) widgets, nearIndex, nearAtoms, farIndex, farAtoms = \ self.rotInfo[br] return dihedral(near.xformCoord(), br.atoms[0].xformCoord(), br.atoms[1].xformCoord(), far.xformCoord())
def postAdd(fakeN, fakeC): # fix up non-"true" terminal residues (terminal simply because # next residue is missing) for fn in fakeN: try: n = fn.atomsMap["N"][0] ca = fn.atomsMap["CA"][0] c = fn.atomsMap["C"][0] except KeyError: continue dihed = None for cnb in c.primaryNeighbors(): if cnb.name == "N": pn = cnb break else: dihed = 0.0 if dihed is None: try: pr = pn.residue pc = pr.atomsMap["C"][0] pca = pr.atomsMap["CA"][0] if pr.type == "PRO": ph = pr.atomsMap["CD"][0] else: ph = pr.atomsMap["H"][0] except KeyError: dihed = 0.0 for nb in n.primaryNeighbors(): if nb.element.number == 1: nb.molecule.deleteAtom(nb) if fn.type == "PRO": continue if dihed is None: dihed = chimera.dihedral(pc.coord(), pca.coord(), pn.coord(), ph.coord()) replyobj.info("Adding 'H' to %s\n" % str(fn)) from chimera.molEdit import addDihedralAtom, addBond h = addDihedralAtom("H", Element(1), n, ca, c, 1.01, 120.0, dihed, bonded=True) # also need to set N's IDATM type, because if we leave it as # N3+ then the residue will be identified by AddCharge as # terminal and there will be no charge for the H atom n.idatmType = "Npl" for fc in fakeC: try: c = fc.atomsMap["C"][0] except KeyError: continue for nb in c.primaryNeighbors(): if nb.element.number == 1: replyobj.info("Removing spurious proton from" " 'C' of %s\n" % str(fc)) nb.molecule.deleteAtom(nb) # the N proton may have been named 'HN'; fix that try: hn = fc.atomsMap["HN"][0] except KeyError: continue addAtom("H", Element(1), fc, hn.coord(), serialNumber=hn.serialNumber, bondedTo=hn.neighbors[0]) fc.molecule.deleteAtom(hn)
def extractResInfo(res): """Takes a Residue instance. Returns the residue type, phi, psi, and "cis" or "trans". """ try: n = res.atomsMap["N"][0] ca = res.atomsMap["CA"][0] c = res.atomsMap["C"][0] except KeyError, IndexError: return res.type, None, None, "trans" from chimera import dihedral for nb in n.neighbors: if nb.residue != res: phi = dihedral(*tuple([x.xformCoord() for x in [nb, n, ca, c]])) break else: phi = None for nb in c.neighbors: if nb.residue != res: psi = dihedral(*tuple([x.xformCoord() for x in [n, ca, c, nb]])) break else: psi = None # measure dihedral with previous residue... cisTrans = "trans" for nnb in n.neighbors: if nnb.residue == res or nnb.name != "C":