def do_pick(self, picked_bond): # this shouldn't actually happen if going through the "do_select" if picked_bond: self.error = "Error: please select bonds, not atoms" print self.error return atom_name = self.object_prefix + str(self.pick_count) if self.pick_count < 2: self.pickNextAtom(atom_name) else: self.pickNextAtom(atom_name) point1 = cmd.get_atom_coords("(%s%s)" % (self.object_prefix, "0")) point2 = cmd.get_atom_coords("(%s%s)" % (self.object_prefix, "1")) point3 = cmd.get_atom_coords("(%s%s)" % (self.object_prefix, "2")) plane = planeFromPoints(point1, point2, point3, self.facetSize) planeName = "plane-%02d" % self.object_count self.object_count += 1 makePrimitive(plane, planeName) cmd.show("cgo", "plane*") self.pick_count = 0 self.reset()
def test_protect(self): cmd.pseudoatom('m1', pos=[0.,0.,0.]) cmd.pseudoatom('m1', pos=[1.,0.,0.]) cmd.protect('m1`1') cmd.translate([0.,1.,0.]) self.assertEqual([0.,0.,0.], cmd.get_atom_coords('m1`1')) self.assertEqual([1.,1.,0.], cmd.get_atom_coords('m1`2')) cmd.deprotect() cmd.translate([0.,0.,1.]) self.assertEqual([0.,0.,1.], cmd.get_atom_coords('m1`1')) self.assertEqual([1.,1.,1.], cmd.get_atom_coords('m1`2'))
def getxyz(Sel): if type(Sel)==list and len(Sel)==3: return Sel, "listXYZ" if type(Sel)==str and Sel[0]=="[" and Sel[-1]=="]": Selsplit = list(Sel[1:-1].split(",")) Selsplit = [float(x) for x in Selsplit] return Selsplit, "strXYZ" if type(Sel)==str: pos = cmd.get_atom_coords(Sel) return pos, "selXYZ"
def get_coord(v): if not isinstance(v, str): try: return v[:3] except: return False if v.startswith('['): return cmd.safe_list_eval(v)[:3] try: if cmd.count_atoms(v)==1: # atom coordinates return cmd.get_atom_coords(v) else: # more than one atom --> use "center" # alt check! if cmd.count_atoms('(alt *) and not (alt "")')!=0: print "distancetoatom: warning! alternative coordinates found for origin, using center!" view_temp=cmd.get_view() cmd.zoom(v) v=cmd.get_position() cmd.set_view(view_temp) return v except: return False
def get_coord(v): if not isinstance(v, str): return v if v.startswith('['): return cmd.safe_list_eval(v) return cmd.get_atom_coords(v)
def Coord(Input): print(cmd.get_atom_coords(Input))
def AtomVector(AtomStart, AtomEnd): PosStart = cmd.get_atom_coords(AtomStart) PosEnd = cmd.get_atom_coords(AtomEnd) VectorDiff = [(PosEnd[0] - PosStart[0]), (PosEnd[1] - PosStart[1]), (PosEnd[2] - PosStart[2])] return VectorDiff
def cyspka(molecule, chain, residue, SeeProgress='yes', pH=7.2, MoveSGatom='no', SGatom=str((0, 0, 0))): # If SeeProgress='yes', computation time will take 10-20% extra, but nice to follow. cmd.refresh() RotationRange = 360 RotationDegree = 1 # For error checking, the energies can be printed out printMC = 'no' printSC = 'no' # Parameters DieElecSpheDist = 7.0 DieElecWaterDist = 1.4 DieElecWater = 78.5 DieElecCore = 4.0 BornPenaltyB = 1.0 AvogadroR = 8.31446216 Temp = 298 DeltapKMCSC = 0 pK1 = 9.25 pK2 = 8.0 NotPopuDist = 2.4 PopEnergyPenalty = 10000000 # Side chain discrete charges DieElecSC = 40.0 SCchargeASP = -1 SCchargeGLU = -1 SCchargeOXT = -1 SCchargeARG = +1 SCchargeHIS = +1 SCchargeLYS = +1 SCchargeMET1 = +1 # Main chain partial charges NrMainchainNeighBours = 5 DieElecMC = 22.0 MCchargeC = +0.55 MCchargeO = -0.55 MCchargeN = -0.35 MCchargeH = +0.35 MCchargeProCA = +0.1 MCchargeProCD = +0.1 MCchargeProN = -0.2 # Loading an Cys residue, give it a logic name, and aligning it. The oxygen atom can not be aligned in many cases, and are skipped. # We use only this molecule, to find the initial position of the SG atom, and to rotate the SG atom around the CA-CB bond. The molecule atom positions are not used for electric potential calculatons. Cysmolecule = str(molecule) + str(residue) + "Cys" cmd.fragment("cys") cmd.set_name('cys', Cysmolecule) # We use pair_fir, since align and super gets unstable with so few atoms pairfitCys(Cysmolecule, molecule, chain, residue) # Give nice representations quickly cmd.show("sticks", Cysmolecule) cmd.select(str(molecule) + str(residue) + "Res", "/" + molecule + "//" + chain + "/" + residue) print("/" + molecule + "//" + chain + "/" + residue) cmd.show("sticks", str(molecule) + str(residue) + "Res") cmd.disable(str(molecule) + str(residue) + "Res") # Find out what is the residuename we are investigating for Respdbstr = cmd.get_pdbstr(str(molecule) + str(residue) + "Res") Ressplit = Respdbstr.split() residueName = Ressplit[3] print("") print("# Hello, PyMOLers. It should take around 1 minute per residue.") print("# molecule: %s , chain: %s, residue: %s %s, pH: %s " % (molecule, chain, residueName, residue, pH)) # Determine the range of neighbour residues possible. Maxresidues = cmd.count_atoms("/" + molecule + "//" + chain + " and name CA") for i in range(NrMainchainNeighBours + 1): if int(residue) - i >= 1: Minresidue = int(residue) - i else: break for i in range(NrMainchainNeighBours + 1): if int(residue) + i <= Maxresidues: Maxresidue = int(residue) + i else: break # Get the position and the vector for the CA->CB bond. dihedN = "/" + Cysmolecule + "//" + "/" + "/N" dihedCA = "/" + Cysmolecule + "//" + "/" + "/CA" dihedCB = "/" + Cysmolecule + "//" + "/" + "/CB" dihedSG = "/" + Cysmolecule + "//" + "/" + "/SG" dihedralPosCA = cmd.get_atom_coords(dihedCA) dihedralPosSG = cmd.get_atom_coords(dihedSG) dihedralVector = AtomVector(dihedCA, dihedCB) # To compare with article, we can move the SGatom to a starting position. The rotation is still determined around the CA-CB bond. if MoveSGatom == 'yes': SGatom = [float(SGatom[1:-1].split(",")[0]), float(SGatom[1:-1].split(",")[1]), float(SGatom[1:-1].split(",")[2])] Translate = [(SGatom[0] - dihedralPosSG[0]), (SGatom[1] - dihedralPosSG[1]), (SGatom[2] - dihedralPosSG[2])] cmd.translate(Translate, dihedSG, state=0, camera=0) dihedralPosSG = cmd.get_atom_coords(dihedSG) # Create a pymol molecule, that in the end will hold and show all SG atoms. Gives the representation of the rotameric states. SGName = str(molecule) + str(residue) + "SG" cmd.create(SGName, "None") # Create a pymol molecule, that in the end will hold and show all Amide protons. Gives a nice representation, and easy to delete. AmideName = str(molecule) + str(residue) + "NH" cmd.create(AmideName, "None") # Check if there are any nearby SG atoms, which could make a SG-SG dimer formation. The breakDimer = "no" breakDimer = CheckDimer(dihedSG, molecule, chain, residue) # Create a list for appending the calculated energies. ListofEnergies = [] ListofRotamerDiscarded = [] # print "Angle before rotation", cmd.get_dihedral(dihedN,dihedCA,dihedCB,dihedSG) # Enter into the loop of rotameric states for i in range(int(math.floor(RotationRange / RotationDegree))): Angle = i * RotationDegree # Create pymol molecule/SG atom for which we will calculate for. SGNameAngle = str(residue) + "SG" + str(Angle) cmd.create(SGNameAngle, dihedSG) # Calculate new coordinates for rotation around CA->CB bond. Then translate the created SG atom. SGNewPos = fRotateAroundLine(dihedralPosSG, dihedralPosCA, dihedralVector, Angle) Translate = [(SGNewPos[0] - dihedralPosSG[0]), (SGNewPos[1] - dihedralPosSG[1]), (SGNewPos[2] - dihedralPosSG[2])] cmd.translate(Translate, SGNameAngle, state=0, camera=0) # If one wants to "see it happen" while its making the states. But it will take extra computation time. if SeeProgress == 'yes': cmd.refresh() # Calculate number of neighbours within 2.4 Angstrom. Amide hydrogens are not considered, and are actually not build yet. nameselect = "(((/" + molecule + "//" + chain + " and not /" + molecule + "//" + chain + "/" + residue + ") or /" + molecule + "//" + chain + "/" + residue + "/N+CA+C+O) within " + str(NotPopuDist) + " of /" + SGNameAngle + "//" + "/" + "/SG) and not resn HOH" # print nameselect cmd.select("NotPop", nameselect) NotPopNr = cmd.count_atoms("NotPop") # print Angle, NotPopNr, cmd.get_dihedral(dihedN,dihedCA,dihedCB,SGNameAngle) # If no neighbours, then proceed calculating if NotPopNr == 0: SumAllWMC = 0.0 # Now calculate the electric potential due to the side chains. SumWSC = fSumWSC(molecule, SGNameAngle, chain, residue, DieElecSC, SCchargeASP, SCchargeGLU, SCchargeOXT, SCchargeARG, SCchargeHIS, SCchargeLYS, SCchargeMET1, printSC) # Now we calculate for the flanking 5 peptide groups on each side of the Cysteine CA atom. # For the first residue, only calculate for the tailing C,O atom in the peptide bond. No test for Proline. SumWMCFirst = fSumWMCFirst(molecule, SGNameAngle, chain, residue, Minresidue, DieElecMC, MCchargeC, MCchargeO, printMC) # For the residue itself, we dont test for PRO, since it should be a Cysteine. SumWMCresidue = fSumWMCresidue(molecule, SGNameAngle, chain, residue, int(residue), DieElecMC, MCchargeC, MCchargeO, MCchargeN, MCchargeH, AmideName, printMC) # For the last residue, we test for Proline. We only calculate for the N,H atom, or if Proline, N,CA and CD atom. SumWMCLast = fSumWMCLast(molecule, SGNameAngle, chain, residue, Maxresidue, DieElecMC, MCchargeN, MCchargeH, MCchargeProCA, MCchargeProCD, MCchargeProN, AmideName, printMC) # Then loop over rest of the residues in the chain. for j in (list(range(Minresidue + 1, int(residue))) + list(range(int(residue) + 1, Maxresidue))): MCNeighbour = j # print "Looking at neighbour", j SumWMC = fSumWMC(molecule, SGNameAngle, chain, residue, MCNeighbour, DieElecMC, MCchargeC, MCchargeO, MCchargeN, MCchargeH, MCchargeProCA, MCchargeProCD, MCchargeProN, AmideName, printMC) SumAllWMC = SumAllWMC + SumWMC # print "Rotation: %s Neighbour: %s " % (Angle, j) # Since the SG atom is negative, we multiply with -1. SumMCSC = -1 * (SumWSC + SumWMCFirst + SumWMCresidue + SumWMCLast + SumAllWMC) # Makes the neighbour count. Everything in 'molecule" within 7 ang of aligned SG atom. Not counting 'residue'. Adding 5 for 'residue' N,CA,C,O,CB ListNeighbourCount = fNeighbourCount(molecule, SGNameAngle, chain, residue, DieElecSpheDist) # Calculate the weighted electric potential and alter the b factor for coloring. Then add the rotated SG into bucket of SG atoms. SG_MCSC_Weight = fBoltzSingleState(SumMCSC, AvogadroR, Temp) * SumMCSC cmd.alter(SGNameAngle, 'b="%s"' % SG_MCSC_Weight) cmd.alter(SGNameAngle, 'name="S%s"' % Angle) cmd.create(SGName, SGName + " + " + SGNameAngle) # Then save the calculated values ListofEnergies.append([Angle, SumMCSC, ListNeighbourCount, NotPopNr, SG_MCSC_Weight, cmd.get_atom_coords(SGNameAngle)]) cmd.delete(SGNameAngle) else: SumMCSCPenalty = PopEnergyPenalty ListNeighbourCount = fNeighbourCount(molecule, SGNameAngle, chain, residue, DieElecSpheDist) ListofRotamerDiscarded.append([Angle, SumMCSCPenalty, ListNeighbourCount, NotPopNr, 0, cmd.get_atom_coords(SGNameAngle)]) cmd.delete(SGNameAngle) # Now show all the SG atoms as the available rotameric states. cmd.show("nb_spheres", SGName) cmd.delete("NotPop") cmd.spectrum("b", selection=SGName) AvailRotStates = len(ListofEnergies) # print "Available Rotational States: ", AvailRotStates # Do the calculations according to eq 5. # Find the partition function BoltzPartition = 0.0 for i in range(len(ListofEnergies)): Boltz = fBoltzSingleState(ListofEnergies[i][1], AvogadroR, Temp) BoltzPartition = BoltzPartition + Boltz # Find the summed function BoltzSumNi = 0.0 for i in range(len(ListofEnergies)): BoltzNi = fBoltzSingleState(ListofEnergies[i][1], AvogadroR, Temp) * ListofEnergies[i][1] BoltzSumNi = BoltzSumNi + BoltzNi # Check if there was any possible rotamers nostates = "no" if len(ListofEnergies) == 0: print("####################################################") print("########### WARNING: No states available ###########") print("########### Did you mutate a Glycine? ###########") print("####################################################") BoltzSumNi = 0 BoltzPartition = 0 BoltzMCSC = 0 DeltapKMCSC = 99 NeighbourCount = 0 nostates = "yes" else: # Final calculation BoltzMCSC = (BoltzSumNi) / (BoltzPartition) DeltapKMCSC = fDeltapK(BoltzMCSC, AvogadroR, Temp) # Find average number of neighbours NCSum = 0.0 NCWeightedSum = 0.0 for i in range(len(ListofEnergies)): NCi = ListofEnergies[i][2] NCSum = NCSum + NCi NCWeightedi = fBoltzSingleState(ListofEnergies[i][1], AvogadroR, Temp) * ListofEnergies[i][2] / BoltzPartition NCWeightedSum = NCWeightedSum + NCWeightedi # print "Weighted neighbour", int(round(NCWeightedSum)) #NeighbourCount = int(round(NCSum/len(ListofEnergies))) NeighbourCount = round(NCWeightedSum, 1) # If we found dimers if breakDimer == "yes": print("####################################################") print("########### WARNING: Dimer formation? ###########") print("####################################################") BoltzSumNi = 0 BoltzPartition = 0 BoltzMCSC = 0 DeltapKMCSC = 99 NeighbourCount = 0 # Calculate the BornPenalty based on the neighbour count. It's a wrapper script for equation 13, 12, 11. EnergyBornPenalty = fEnergyBornPenalty(DieElecSpheDist, DieElecWaterDist, NeighbourCount, DieElecWater, DieElecCore, BornPenaltyB) DeltapKB = fDeltapK(EnergyBornPenalty, AvogadroR, Temp) # Do the calculations according to eq 3 and 9. pKm1 = fpKm1(DeltapKMCSC, pK1) pKm2 = fpKm2(DeltapKMCSC, DeltapKB, pK2) FracCysm1 = fFracCys(pKm1, pH) FracCysm2 = fFracCys(pKm2, pH) # Lets make a result file, and write out the angle, the SumMCSC, and the number of neighbours for this state. Currentdir = os.getcwd() Newdir = os.path.join(os.getcwd(), "Results") if not os.path.exists(Newdir): os.makedirs(Newdir) filename = os.path.join(".", "Results", "Result_" + molecule + "_" + chain + "_" + residue + ".txt") filenamelog = os.path.join(".", "Results", "Result_log.log") logfile = open(filenamelog, "a") outfile = open(filename, "w") timeforlog = strftime("%Y %b %d %a %H:%M:%S", localtime()) logfile.write("# " + timeforlog + "\n") logfile.write("# molecule: %s , chain: %s, residue: %s %s, pH: %s " % (molecule, chain, residueName, residue, pH) + "\n") logfile.write("# BoltzSumNi: BoltzPartition: BoltzMCSC" + "\n") logfile.write(("# %.4f %.4f %.4f" + '\n') % (BoltzSumNi, BoltzPartition, BoltzMCSC)) logfile.write("# Res NC States pKmcsc pK1 pKB pK2 pKm1 pKm2 f(C-)m1 f(C-)m2" + "\n") logfile.write(("; %s %s %s %s %.4f %s %.4f %s %.4f %.4f %.6f %.6f" + '\n') % (residueName, residue, NeighbourCount, AvailRotStates, DeltapKMCSC, pK1, DeltapKB, pK2, pKm1, pKm2, FracCysm1, FracCysm2)) if nostates == "yes": logfile.write("##### ERROR; No states available ###" + "\n") if breakDimer == "yes": logfile.write("##### ERROR; Dimer formation ###" + "\n") logfile.write('\n') outfile.write("# molecule: %s , chain: %s, residue: %s %s, pH: %s " % (molecule, chain, residueName, residue, pH) + "\n") outfile.write("# BoltzSumNi: BoltzPartition: BoltzMCSC" + "\n") outfile.write(("# %.4f %.4f %.4f" + '\n') % (BoltzSumNi, BoltzPartition, BoltzMCSC)) outfile.write("# Res NC States pKmcsc pK1 pKB pK2 pKm1 pKm2 f(C-)m1 f(C-)m2" + "\n") outfile.write(("; %s %s %s %s %.4f %s %.4f %s %.4f %.4f %.6f %.6f" + '\n') % (residueName, residue, NeighbourCount, AvailRotStates, DeltapKMCSC, pK1, DeltapKB, pK2, pKm1, pKm2, FracCysm1, FracCysm2)) if nostates == "yes": outfile.write("##### ERROR; No states available ###" + "\n") if breakDimer == "yes": outfile.write("##### ERROR; Dimer formation ###" + "\n") outfile.write('\n') outfile.write("#Ang SumMCSC NC rNC MCSC_Weight SG[X,Y,Z]" + "\n") for i in range(len(ListofEnergies)): outfile.write("%4.1d %10.3f %2.1d %1.1d %10.3f [%8.3f, %8.3f, %8.3f]" % (ListofEnergies[i][0], ListofEnergies[i][1], ListofEnergies[i][2], ListofEnergies[i][3], ListofEnergies[i][4], ListofEnergies[i][5][0], ListofEnergies[i][5][1], ListofEnergies[i][5][2]) + '\n') for i in range(len(ListofRotamerDiscarded)): outfile.write("%4.1d %10.3f %2.1d %1.1d %10.3f [%8.3f, %8.3f, %8.3f]" % (ListofRotamerDiscarded[i][0], ListofRotamerDiscarded[i][1], ListofRotamerDiscarded[i][2], ListofRotamerDiscarded[i][3], ListofRotamerDiscarded[i][4], ListofRotamerDiscarded[i][5][0], ListofRotamerDiscarded[i][5][1], ListofRotamerDiscarded[i][5][2]) + '\n') outfile.close() # Now, we are done. Just print out. The ; is for a grep command to select these lines in the output. print("# residue: %s %s. Average NeighbourCount NC= %s " % (residueName, residue, NeighbourCount)) print("# From residue %s to residue %s" % (Minresidue, Maxresidue)) print("# BoltzSumNi: BoltzPartition: BoltzMCSC") print("# %.4f %.4f %.4f" % (BoltzSumNi, BoltzPartition, BoltzMCSC)) print("# Result written in file: %s" % (filename)) print("# Res NC States pKmcsc pK1 pKB pK2 pKm1 pKm2 f(C-)m1 f(C-)m2") print("; %s %s %s %s %.4f %s %.4f %s %.4f %.4f %.6f %.6f" % (residueName, residue, NeighbourCount, AvailRotStates, DeltapKMCSC, pK1, DeltapKB, pK2, pKm1, pKm2, FracCysm1, FracCysm2)) if nostates == "yes": print("##### ERROR; No states available ###") if breakDimer == "yes": print("##### ERROR; Dimer formation ###")
def rpcGetAtomCoords(what='all', state=0): """ returns the results of cmd.get_atom_coords(what,state) """ return cmd.get_atom_coords(what, state=state)
def elbow_angle(obj, light='L', heavy='H', limit_l=107, limit_h=113, draw=0): """ DESCRIPTION Calculates the integer elbow angle of an antibody Fab complex and optionally draws a graphical representation of the vectors used to determine the angle. ARGUMENTS obj = string: object light/heavy = strings: chain ID of light and heavy chains, respectively limit_l/limit_h = integers: residue numbers of the last residue in the light and heavy chain variable domains, respectively draw = boolean: Choose whether or not to draw the angle visualization REQUIRES: com.py, transformations.py, numpy (see above) """ # store current view orig_view = cmd.get_view() limit_l = int(limit_l) limit_h = int(limit_h) draw = int(draw) # for temp object names tmp_prefix = "tmp_elbow_" prefix = tmp_prefix + obj + '_' # names vl = prefix + 'VL' vh = prefix + 'VH' cl = prefix + 'CL' ch = prefix + 'CH' # selections vl_sel = 'polymer and %s and chain %s and resi 1-%i' % (obj, light, limit_l) vh_sel = 'polymer and %s and chain %s and resi 1-%i' % (obj, heavy, limit_h) cl_sel = 'polymer and %s and chain %s and not resi 1-%i' % (obj, light, limit_l) ch_sel = 'polymer and %s and chain %s and not resi 1-%i' % (obj, heavy, limit_h) v_sel = '((' + vl_sel + ') or (' + vh_sel + '))' c_sel = '((' + cl_sel + ') or (' + ch_sel + '))' # create temp objects cmd.create(vl, vl_sel) cmd.create(vh, vh_sel) cmd.create(cl, cl_sel) cmd.create(ch, ch_sel) # superimpose vl onto vh, calculate axis and angle Rv = calc_super_matrix(vl, vh) angle_v, direction_v, point_v = transformations.rotation_from_matrix(Rv) # superimpose cl onto ch, calculate axis and angle Rc = calc_super_matrix(cl, ch) angle_c, direction_c, point_c = transformations.rotation_from_matrix(Rc) # delete temporary objects cmd.delete(vl) cmd.delete(vh) cmd.delete(cl) cmd.delete(ch) # if dot product is positive, angle is acute if (numpy.dot(direction_v, direction_c) > 0): direction_c = direction_c * -1 # ensure angle is > 90 (need to standardize this) # TODO: make both directions point away from the elbow axis. elbow = int(numpy.degrees(numpy.arccos(numpy.dot(direction_v, direction_c)))) # while (elbow < 90): # elbow = 180 - elbow # limit to physically reasonable range # compare the direction_v and direction_c axes to the vector defined by # the C-alpha atoms of limit_l and limit_h of the original fab hinge_l_sel = "%s//%s/%s/CA" % (obj, light, limit_l) hinge_h_sel = "%s//%s/%s/CA" % (obj, heavy, limit_h) hinge_l = cmd.get_atom_coords(hinge_l_sel) hinge_h = cmd.get_atom_coords(hinge_h_sel) hinge_vec = numpy.array(hinge_h) - numpy.array(hinge_l) test = numpy.dot(hinge_vec, numpy.cross(direction_v, direction_c)) if (test > 0): elbow = 360 - elbow print " Elbow angle: %i degrees" % elbow if (draw == 1): # there is probably a more elegant way to do this, but # it works so I'm not going to mess with it for now pre = obj + '_elbow_' # draw hinge vector cmd.pseudoatom(pre + "hinge_l", pos=hinge_l) cmd.pseudoatom(pre + "hinge_h", pos=hinge_h) cmd.distance(pre + "hinge_vec", pre + "hinge_l", pre + "hinge_h") cmd.set("dash_gap", 0) # draw the variable domain axis com_v = com.COM(v_sel) start_v = [a - 10 * b for a, b in zip(com_v, direction_v)] end_v = [a + 10 * b for a, b in zip(com_v, direction_v)] cmd.pseudoatom(pre + "start_v", pos=start_v) cmd.pseudoatom(pre + "end_v", pos=end_v) cmd.distance(pre + "v_vec", pre + "start_v", pre + "end_v") # draw the constant domain axis com_c = com.COM(c_sel) start_c = [a - 10 * b for a, b in zip(com_c, direction_c)] end_c = [a + 10 * b for a, b in zip(com_c, direction_c)] cmd.pseudoatom(pre + "start_c", pos=start_c) cmd.pseudoatom(pre + "end_c", pos=end_c) cmd.distance(pre + "c_vec", pre + "start_c", pre + "end_c") # customize appearance cmd.hide("labels", pre + "hinge_vec") cmd.hide("labels", pre + "v_vec") cmd.hide("labels", pre + "c_vec") cmd.color("green", pre + "hinge_l") cmd.color("red", pre + "hinge_h") cmd.color("black", pre + "hinge_vec") cmd.color("black", pre + "start_v") cmd.color("black", pre + "end_v") cmd.color("black", pre + "v_vec") cmd.color("black", pre + "start_c") cmd.color("black", pre + "end_c") cmd.color("black", pre + "c_vec") # draw spheres cmd.show("spheres", pre + "hinge_l or " + pre + "hinge_h") cmd.show("spheres", pre + "start_v or " + pre + "start_c") cmd.show("spheres", pre + "end_v or " + pre + "end_c") cmd.set("sphere_scale", 2) cmd.set("dash_gap", 0, pre + "hinge_vec") cmd.set("dash_width", 5) cmd.set("dash_radius", 0.3) # group drawing objects cmd.group(pre, pre + "*") # restore original view cmd.set_view(orig_view) return 0
def distancetoatom( origin='pk1', cutoff=10, filename=None, selection='all', state=0, property_name='p.dist', coordinates=0, decimals=3, sort=1, quiet=1 ): ''' DESCRIPTION distancetoatom.py Described at: http://www.pymolwiki.org/Distancetoatom Prints all distanced between the specified atom/coordinate/center and all atoms within cutoff distance that are part of the selection. All coordinates and distances can be saved in a csv-style text file report and can be appended to a (custom) atom property, if defined. USAGE distancetoatom [ origin [, cutoff [, filename [, selection [, state [, property_name [, coordinates [, decimals [, sort [, quiet ]]]]]]]]]] ARGUMENTS NAME TYPE FUNCTION origin: <list> defines the coordinates for the origin and can be: <str> 1. a list with coordinates [x,y,z] 2. a single atom selection string {default='pk1'} 3. a multi-atom selection string (center will be used) cutoff <float> sets the maximum distance {default: 10} filename <str> filename for optional output report. {default=None} set to e.g. 'report.txt' to create a report (omit or set to '', None, 0 or False to disable) selection <str> can be used to define/limit the measurment to specific sub-selections {default='all'} state <int> object state, {default=0} # = current property_name <str> the distance will be stored in this property {p.dist} set "" to disable coordinates <int> toggle whether atom coordinated will be reported {0} decimals <int> decimals for coordinates and distance: default = 3 # = max. PDB resolution sort <int> Sorting by distance? 1: ascending (default) 0: no sorting (by names) -1: descending quiet <bool> toggle verbosity ''' # keyword check try: selection = '(%s)'%selection ori=get_coord(origin) if not ori: print "distancetoatom: aborting - check input for 'origin'!" return False cutoff = abs(float(cutoff)) filename = str(filename) state = abs(int(state)) if (not int(state)): state=cmd.get_state() cmd.set('state', state) # distance by state property_name = str(property_name) decimals = abs(int(decimals)) sort = int(sort) coordinates=bool(int(coordinates)) quiet=bool(int(quiet)) except: print 'distancetoatom: aborting - input error!' return False # round origin ori = [round(x,decimals) for x in ori] # report? if filename in ['', '0', 'False', 'None']: filename=False else: try: report=open(filename,'w') # file for writing except: print 'distancetoatom: Unable to open report file! - Aborting!' return False # temporary name for pseudoatom tempname = cmd.get_unused_name('temp_name') tempsel = cmd.get_unused_name('temp_sel') #origin cmd.pseudoatom(object=tempname, resi=1, pos=ori) # select atoms within cutoff cmd.select(tempsel, '(%s around %f) and (%s) and state %d' %(tempname, cutoff, selection, state)) cmd.delete(tempname) # single atom ori and part of selection # avoid double reporting! single_atom_ori=False try: if cmd.count_atoms('(%s) and (%s) and (%s)'%(selection, tempsel, origin))==1: single_atom_ori=True except: pass # pass= coordinates or multi-atom or single, not selected --> report ori # atom list stored.temp=[] cmd.iterate(tempsel, 'stored.temp.append([model, segi, chain, resn, resi, name, alt])') # custom properties? # conditional disabling if (property_name==''): property_name=False if ((cmd.get_version()[1]<1.7) and (property_name not in ['b','q'])): property_name=False # calculate the distances, creating list distance_list=[] if (not single_atom_ori): distance_list.append(['ORIGIN: '+str(origin), ori[0], ori[1], ori[2], 0.0]) for atom in stored.temp: atom_name = ('/%s/%s/%s/%s`%s/%s`%s'%(atom[0], atom[1], atom[2], atom[3], atom[4], atom[5], atom[6])) atom_xyz = [round(x, decimals) for x in cmd.get_atom_coords(atom_name)] atom_dist = round(cpv.distance(ori, atom_xyz), decimals) distance_list.append([atom_name,atom_xyz[0],atom_xyz[1],atom_xyz[2], atom_dist]) # create property with distance (can be used for coloring, labeling etc) if property_name: try: cmd.alter(atom_name, '%s=%f'%(property_name, atom_dist)) except: # I'm not sure alter raises exceptions if the property is illegal property_name=False # sort list, if selected if sort>0: distance_list.sort(key=lambda dist: dist[4]) elif sort<0: distance_list.sort(key=lambda dist: dist[4], reverse=True) # add header distance_list=[['Atom Macro ID', 'x-coord', 'y-coord', 'z-coord', 'distance_to_origin'] ]+distance_list if ((not quiet) and (filename)): # Hijack stdout to print to file and console class logboth(object): def __init__(self, *files): self.files = files def write(self, obj): for f in self.files: f.write(obj) originalstdout = sys.stdout sys.stdout = logboth(sys.stdout, report) for entry in distance_list: if coordinates: output= '%s, %s, %s, %s, %s' %(entry[0],entry[1],entry[2],entry[3],entry[4]) #csv style else: output= '%s, %s' %(entry[0],entry[4]) #csv style if (not quiet): print output elif filename: report.write(output+'\n') # restore regular stdout if ((not quiet) and (filename)): sys.stdout = originalstdout # close file if filename: report.close() if (not quiet): if property_name: print 'Distances saved to property: %s' %str(property_name) else: print 'Distances NOT saved to property (illegal custom property)'
def cgo_grid( pos1=[0,0,0], pos2=[1,0,0], pos3=[0,0,1], length_x=30, length_z='', npoints_x='', npoints_z='', nwaves_x=2, nwaves_z='', offset_x=0, offset_z='', gain_x=1, gain_z='', thickness=2.0, color='', nstates=60, startframe=1, endframe=1, mode=0, view=0, name='', quiet=1): ''' DESCRIPTION Generates an animated flowing mesh object using the points provided or the current view. The shape is affected substantially by the arguments! USEAGE cgo_grid [ pos1 [, pos2 [, pos3 [, length_x [, length_z [, npoints_x [, npoints_z [, nwaves_x [, nwaves_z [, offset_x [, offset_z [, gain_x [, gain_z [, thickness [, color [, nstates [, startframe [, endframe [, mode [, view [, name [, quiet ]]]]]]]]]]]]]]]]]]]]]] EXAMPLE cgo_grid view=1 ARGUMENTS pos1 = single atom selection (='pk1') or list of 3 floats {default: [0,0,0]} pos2 = single atom selection (='pk2') or list of 3 floats {default: [1,0,0]} pos3 = single atom selection (='pk3') or list of 3 floats {default: [0,0,1]} --> the plane is defined by pos1 (origin) and vectors to pos2 and pos3, respectively length_x = <float>: length of membrane {default: 30} length_z = <float>: length of membrane {default: ''} # same as length_x npoints_x = <int>: number of points(lines) along x-direction {default: ''} #will be set to give a ~1 unit grid npoints_z = <int>: number of points(lines) along z-direction {default: ''} #will be set to give a ~1 unit grid {minimum: 1 # automatic} nwaves_x = <float>: number of complete sin waves along object x-axis {default: 2} nwaves_z = <float>: number of complete sin waves along object z-axis {default: ''} # same as nwaves_x define separately to adjust number of waves in each direction offset_x = <float> phase delay (in degrees) of sin wave in x-axis can be set to affect shape and starting amplitude {default: 0} offset_z = <float> phase delay (in degrees) of sin wave in z-axis can be set to affect shape and starting amplitude {default: ''} # same as offset_x offset_x and offset_z can be used together to phase otherwise identical objects gain_x = <float>: multiplication factor for y-amplitude for x-direction {default: 1} gain_z = <float>: multiplication factor for y-amplitude for z-direction {default: ''} #=gain_x thickness = <float>: line thickness {default: 2} color = color name <string> (e.g. 'skyblue') OR rgb-value list of 3 floats (e.g. [1.0,1.0,1.0]) OR {default: ''} // opposite of background input illegal values for random coloring nstates = <int>: number of states; {default: 60} this setting will define how many states the object will have (per wave) and how fluent and fast the animation will be. Higher values will promote 'fluent' transitions, but decrease flow speed. Note: Frame animation cycles thought the states one at a time and needs to be set accordingly. Can also be used to phase otherwise identical objects. Set to 1 for static object {automatic minimum} startframe: specify starting frame <int> or set (='') to use current frame set to 'append' to extend movie from the last frame {default: 1} endframe: specify end frame <int> or set (='') to use last frame if 'append' is used for startframe, endframe becomes the number of frames to be appended instead {default: 1} Note: if start- and endframe are the same, movie animation will be skipped, the object will be loaded and can be used afterwards mode: defines positioning {default: 0}: 0: pos1 is center 1: pos1 is corner view {default: 0}: '0': off/ uses provided points to create CGO '1': overrides atom selections and uses current orienatation for positioning - pos1 = origin/center - pos2 = origin +1 in camera y - pos3 = origin +1 in camera z name: <string> name of cgo object {default: ''} / automatic quiet: <boolean> toggles output ''' ########## BEGIN OF FUNCTION CODE ########## def get_coord(v): if not isinstance(v, str): try: return v[:3] except: return False if v.startswith('['): return cmd.safe_list_eval(v)[:3] try: if cmd.count_atoms(v)==1: # atom coordinates return cmd.get_atom_coords(v) else: # more than one atom --> use "center" # alt check! if cmd.count_atoms('(alt *) and not (alt "")')!=0: print("cgo_grid: warning! alternative coordinates found for origin, using center!") view_temp=cmd.get_view() cmd.zoom(v) v=cmd.get_position() cmd.set_view(view_temp) return v except: return False def eval_color(v): try: if not v: v=eval(cmd.get('bg_rgb')) v=list(map(sum, list(zip(v,[-1,-1,-1])))) v=list(map(abs, v)) if v[0]==v[1]==v[2]==0.5: # grey v=[0,0,0] return v if isinstance(v, list): return v[0:3] if not isinstance(v, str): return v[0:3] if v.startswith('['): return cmd.safe_list_eval(v)[0:3] return list(cmd.get_color_tuple(v)) except: return [random.random(),random.random(),random.random()] cmd.extend("eval_color", eval_color) color=eval_color(color) try: mode=int(mode) except: raise Exception("Input error in Mode") if mode<0 or mode>1: raise Exception("Mode out of range!") try: nstates=int(nstates) if nstates<1: nstates=1 print("NB! nstates set to 1 (automatic minimum)") length_x=float(length_x) if length_z=='': length_z=length_x else: length_z=float(length_z) if npoints_x=='': npoints_x=int(length_x)+1 else: npoints_x=int(npoints_x) if npoints_x<1: npoints_x=1 print("NB! npoints_x set to 1 (automatic minimum)") if npoints_z =='': npoints_z=int(length_z)+1 else: npoints_z=int(npoints_z) if npoints_z<1: npoints_z=1 print("NB! npoints_x set to 1 (automatic minimum)") nwaves_x=abs(float(nwaves_x)) if nwaves_z=='': nwaves_z=nwaves_x else: nwaves_z=abs(float(nwaves_z)) offset_x=float(offset_x)*math.pi/180 if offset_z=='': offset_z=offset_x else: offset_z=float(offset_z)*math.pi/180 thickness=float(thickness) gain_x=float(gain_x) if gain_z=='': gain_z=gain_x else: gain_z=float(gain_z) if not name: name = cmd.get_unused_name('membrane') else: name = str(name) if int(quiet): quiet=True else: quiet=False if int(view): view=True else: view=False except: raise Exception("Input error in parameters!") #prevent auto zooming on object temp_auto_zoom=cmd.get('auto_zoom') cmd.set('auto_zoom', '0') if int(view): xyz1=cmd.get_position() tempname = cmd.get_unused_name('temp') ori_ax=[[0,0,0],[10,0,0],[0,0,10]] for a in range (0,len(ori_ax)): cmd.pseudoatom(tempname, resi=''+str(a+1)+'', pos=xyz1) cmd.translate(ori_ax[a], selection=''+tempname+' and resi '+str(a+1)+'', camera='1') ori_ax[a]=cmd.get_atom_coords(''+tempname+' and resi '+str(a+1)+'') cmd.delete(tempname) xyz1=ori_ax[0] xyz2=ori_ax[1] xyz3=ori_ax[2] else: xyz1 = get_coord(pos1) xyz2 = get_coord(pos2) xyz3 = get_coord(pos3) if (not startframe): startframe=cmd.get('frame') if (not endframe): endframe=cmd.count_frames() if endframe==0: endframe=1 if (startframe=='append'): startframe=cmd.count_frames()+1 try: endframe=int(endframe) cmd.madd('1 x'+str(endframe)) endframe=cmd.count_frames() except ValueError: raise Exception("Input error: Value for 'endframe' is not integer!") try: startframe=int(startframe) endframe=int(endframe) endframe/startframe startframe/endframe except ValueError: raise Exception("Input error: Failed to convert to integer!") except ZeroDivisionError: raise Exception("Error: unexpected zero value!") except: raise Exception("Unexpected error!") if (nstates==1): if not quiet: print("Creating one state object!") if startframe > endframe: startframe, endframe = endframe, startframe if not quiet: print("Inverted start and end frames!") ########## BEGIN OF FUNCTIONAL SCRIPT ########## #normalize and get orthogonal vector # define vectors from points xyz2 = cpv.sub(xyz2, xyz1) xyz3 = cpv.sub(xyz3, xyz1) #NB! cpv.get_system2 outputs normalized vectors [x,y,z] xyz4 = cpv.get_system2(xyz2,xyz3) xyz2 = xyz4[0] xyz3 = xyz4[1] for x in range(0,3): for z in range(0,3): if x==z: continue if xyz4[x]==xyz4[z]: raise Exception("Illegal vector settings!") xyz4 = cpv.negate(xyz4[2]) #overwrites original # transform origin to corner if mode==0: if npoints_x>1: xyz1 = cpv.sub(xyz1, cpv.scale(xyz2,length_x/2)) if npoints_z>1: xyz1 = cpv.sub(xyz1, cpv.scale(xyz3,length_z/2)) #defines array lines nlines=max([npoints_x, npoints_z]) # in case only one line max # create an empty array for xyz entries # this may contain more values than are actually drawn later, # but they are needed to draw lines in each direction grid_xyz = [] for x in range(0,nlines): grid_xyz.append([0.0,0.0,0.0]*nlines) # grid distance and steps # prevent zero divisions (lines=1) and enable calculations if lines=0 if (not (npoints_x-1<2)): gap_length_x = length_x/(npoints_x-1) step_line_x = 2*math.pi/(npoints_x-1) else: gap_length_x=length_x step_line_x=2*math.pi if (not (npoints_z-1<2)): gap_length_z = length_z/(npoints_z-1) step_line_z = 2*math.pi/(npoints_z-1) else: gap_length_z=length_z step_line_z=2*math.pi # calculate steps if nstates==1: step_state=0 else: step_state = 2*math.pi/(nstates-1) ########## BEGIN STATE ITERATION ########## # create a n-state object in PyMol for a in range(0,nstates): # Reset object obj = [] #assign color obj.extend( [ COLOR, color[0], color[1], color[2] ] ) #set width obj.extend( [ LINEWIDTH, thickness ] ) # Calculate xyz-coordinates for each line for x in range(0,nlines): for z in range(0,nlines): # update grid position in x-direction xyztemp=cpv.add(xyz1,cpv.scale(xyz2,gap_length_x*x)) # update grid position in z-direction xyztemp=cpv.add(xyztemp,cpv.scale(xyz3,gap_length_z*z)) # calculate amplitude for y-direction and update grid position y_amp=(\ gain_x*math.sin(offset_x+nwaves_x*((a*step_state)+(x*step_line_x)))/2+\ gain_z*math.sin(offset_z+nwaves_z*((a*step_state)+(z*step_line_z)))/2\ ) xyztemp=cpv.add(xyztemp,cpv.scale(xyz4,y_amp)) grid_xyz[x][z]=xyztemp #Now the coordinates for this state are defined! #Now the coordinates are read separately: # allow to run the loops as often as required #if npoints_x==0:npoints_x=npoints_z #lines along z in x direction for z in range(0,npoints_z): obj.extend( [ BEGIN, LINE_STRIP ] ) for x in range(0,npoints_x): obj.extend( [ VERTEX, grid_xyz[x][z][0], grid_xyz[x][z][1], grid_xyz[x][z][2] ] ) obj.append( END ) #lines along x in z direction for x in range(0,npoints_x): obj.extend( [ BEGIN, LINE_STRIP ] ) for z in range(0,npoints_z): obj.extend( [ VERTEX, grid_xyz[x][z][0], grid_xyz[x][z][1], grid_xyz[x][z][2] ] ) obj.append( END ) # Load state into PyMOL object: cmd.load_cgo(obj,name,a+1) # All states of object loaded! #reset auto zooming to previous value cmd.set('auto_zoom', temp_auto_zoom) # animate object using frames instead of states if (not endframe==startframe): framecount=0 countvar=1 for frame in range(startframe, endframe + 1): #increase count framecount=framecount+countvar # set state in frame cmd.mappend(frame, "/cmd.set('state', %s, %s)" % (repr(framecount), repr(name))) # Looping if framecount==nstates: if ((int(nwaves_x)!=nwaves_x) or (int(nwaves_z)!=nwaves_z)): #if not complete sinus wave #--> reverse wave in ongoing animation countvar=-1 else: #wave is complete --> repeat framecount=0 # count up from first state if framecount==1: countvar=1 if not quiet: print("object loaded and animated with frames!") else: if not quiet: print("object loaded!") #OUTPUT if not quiet: print("Grid variables for:",name) print("corner:", xyz1) print("vector 1:", xyz2) print("vector 2:", xyz3) print("length_x:",length_x) print("length_z:",length_z) print("npoints_x:", npoints_x) print("npoints_z:", npoints_z) print("nwaves_x:", nwaves_x) print("nwaves_z:", nwaves_z) print("offset_x:",offset_x) print("offset_z:",offset_z) print("gain_x:",gain_x) print("gain_z:",gain_z) print("thickness:",thickness) print("states", nstates) if (not endframe==startframe): print("frames: start:",startframe,"end:",endframe) return grid_xyz