|
|
(24 intermediate revisions by 3 users not shown) |
Line 1: |
Line 1: |
| SuperSym is a PyMOL plugin providing a large number of tools for visualization of space groups; unit cells; and symmetry axes, operators, and partners. Source code for version 1.0 is below.
| | {{Infobox script-repo |
| | |type = plugin |
| | |filename = plugins/SuperSymPlugin.py |
| | |author = [[User:Srballard|Stuart Ballard]] |
| | |license = |
| | }} |
|
| |
|
| ==Dependencies and Acknowledgments==
| | [[File:SuperSymExample.png|300px|thumb|right|Symmetry partners for 1hpv showing 6-1 screw axis]] |
| | [[File:SuperSymExample2.png|300px|thumb|right|Full cell of symmetry partners with symmetry axes displayed]] |
| | SuperSym is a PyMOL plugin providing a large number of tools for visualization of space groups; unit cells; and symmetry axes, operators, and partners. |
|
| |
|
| Pre-v1.0 PyMOL may not display objects created by this plugin properly. Use at your own risk.
| | The original source code is available from https://sourceforge.net/projects/supersym/ |
|
| |
|
| This plugin requires cctbx and numeric python.
| | == Dependencies == |
|
| |
|
| Code for unit cell and symmetry axis building is borrowed from scripts created by Robert Campbell, available at [http://pldserver1.biochem.queensu.ca/~rlc/work/pymol/ http://pldserver1.biochem.queensu.ca/~rlc/work/pymol/]. This code has been modified for use in SuperSym.
| | * [[CCTBX|cctbx]] |
| | * numpy |
|
| |
|
| [[FindSurfaceResidues]] is utilized for some of SuperSym's graphics generation, with some modifications. | | '''PyMOL, cctbx and numpy must all be compiled with the same Python distribution!''' |
| | See [[CCTBX]]. |
|
| |
|
| ==Using SuperSym==
| | This plugin was developed in 2010 for PyMOL version 1.2r1 and has not been updated since. |
|
| |
|
| To use SuperSym, copy the text of source files to corresponding .py files. Place SuperSymMenu.py in pymol/modules/pmg_tk/startup, and all other files in pymol/modules.
| | == Bugs == |
|
| |
|
| To use functions of SuperSym directly, without creating a drop-down menu in the PyMOL GUI, ignore SuperSymMenu.py and run the other files in PyMOL as you would for any other script.
| | Symmetry axes are not defined for all space groups, and do not display properly for some. |
|
| |
|
| ==Source Files== | | == Acknowledgments == |
|
| |
|
| File: SuperSym.py
| | Primary coding and development was done by Stuart Ballard. All comments, questions, and issues should be directed to him at srballard@wisc.edu. |
| <source lang="python">
| |
| from Tkinter import *
| |
| import tkSimpleDialog
| |
| import tkMessageBox
| |
| import tkColorChooser
| |
| import sys
| |
| from pymol import stored, cmd, selector
| |
| import math
| |
| from cctbx import sgtbx, uctbx
| |
| import numpy as N
| |
| from numpy.linalg import *
| |
| import draw_cell as draw_cell
| |
| import draw_symops_cctbx as sym_axes
| |
|
| |
|
| '''
| | Code for unit cell and symmetry axis building is borrowed from scripts created by Robert Campbell and Ralf W. Grosse-Kunstleve, available at [http://pldserver1.biochem.queensu.ca/~rlc/work/pymol/ http://pldserver1.biochem.queensu.ca/~rlc/work/pymol/]. Some of this code has been modified for use in SuperSym. |
| symDialog: Dialog generator and command issuer for generating symmetry partners
| |
|
| |
|
| This function is called by SuperSymMenu when any symmetry partner generating option is
| | [[FindSurfaceResidues]] is utilized for some of SuperSym's graphics generation, with some modifications. |
| selected. It creates dialog windows and receives user input for symmetry generation parameters.
| |
| | |
| @app -- identifies the GUI interface to build dialog boxes onto.
| |
| @mode -- determines specific treatment of symmetry building command
| |
| '''
| |
| def symDialog(app, mode):
| |
| prefix = tkSimpleDialog.askstring('Prefix',
| |
| 'Enter desired prefix for these partners:', parent=app.root)
| |
| object = tkSimpleDialog.askstring('Object',
| |
| 'Enter object to generate partners from:', parent=app.root)
| |
| if (mode == 0): #make default symmetry set in cell [0,0,0]
| |
| symset(prefix, object)
| |
| if (mode == 1): #make symmetry set in custom cell
| |
| cell = tkSimpleDialog.askstring('Cell',
| |
| 'Enter lattice cell coordinates separated by commas (ex:x,y,z):', parent = app.root)
| |
| x,y,z = cell.split(',')
| |
| x,y,z = int(x),int(y),int(z)
| |
| symset(prefix, object, x, y, z)
| |
| if mode == 2: #make 2x2x2 block of symmetry sets
| |
| for i in range(2):
| |
| for j in range(2):
| |
| for k in range(2):
| |
| symset(prefix, object, i, j, k)
| |
| if mode == 3: #make 3x3x3 block of symmetry sets
| |
| for i in range(-1,2):
| |
| for j in range(-1,2):
| |
| for k in range(-1,2):
| |
| symset(prefix, object, i, j, k)
| |
| if mode == 4: #select individual partners by operation and cell
| |
| ops = get_operations(object)
| |
| opString = ""
| |
| for i in range(len(ops)):
| |
| opString = opString + str(i) + " : " + ops[i] + "\n"
| |
| opIndeces = tkSimpleDialog.askstring("Symmetry Operations", opString +
| |
| "Enter numbers of desired operations separated by commas (ex:0,2,9)", parent = app.root)
| |
| opListStrings = opIndeces.split(",")
| |
| opList = []
| |
| for op in opListStrings:
| |
| opList.append(int(op))
| |
| cell = tkSimpleDialog.askstring('Cell',
| |
| 'Enter lattice cell coordinates separated by commas (ex:x,y,z):', parent = app.root)
| |
| x,y,z = cell.split(',')
| |
| x,y,z = int(x),int(y),int(z)
| |
| symset(prefix, object, x,y,z, opList)
| |
| | |
| '''
| |
| colorDialog: Dialog generator for coloring commands
| |
| | |
| This function colors sets of symmetry partners defined by the user in the
| |
| dialog which it generates.
| |
| | |
| @app -- identifies root menu calling this function
| |
| @mode -- determines coloring scheme to execute
| |
| '''
| |
| def colorDialog(app, mode):
| |
| prefix = tkSimpleDialog.askstring('Prefix',
| |
| 'Enter the prefix of symmetry partners to color', parent = app.root)
| |
| if mode == 0: #standard rainbow by symmetry operation
| |
| colors = ["red", "orange", "yellow", "green", "blue", "purple",
| |
| "salmon", "grey", "pink", "teal", "brown", "br0", "aquamarine",
| |
| "deepolive", "dirtyviolet", "slate", "br4", "darksalmon", "br7",
| |
| "chocolate", "firebrick", "brightorange"]
| |
| for i in range(10):
| |
| try: #required because PyMOL inappropriately throws an exception
| |
| #when the cmd.color() function colors no objects
| |
| cmd.color(colors[i], prefix + "0" + str(i) + "*")
| |
| except:
| |
| pass #allows us to move on to next symmetry operator
| |
| for i in range(10,20):
| |
| try: #required because PyMOL inappropriately throws an exception
| |
| #when the cmd.color() function colors no objects
| |
| cmd.color(colors[i], prefix + str(i) + "*")
| |
| except:
| |
| pass #allows us to move on to next symmetry operator
| |
| if mode == 1: #specify for each symmetry operation
| |
| cmd.iterate_state(1, prefix + "*", "stored.tmpObject = model")
| |
| ops = get_operations(stored.tmpObject)
| |
| opString = ""
| |
| for i in range(len(ops)):
| |
| opString = opString + str(i) + " : " + ops[i] + "\n"
| |
| opIndeces = tkSimpleDialog.askstring("Symmetry Operations", opString +
| |
| "Enter numbers of desired operations separated by commas (ex:0,2,9) or all", parent = app.root)
| |
| if opIndeces == "all":
| |
| opList = []
| |
| for i in range(len(ops)):
| |
| opList.append(i)
| |
| else:
| |
| opList = opIndeces.split(",")
| |
| opStringList = opString.split("\n")
| |
| for i in opList:
| |
| tempColor = tkColorChooser.askcolor(title = "Color for " + opStringList[int(i)], parent = app.root)[0]
| |
| rgb = []
| |
| for value in tempColor:
| |
| value = float(value)
| |
| value = value/255
| |
| rgb.append(value)
| |
| cmd.set_color("tempColor", rgb)
| |
| try:
| |
| if int(i) < 10:
| |
| cmd.color("tempColor", prefix + "0" + str(i) + "*")
| |
| if int(i) > 9:
| |
| cmd.color("tempColor", prefix + str(i) + "*")
| |
| except:
| |
| pass
| |
| if mode == 2: #monochrome for a set of operations
| |
| cmd.iterate_state(1, prefix + "*", "stored.tmpObject = model")
| |
| ops = get_operations(stored.tmpObject)
| |
| opString = ""
| |
| for i in range(len(ops)):
| |
| opString = opString + str(i) + " : " + ops[i] + "\n"
| |
| opIndeces = tkSimpleDialog.askstring("Symmetry Operations", opString +
| |
| "Enter numbers of desired operations separated by commas (ex:0,2,9) or all", parent = app.root)
| |
| if opIndeces == 'all':
| |
| opList = []
| |
| for i in range(len(ops)):
| |
| opList.append(i)
| |
| else:
| |
| opList = opIndeces.split(",")
| |
| opStringList = opString.split("\n")
| |
| tempColor = tkColorChooser.askcolor(parent = app.root)[0]
| |
| rgb = []
| |
| for value in tempColor:
| |
| value = float(value)
| |
| value = value/255
| |
| rgb.append(value)
| |
| cmd.set_color("tempColor", rgb)
| |
| for i in opList:
| |
| try:
| |
| if int(i) < 10:
| |
| cmd.color("tempColor", prefix + "0" + str(i) + "*")
| |
| if int(i) > 9:
| |
| cmd.color("tempColor", prefix + str(i) + "*")
| |
| except:
| |
| pass
| |
| '''
| |
| graphicsDialog: Dialog generator for graphics commands
| |
| | |
| This function sets visual representations for sets of symmetry partners.
| |
| | |
| @app -- identifies root menu
| |
| @mode -- determines type of representation to show
| |
| '''
| |
| def graphicsDialog(app, mode):
| |
| prefix = tkSimpleDialog.askstring('Prefix',
| |
| 'Enter prefix of symmetry partners to display', parent = app.root)
| |
| cmd.hide("everything", prefix + "*")
| |
| if mode == 0: # show lines
| |
| cmd.show("lines", prefix + "*")
| |
| if mode == 1: # show ribbon
| |
| cmd.show("ribbon", prefix + "*")
| |
| if mode == 2: # sphere surface
| |
| objSel = prefix + "*"
| |
| findSurfaceResidues(objSel, 3.5, "surface")
| |
| cmd.set("sphere_scale", 1.8)
| |
| cmd.show("spheres", "surface")
| |
| if mode == 3: # regular surface
| |
| cmd.show("surface", prefix + "*")
| |
| | |
| '''
| |
| cellDialog: dialog proxy for draw_cell
| |
| | |
| This function generates a unit cell representation
| |
| FUTURE IMPLEMENTATIONS: select which lattice coordinates to generate unit cell for
| |
| | |
| @app -- identifies root menu
| |
| '''
| |
| def cellDialog(app):
| |
| object = tkSimpleDialog.askstring('Object',
| |
| 'Enter object to generate cell for:', parent = app.root)
| |
| if tkMessageBox.askyesno('3D Printing', 'Going to print this model?', parent = app.root):
| |
| draw_cell.draw_cell(object, 3.0)
| |
| else:
| |
| draw_cell.draw_cell(object)
| |
| | |
| '''
| |
| axesDialog: dialog proxy for draw_symops_cctbx
| |
| | |
| This function generates one set of symmetry axes for a given object
| |
| FUTURE IMPLEMENTATIONS: select individual axes to generate, attach to model for 3D printing,
| |
| generate axes for multiple unit cells
| |
| | |
| @app -- identifies root menu
| |
| '''
| |
| def axesDialog(app):
| |
| object = tkSimpleDialog.askstring('Object',
| |
| 'Enter object to generate symmetry axes for:', parent = app.root)
| |
| if tkMessageBox.askyesno('3D Printing', 'Going to print this model?', parent = app.root):
| |
| sym_axes.draw_symops(object, 2.0)
| |
| else:
| |
| sym_axes.draw_symops(object)
| |
| | |
| '''
| |
| cellShiftInfo: displays info for using cell_shift hotkeys
| |
| | |
| @app -- identifies root menu
| |
| '''
| |
| def cellShiftInfo(app):
| |
| tkMessageBox.showinfo('Cell Shifting',
| |
| "To shift a symmetry partner, simply click to select any part of it (select only one partner at a time). \n\n" +
| |
| "Next, hold ALT and press the numpad key corresponding to the axis direction you\'d like to move. \n\n" +
| |
| "Key assignments:\n" +
| |
| "A (x) axis: down--4, up--6 \n" +
| |
| "B (y) axis: down--2, up--8 \n" +
| |
| "C (z) axis: down--1, up--5", parent = app.root)
| |
| tkMessageBox.showwarning('Caution', 'Only attempt to shift symmetry partners created by SuperSym.'+
| |
| 'Attempting to shift any other object will result in errors.')
| |
| | |
| def aboutInfo(app):
| |
| tkMessageBox.showinfo('About',
| |
| 'SuperSym v1.0\nDeveloped by Stuart Ballard (srballard@wisc.edu)\nDepartment of Biochemistry\n'+
| |
| 'University of Wisconsin-Madison', parent = app.root)
| |
| def helpInfo(app):
| |
| tkMessageBox.showinfo('Help',
| |
| 'For documentation see http://pymolwiki.org/index.php/SuperSym', parent = app.root)
| |
| | |
| '''
| |
| symset: generates up to one full set of symmetry partners for a given object in a given lattice position
| |
| | |
| 1. Obtain all essential symmetry information from CCTBX. This includes the space group, unit cell parameters,
| |
| and fractional coordinates corresponding to symmetry operations.
| |
| 2. Generate transformation matrices to translate coordinates from orthogonal to fractional, and back.
| |
| 3.
| |
| '''
| |
| def symset(prefix = "sym", object = -1, x=0,y=0,z=0, opList = []):
| |
| if object == -1:
| |
| object = cmd.get_names()[0]
| |
| cell = [float(x),float(y),float(z)]
| |
| view = cmd.get_view()
| |
| cmd.show("lines", object)
| |
| sgInfo = cmd.get_symmetry(object)
| |
| raw_ops = []
| |
| for s in sgtbx.space_group_info(sgInfo[6]).group():
| |
| raw_ops.append(str(s))
| |
| if (len(opList) == 0):
| |
| for i in range(len(raw_ops)):
| |
| opList.append(i)
| |
| a,b,c,alpha,beta,gamma = sgInfo[0:6]
| |
| ca = math.cos(math.radians(alpha))
| |
| cb = math.cos(math.radians(beta))
| |
| cg = math.cos(math.radians(gamma))
| |
| sb = math.sin(math.radians(beta))
| |
| sg = math.sin(math.radians(gamma))
| |
| stored.fracToOrt = N.array([[a, b * cg, c * cb],
| |
| [0.0, b * sg, c * (ca - cb * cg) / sg],
| |
| [0.0, 0.0, c * sb * math.sqrt(1.0 - ((cb * cg - ca) / (sb * sg))**2)]])
| |
| stored.fracToOrt = stored.fracToOrt.transpose()
| |
| stored.ortToFrac = inv(stored.fracToOrt)
| |
| for i in opList:
| |
| try:
| |
| stored.tmpOp = raw_ops[i]
| |
| except:
| |
| print "Bad symmetry partner numbers. Try again."
| |
| quit()
| |
| if i > 9:
| |
| copy = prefix + str(i) + "_" + str(x) + "_" + str(y) + "_" + str(z)
| |
| else:
| |
| copy = prefix + "0" + str(i) + "_" + str(x) + "_" + str(y) + "_" + str(z)
| |
| cmd.copy(copy, object)
| |
| #COPIES COORDINATES OF EACH ATOM TO CORRESPONDING ONE IN GIVEN SYMMETRY PARTNER
| |
| cmd.alter_state(1, copy, "x,y,z = cmd.sym_partner([x,y,z], stored.tmpOp)")
| |
| #MOVES SYMMETRY PARTNER TO PROPER LATTICE COORDINATES AND CORRECTS FOR NATIVE LATTICE POSITION ERROR
| |
| stored.xSum,stored.ySum,stored.zSum = 0.0,0.0,0.0
| |
| atoms = cmd.count_atoms(copy)
| |
| cmd.iterate_state(1, copy, "stored.xSum = stored.xSum + x; stored.ySum = stored.ySum + y; stored.zSum = stored.zSum + z")
| |
| xMean = (stored.xSum / atoms)
| |
| yMean = (stored.ySum / atoms)
| |
| zMean = (stored.zSum / atoms)
| |
| xError, yError, zError = N.dot(N.array([xMean,yMean,zMean]), stored.ortToFrac)
| |
| dX,dY,dZ = -math.floor(xError) + cell[0], -math.floor(yError) + cell[1], -math.floor(zError) + cell[2]
| |
| cell_shift(copy,dX,dY,dZ, 0)
| |
| cmd.hide("everything", object)
| |
| cmd.set_view(view)
| |
| | |
| def sym_partner(coords, op):
| |
| fracCoords = N.dot(N.array(coords), stored.ortToFrac)
| |
| op = op.replace("x", "(" + str(fracCoords[0]) + ")")
| |
| op = op.replace("y", "(" + str(fracCoords[1]) + ")")
| |
| op = op.replace("z", "(" + str(fracCoords[2]) + ")")
| |
| op = op.split(",")
| |
| for i in range(3):
| |
| index = op[i].find("/")
| |
| if index != -1:
| |
| if len(op[i]) == index + 2:
| |
| op[i] = op[i][0:index - 1] + str(float(op[i][index - 1]) / float(op[i][index + 1]))
| |
| else:
| |
| op[i] = op[i][0:index - 1] + str(float(op[i][index - 1]) / float(op[i][index + 1])) + op[i][index + 2:]
| |
| op[i] = eval(op[i])
| |
| return N.dot(N.array(op), stored.fracToOrt)
| |
| | |
| def cell_shift_proxyX1():
| |
| cmd.iterate_state(1, "sele", "stored.tmpObject = model")
| |
| cell_shift(stored.tmpObject, 1,0,0)
| |
| def cell_shift_proxyX2():
| |
| cmd.iterate_state(1, "sele", "stored.tmpObject = model")
| |
| cell_shift(stored.tmpObject, -1,0,0)
| |
| def cell_shift_proxyY1():
| |
| cmd.iterate_state(1, "sele", "stored.tmpObject = model")
| |
| cell_shift(stored.tmpObject, 0,1,0)
| |
| def cell_shift_proxyY2():
| |
| cmd.iterate_state(1, "sele", "stored.tmpObject = model")
| |
| cell_shift(stored.tmpObject, 0,-1,0)
| |
| def cell_shift_proxyZ1():
| |
| cmd.iterate_state(1, "sele", "stored.tmpObject = model")
| |
| cell_shift(stored.tmpObject, 0,0,1)
| |
| def cell_shift_proxyZ2():
| |
| cmd.iterate_state(1, "sele", "stored.tmpObject = model")
| |
| cell_shift(stored.tmpObject, 0,0,-1)
| |
| | |
| def cell_shift(object, dX, dY, dZ, rename = 1):
| |
| if rename:
| |
| oldName = object.split("_")
| |
| oldPre = oldName[0]
| |
| oldX = int(oldName[1])
| |
| oldY = int(oldName[2])
| |
| oldZ = int(oldName[3])
| |
| newX = "_" + str(int(dX) + oldX)
| |
| newY = "_" + str(int(dY) + oldY)
| |
| newZ = "_" + str(int(dZ) + oldZ)
| |
| newName = oldPre + newX + newY + newZ
| |
| #if cmd.get_names().find(newName) != -1:
| |
| # print "Symmetry partner already exists in destination position!"
| |
| # quit()
| |
| cmd.set_name(object, newName)
| |
| object = newName
| |
| stored.shift = [float(dX),float(dY),float(dZ)]
| |
| stored.sgInfo = cmd.get_symmetry(object)
| |
| a,b,c,alpha,beta,gamma = stored.sgInfo[0:6]
| |
| ca = math.cos(math.radians(alpha))
| |
| cb = math.cos(math.radians(beta))
| |
| cg = math.cos(math.radians(gamma))
| |
| sb = math.sin(math.radians(beta))
| |
| sg = math.sin(math.radians(gamma))
| |
| stored.fracToOrt = N.array([[a, b * cg, c * cb],
| |
| [0.0, b * sg, c * (ca - cb * cg) / sg],
| |
| [0.0, 0.0, c * sb * math.sqrt(1.0 - ((cb * cg - ca) / (sb * sg))**2)]])
| |
| stored.fracToOrt = stored.fracToOrt.transpose()
| |
| stored.ortToFrac = inv(stored.fracToOrt)
| |
| cmd.alter_state(1, object, "x,y,z = cmd.cell_shift_helper([x,y,z],stored.shift)")
| |
|
| |
| | |
| def shift_and_copy(object, dX, dY, dZ):
| |
| oldName = object.split("_")
| |
| oldPre = oldName[0]
| |
| oldX = int(oldName[1])
| |
| oldY = int(oldName[2])
| |
| oldZ = int(oldName[3])
| |
| newX = "_" + str(int(dX) + oldX)
| |
| newY = "_" + str(int(dY) + oldY)
| |
| newZ = "_" + str(int(dZ) + oldZ)
| |
| copy = oldPre + newX + newY + newZ
| |
| if cmd.count_atoms(copy) != 0:
| |
| print "Symmetry partner already exists in destination position!"
| |
| quit()
| |
| cmd.copy(newName, object)
| |
| stored.shift = [float(dX),float(dY),float(dZ)]
| |
| stored.sgInfo = cmd.get_symmetry(object)
| |
| a,b,c,alpha,beta,gamma = stored.sgInfo[0:6]
| |
| ca = math.cos(math.radians(alpha))
| |
| cb = math.cos(math.radians(beta))
| |
| cg = math.cos(math.radians(gamma))
| |
| sb = math.sin(math.radians(beta))
| |
| sg = math.sin(math.radians(gamma))
| |
| stored.fracToOrt = N.array([[a, b * cg, c * cb],
| |
| [0.0, b * sg, c * (ca - cb * cg) / sg],
| |
| [0.0, 0.0, c * sb * math.sqrt(1.0 - ((cb * cg - ca) / (sb * sg))**2)]])
| |
| stored.fracToOrt = stored.fracToOrt.transpose()
| |
| stored.ortToFrac = inv(stored.fracToOrt)
| |
| cmd.alter_state(1, newName, "x,y,z = cell_shift_helper([x,y,z],stored.shift)")
| |
| | |
| | |
| def cell_shift_helper(coords, shift):
| |
| fracCoords = N.dot(N.array(coords), stored.ortToFrac)
| |
| for i in range(3):
| |
| fracCoords[i] = fracCoords[i] + shift[i]
| |
| coords = N.dot(N.array(fracCoords), stored.fracToOrt)
| |
| return coords[0], coords[1], coords[2]
| |
| | |
| def get_operations(object):
| |
| raw_ops = []
| |
| sgInfo = cmd.get_symmetry(object)
| |
| for s in sgtbx.space_group_info(sgInfo[6]).group():
| |
| raw_ops.append(str(s))
| |
| return raw_ops
| |
| | |
| def get_orthogonalization_matrix(object, quiet = 0):
| |
| a,b,c,alpha,beta,gamma = cmd.get_symmetry(object)[0:6]
| |
| ca = math.cos(math.radians(alpha))
| |
| cb = math.cos(math.radians(beta))
| |
| cg = math.cos(math.radians(gamma))
| |
| sb = math.sin(math.radians(beta))
| |
| sg = math.sin(math.radians(gamma))
| |
| fracToOrt = N.array([[a, b * cg, c * cb],
| |
| [0.0, b * sg, c * (ca - cb * cg) / sg],
| |
| [0.0, 0.0, c * sb * math.sqrt(1.0 - ((cb * cg - ca) / (sb * sg))**2)]])
| |
| if not quiet:
| |
| print fracToOrt
| |
| print inv(fracToOrt)
| |
| return fracToOrt
| |
| | |
| # -*- coding: utf-8 -*-
| |
| # this function is borrowed from findSurfaceResidues script on PyMOL wiki
| |
| def findSurfaceResidues(objSel="(all)", cutoff=2.5, selName = 0):
| |
| """
| |
| findSurfaceResidues
| |
| finds those residues on the surface of a protein
| |
| that have at least 'cutoff' exposed A**2 surface area.
| |
|
| |
| PARAMS
| |
| objSel (string)
| |
| the object or selection in which to find
| |
| exposed residues
| |
| DEFAULT: (all)
| |
|
| |
| cutoff (float)
| |
| your cutoff of what is exposed or not.
| |
| DEFAULT: 2.5 Ang**2
| |
|
| |
| asSel (boolean)
| |
| make a selection out of the residues found
| |
|
| |
| RETURNS
| |
| (list: (chain, resv ) )
| |
| A Python list of residue numbers corresponding
| |
| to those residues w/more exposure than the cutoff.
| |
|
| |
| """
| |
| tmpObj="__tmp"
| |
| cmd.create( tmpObj, objSel + " and polymer");
| |
| cmd.set("dot_solvent");
| |
| cmd.get_area(selection=tmpObj, load_b=1)
| |
|
| |
| # threshold on what one considers an "exposed" atom (in A**2):
| |
| cmd.remove( tmpObj + " and b < " + str(cutoff) )
| |
|
| |
| stored.tmp_dict = {}
| |
| cmd.iterate(tmpObj, "stored.tmp_dict[(chain,resv)]=1")
| |
| exposed = stored.tmp_dict.keys()
| |
| exposed.sort()
| |
|
| |
| cmd.select(selName, objSel + " in " + tmpObj )
| |
| cmd.delete(tmpObj)
| |
|
| |
| return exposed
| |
| </source>
| |
| File: SuperSymMenu.py
| |
| <source lang="python">
| |
| from Tkinter import *
| |
| import tkFileDialog
| |
| from pymol import cmd, selector
| |
| from SuperSym import *
| |
| | |
| def __init__(self):
| |
| #MAIN
| |
| self.menuBar.addmenu('SuperSym','SuperSym')
| |
| #DEFAULT SET BUILD
| |
| self.menuBar.addmenuitem('SuperSym', 'command', 'Default Symmetry Partner Set',
| |
| label = 'Default Symmetry Partner Set',
| |
| command = lambda s = self: symDialog(s, 0))
| |
| #UNIT CELL BUILD
| |
| self.menuBar.addmenuitem('SuperSym', 'command', 'Draw Unit Cell',
| |
| label = 'Draw Unit Cell',
| |
| command = lambda s = self: cellDialog(s))
| |
| #SYM SUBMENU
| |
| self.menuBar.addcascademenu('SuperSym', 'Build Symmetry Partners')
| |
| | |
| self.menuBar.addmenuitem('Build Symmetry Partners', 'command', 'Cell [0,0,0] (default)',
| |
| label = 'Cell [0,0,0] (default)',
| |
| command = lambda s = self: symDialog(s, 0))
| |
| | |
| self.menuBar.addmenuitem('Build Symmetry Partners', 'command', 'Cell [x,y,z] (custom)',
| |
| label = 'Cell [x,y,z] (custom)',
| |
| command = lambda s = self: symDialog(s, 1))
| |
| | |
| self.menuBar.addmenuitem('Build Symmetry Partners', 'command', '2x2x2 Block',
| |
| label = '2x2x2 Block',
| |
| command = lambda s = self: symDialog(s, 2))
| |
| | |
| self.menuBar.addmenuitem('Build Symmetry Partners', 'command', '3x3x3 Block',
| |
| label = '3x3x3 Block',
| |
| command = lambda s = self: symDialog(s, 3))
| |
| | |
| self.menuBar.addmenuitem('Build Symmetry Partners', 'command', 'By Partner',
| |
| label = 'By Partner',
| |
| command = lambda s = self: symDialog(s, 4))
| |
| #COLOR SUBMENU
| |
| self.menuBar.addcascademenu('SuperSym', 'Coloring')
| |
| | |
| self.menuBar.addmenuitem('Coloring', 'command', 'Default Rainbow',
| |
| label = 'Default Rainbow',
| |
| command = lambda s = self: colorDialog(s, 0))
| |
| | |
| self.menuBar.addmenuitem('Coloring', 'command', 'Select color for each operation',
| |
| label = 'Select color for each operation',
| |
| command = lambda s = self: colorDialog(s, 1))
| |
| | |
| self.menuBar.addmenuitem('Coloring', 'command', 'Select one color for custom set of operations',
| |
| label = 'Select one color for custom set of operations',
| |
| command = lambda s = self: colorDialog(s, 2))
| |
| #GRAPHICS SUBMENU
| |
| self.menuBar.addcascademenu('SuperSym', 'Graphics')
| |
| | |
| self.menuBar.addmenuitem('Graphics', 'command', 'Lines',
| |
| label = 'Lines',
| |
| command = lambda s = self: graphicsDialog(s, 0))
| |
| | |
| self.menuBar.addmenuitem('Graphics', 'command', 'Ribbon',
| |
| label = 'Ribbon',
| |
| command = lambda s = self: graphicsDialog(s, 1))
| |
| | |
| self.menuBar.addmenuitem('Graphics', 'command', 'Sphere Surface (best for printing)',
| |
| label = 'Sphere Surface (best for printing)',
| |
| command = lambda s = self: graphicsDialog(s, 2))
| |
| | |
| self.menuBar.addmenuitem('Graphics', 'command', 'Surface (high load render)',
| |
| label = 'Surface (high load render)',
| |
| command = lambda s = self: graphicsDialog(s, 3))
| |
| #SYM AXES SUBMENU
| |
| self.menuBar.addcascademenu('SuperSym', 'Symmetry Axes')
| |
| | |
| self.menuBar.addmenuitem('Symmetry Axes', 'command', 'Build Axes',
| |
| label = 'Build Axes',
| |
| command = lambda s = self: axesDialog(s))
| |
| #ADD OTHER SYMMETRY AXES OPTION HERE
| |
| self.menuBar.addmenuitem('SuperSym', 'command', 'Move symmetry partners',
| |
| label = 'Move symmetry partners',
| |
| command = lambda s = self: cellShiftInfo(s))
| |
| self.menuBar.addmenuitem('SuperSym', 'command', 'About',
| |
| label = 'About',
| |
| command = lambda s = self: aboutInfo(s))
| |
| self.menuBar.addmenuitem('SuperSym', 'command', 'Help',
| |
| label = 'Help',
| |
| command = lambda s = self: helpInfo(s))
| |
| cmd.cell_shift = cell_shift
| |
| cmd.get_operations = get_operations
| |
| cmd.get_matrix = get_orthogonalization_matrix
| |
| cmd.symset = symset
| |
| cmd.sym_partner = sym_partner
| |
| cmd.cell_shift_helper = cell_shift_helper
| |
| cmd.set_key("ALT-6", cell_shift_proxyX1)
| |
| cmd.set_key("ALT-4", cell_shift_proxyX2)
| |
| cmd.set_key("ALT-8", cell_shift_proxyY1)
| |
| cmd.set_key("ALT-2", cell_shift_proxyY2)
| |
| cmd.set_key("ALT-5", cell_shift_proxyZ1)
| |
| cmd.set_key("ALT-1", cell_shift_proxyZ2)
| |
| </source>
| |
| File: draw_cell.py
| |
| <source lang="python">
| |
| #original code written by Robert Campbell
| |
| #modified by Stuart Ballard
| |
| from cctbx import uctbx, sgtbx
| |
| from pymol.cgo import *
| |
| from pymol import cmd
| |
| from pymol.vfont import plain
| |
| | |
| def set_to_zero(a):
| |
| if abs(a) < 1e-10:
| |
| a=0
| |
| return a
| |
| | |
| def draw_cell(obj,radius=1.0,mode=0):
| |
| """
| |
| From pymol issue the "run draw_cell.py" command to load the script,
| |
| then issue the "draw_cell(object,<optional radius>)" command
| |
| to actually run it and create the cgo object showing the unit cell
| |
| border for the space group specified by molecular object 'object'.
| |
| | |
| e.g. load 1avv.pdb
| |
| run draw_cell.py
| |
| draw_cell 1avv 0.5 (or draw_cell('1avv',.5))
| |
| | |
| see also help(draw_cell_param) to draw the cell border for
| |
| user-defined cell dimensions (i.e. not loaded from a pdb file)
| |
| | |
| See also "help(draw_cell_param) to draw the cell border by
| |
| specifying the unit cell parameters directly (i.e. not loaded from
| |
| a pdb file).
| |
| """
| |
| radius=float(radius)
| |
| cell_info=cmd.get_symmetry(obj)
| |
| draw_cell_param(cell_info[0:6],radius,mode)
| |
| | |
| def draw_cell_param(cell_param_list,radius=1.0,mode=0):
| |
| """
| |
| If you wish to draw the unit cell border for any cell without the
| |
| need to load a pdb file, then do this:
| |
| | |
| e.g. run draw_cell.py
| |
| draw_cell_param((45.2,45.2,70.8,90.,90.,120.),0.5)
| |
| | |
| to generate the cell border for this trigonal space group "p 31 2 1"
| |
| with a radius of 0.5A. Labels for the origin, and A, B and C axes
| |
| will appear as well. The perimeter of the cell is colored with the
| |
| RGB components corresponding to the A,B,C components.
| |
| """
| |
|
| |
| U=uctbx.unit_cell((cell_param_list))
| |
| | |
| vert_000 = map(set_to_zero,U.orthogonalize((0.,0.,0)))
| |
| vert_100 = map(set_to_zero,U.orthogonalize((1.,0.,0)))
| |
| vert_010 = map(set_to_zero,U.orthogonalize((0.,1.,0)))
| |
| vert_001 = map(set_to_zero,U.orthogonalize((0.,0.,1)))
| |
| vert_110 = map(set_to_zero,U.orthogonalize((1.,1.,0)))
| |
| vert_011 = map(set_to_zero,U.orthogonalize((0.,1.,1)))
| |
| vert_101 = map(set_to_zero,U.orthogonalize((1.,0.,1)))
| |
| vert_111 = map(set_to_zero,U.orthogonalize((1.,1.,1)))
| |
| | |
| # vert_000 = map(None,U.orthogonalize((0.,0.,0)))
| |
| # vert_100 = map(None,U.orthogonalize((1.,0.,0)))
| |
| # vert_010 = map(None,U.orthogonalize((0.,1.,0)))
| |
| # vert_001 = map(None,U.orthogonalize((0.,0.,1)))
| |
| # vert_110 = map(None,U.orthogonalize((1.,1.,0)))
| |
| # vert_011 = map(None,U.orthogonalize((0.,1.,1)))
| |
| # vert_101 = map(None,U.orthogonalize((1.,0.,1)))
| |
| # vert_111 = map(None,U.orthogonalize((1.,1.,1)))
| |
| | |
| #print vert_000
| |
| | |
| #CYLINDER = ['CYLINDER']
| |
| #radius = [0.2]
| |
| #print radius
| |
| cell = []
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_000 + vert_100 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_000 + vert_010 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_000 + vert_001 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_100 + vert_110 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_100 + vert_101 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_010 + vert_110 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_010 + vert_011 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_001 + vert_101 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_001 + vert_011 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_110 + vert_111 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_101 + vert_111 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(CYLINDER)
| |
| cell = cell + vert_011 + vert_111 + [radius] + [1,1,1] + [1,1,1]
| |
| cell.append(SPHERE)
| |
| cell = cell + vert_000 + [radius]
| |
| cell.append(SPHERE)
| |
| cell = cell + vert_001 + [radius]
| |
| cell.append(SPHERE)
| |
| cell = cell + vert_010 + [radius]
| |
| cell.append(SPHERE)
| |
| cell = cell + vert_011 + [radius]
| |
| cell.append(SPHERE)
| |
| cell = cell + vert_100 + [radius]
| |
| cell.append(SPHERE)
| |
| cell = cell + vert_101 + [radius]
| |
| cell.append(SPHERE)
| |
| cell = cell + vert_110 + [radius]
| |
| cell.append(SPHERE)
| |
| cell = cell + vert_111 + [radius]
| |
| | |
| cmd.load_cgo(cell,"cell")
| |
| #return cell
| |
| | |
| if mode == 1:
| |
| text = [COLOR, 1.0, 0.0, 1.0,]
| |
| | |
| #wire_text(text,plain,[-5.,-5.,-1],'Origin',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])
| |
| #wire_text(text,plain,map(None,U.orthogonalize((1.05,0.0,0.0))),'A',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])
| |
| #wire_text(text,plain,map(None,U.orthogonalize((0.0,1.05,0.0))),'B',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])
| |
| #wire_text(text,plain,map(None,U.orthogonalize((0.0,0.0,1.05))),'C',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])
| |
| | |
| cyl_text(text,plain,[-5.,-5.,-1],'Origin',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[1.0,0.0,1.0])
| |
| cyl_text(text,plain,map(None,U.orthogonalize((1.05,0.0,0.0))),'A',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[1.0,0.0,0.0])
| |
| cyl_text(text,plain,map(None,U.orthogonalize((0.0,1.05,0.0))),'B',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[0.0,1.0,0.0])
| |
| cyl_text(text,plain,map(None,U.orthogonalize((0.0,0.0,1.05))),'C',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[0.0,0.0,1.0])
| |
| | |
| cmd.load_cgo(text,'text')
| |
| | |
| cmd.extend("draw_cell",draw_cell)
| |
| </source>
| |
| File: draw_symops_cctbx.py
| |
| <source lang="python">
| |
| #! /usr/bin/env python
| |
| # Copyright (c) 2004 Robert L. Campbell
| |
| | |
| from cctbx import uctbx, sgtbx
| |
| #import string, math
| |
| from pymol.cgo import *
| |
| from pymol import cmd
| |
| | |
| from all_axes_new import get_all_axes
| |
| | |
| import numpy as N
| |
| #import numarray as N
| |
| | |
| print "Finished importing for draw_symops_cctbx.py"
| |
| | |
| def set_to_zero(a):
| |
| if abs(a) < 1e-10:
| |
| a=0
| |
| return a
| |
| | |
| def draw_symbol(start,end,symb,color,radius=0.2):
| |
| degtorad = N.pi/180.
| |
| costhirty = N.cos(30.0*degtorad)
| |
| sinthirty = N.sin(30.0*degtorad)
| |
| symb_obj = []
| |
| | |
| if symb == '2' or symb == '2^1':
| |
| pass
| |
| | |
| elif symb == '3' or symb == '3^1' or symb == '3^2':
| |
| symb_obj = [ BEGIN, TRIANGLES, COLOR ] + color
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([start]) + N.array([radius, 0, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([start]) + N.array([-radius*sinthirty, radius*costhirty, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([start]) + N.array([-radius*sinthirty, -radius*costhirty, 0]))[0].tolist()
| |
| | |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([end]) + N.array([radius, 0, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([end]) + N.array([-radius*sinthirty, radius*costhirty, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([end]) + N.array([-radius*sinthirty, -radius*costhirty, 0]))[0].tolist()
| |
| symb_obj.append(END)
| |
| | |
| elif symb == '4' or symb == '4^1' or symb == '4^2' or symb == '4^3':
| |
| symb_obj = [ BEGIN, TRIANGLES, COLOR ] + color
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([start]) + N.array([radius, radius, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([start]) + N.array([-radius, radius, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([start]) + N.array([-radius, -radius, 0]))[0].tolist()
| |
| | |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([start]) + N.array([radius, radius, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([start]) + N.array([radius, -radius, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([start]) + N.array([-radius, -radius, 0]))[0].tolist()
| |
| | |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([end]) + N.array([radius, radius, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([end]) + N.array([-radius, radius, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([end]) + N.array([-radius, -radius, 0]))[0].tolist()
| |
| | |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([end]) + N.array([radius, radius, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([end]) + N.array([radius, -radius, 0]))[0].tolist()
| |
| symb_obj.append(VERTEX)
| |
| symb_obj = symb_obj + (N.array([end]) + N.array([-radius, -radius, 0]))[0].tolist()
| |
| symb_obj.append(END)
| |
| | |
| elif symb == '6' or symb == '6^1' or symb == '6^2' or symb == '6^3' or symb == '6^4' or symb == '6^5':
| |
| # hexagons still need to be created :)
| |
| pass
| |
| | |
| return symb_obj
| |
| | |
| def draw_symops(obj,radius=0.2,extension=0):
| |
| """
| |
| From pymol issue the "run draw_symops_cctbx.py" command to load the script,
| |
| then issue the "draw_symops(object,<optional radius>,<optional extension>)" command
| |
| to actually run it and create the cgo object.
| |
| | |
| e.g. load 1avv.pdb
| |
| run draw_symops_cctbx.py
| |
| draw_symops 1avv, 0.5, .2
| |
| or draw_symops('1avv',.5,.2)
| |
| or draw_symops 1avv, radius=.5, extension=.2
| |
| | |
| The different axis types appear as different objects on the PyMOL menu so they can be turned
| |
| on and off individually.
| |
| | |
| See also help(draw_symops_param) to draw operators by specifying the space group
| |
| and cell dimensions directly (i.e. not loaded from a pdb file)
| |
| | |
| The 'extension' parameter is a fractional increase in the length of each symmetry
| |
| operator axis drawn. i.e. a value of 0 is the default and a value of .2 increases
| |
| the length by 20% at each end
| |
| """
| |
| radius=float(radius)
| |
| extension=float(extension)
| |
| cell_info=cmd.get_symmetry(obj)
| |
| draw_symops_param(cell_info[0:6],cell_info[6],radius,extension)
| |
| | |
| def draw_symops_param(cell_param_list,sg,radius=0.2,extension=0):
| |
| """
| |
| If you wish to draw the symmetry operators for any cell without the need to load a
| |
| pdb file, then do this:
| |
| | |
| e.g. run draw_symops_cctbx.py
| |
| draw_symops_param((45.2,45.2,70.8,90.,90.,120.),'p3121',0.5,0.1)
| |
|
| |
| to generate the symmetry operators for this trigonal space group "p 31 2 1"
| |
| of radius .5 with 10% added as an extension at each end.
| |
| """
| |
| radius=float(radius)
| |
| extension=float(extension)
| |
| | |
| U=uctbx.unit_cell((cell_param_list))
| |
| | |
| #rotation axes
| |
| # "2" "yellow",
| |
| # "3" "orange",
| |
| # "4" "mauve",
| |
| # "6" "purple",
| |
| | |
| #screw axes (all sub_1 axes are green)
| |
| # "21" "green",
| |
| # "31" "green",
| |
| # "32" "lime",
| |
| # "41" "green",
| |
| # "42" "cyan",
| |
| # "43" "iceblue",
| |
| # "61" "green",
| |
| # "62" "silver",
| |
| # "63" "cyan",
| |
| # "64" "iceblue",
| |
| # "65" "blue",
| |
| | |
| color = {
| |
| "2" : [1.0, 1.0, 0.0],
| |
| "3" : [1.0, 0.5, 0.0],
| |
| "4" : [1.0, 0.5, 1.0],
| |
| "6" : [1.0, 0.0, 1.0],
| |
| "2^1" : [0.0, 1.0, 0.0],
| |
| "3^1" : [0.0, 1.0, 0.0],
| |
| "3^2" : [0.5, 1.0, 0.5],
| |
| "4^1" : [0.0, 1.0, 0.0],
| |
| "4^2" : [0.0, 1.0, 1.0],
| |
| "4^3" : [0.5, 0.5, 1.0],
| |
| "6^1" : [0.0, 1.0, 0.0],
| |
| "6^2" : [0.8, 0.8, 0.8],
| |
| "6^3" : [0.0, 1.0, 1.0],
| |
| "6^4" : [0.5, 0.5, 1.0],
| |
| "6^5" : [0.0, 0.0, 1.0],
| |
| }
| |
| | |
| sg = sg.upper()
| |
| symop_axes = get_all_axes(sg,extension=extension)
| |
| | |
| #CYLINDER = 'CYLINDER'
| |
| ax_obj = {}
| |
| #vert_obj = []
| |
| | |
| #debug_out = open('debug.log','w')
| |
| | |
| if symop_axes:
| |
| for i in range(len(symop_axes)):
| |
| #print symop_axes[i]
| |
| start = map(set_to_zero,U.orthogonalize(map(None,symop_axes[i]['start'])))
| |
| end = map(set_to_zero,U.orthogonalize(map(None,symop_axes[i]['end'])))
| |
| ###############################################################################
| |
| # Tried rounding off start and end values in order to understand why axes go
| |
| # missing in the drawing, but seem to be present in the cgo. Doesn't help!
| |
| # e.g. for space group 'p23' one of the 3-fold rotations is missing (0,0,0 -> x,-x,x)
| |
| # changing one cell axis to something ever so slightly different recovers the axis
| |
| # e.g. set cell to be (30.00001,30.,30.,90.,90.,90) and it works!
| |
| # start = map(lambda x: round(x,3),U.orthogonalize(symop_axes[i]['start']))
| |
| # end = map(lambda x: round(x,3),U.orthogonalize(symop_axes[i]['end']))
| |
| ###############################################################################
| |
| color_ax = color[symop_axes[i]['symb']]
| |
| symb_ax = symop_axes[i]['symb']
| |
| | |
| #print "axis: ",symb_ax, start, end
| |
| if ax_obj.has_key(symb_ax):
| |
| ax_obj[symb_ax].append(CYLINDER)
| |
| else:
| |
| ax_obj[symb_ax] = [CYLINDER]
| |
| | |
| ax_obj[symb_ax] = ax_obj[symb_ax] + start + end + [radius]
| |
| ax_obj[symb_ax] = ax_obj[symb_ax] + color[symb_ax] + color[symb_ax]
| |
| ax_obj[symb_ax] = ax_obj[symb_ax] + draw_symbol(start,end,symb_ax,color[symb_ax],radius*6.)
| |
| | |
| # #######################################################################################
| |
| # # Debugging output to try to understand why some axes go missing in the drawing.
| |
| # # They don't appear to be missing from the cgo object, though!
| |
| # for xxx in ax_obj[symb_ax]:
| |
| # if xxx == 9.0:
| |
| # #print "\n\n",xxx
| |
| # xxx = "\n\n" + str(xxx) + " "
| |
| # debug_out.write(xxx)
| |
| # else:
| |
| # #print xxx
| |
| # #xxx = "\n" + str(xxx) + " "
| |
| # xxx = str(xxx) + " "
| |
| # debug_out.write(xxx)
| |
| # #print ax_obj[symb_ax]
| |
| # debug_out.write("\n\n")
| |
| # big_string = str(ax_obj)
| |
| # debug_out.write(big_string)
| |
| # # End of debugging output
| |
| # #######################################################################################
| |
| | |
| else:
| |
| print "\nNo symmetry axes found for this space group: %s\n" % sg
| |
| | |
| for key in ax_obj.keys():
| |
| name=sg + "_" + key
| |
| cmd.load_cgo(ax_obj[key],name)
| |
| #debug_out.write("\n\n" + key + "\n" + str(ax_obj[key]))
| |
| #return ax_obj
| |
| | |
| cmd.extend("draw_symops",draw_symops)
| |
| #cmd.extend("draw_symops_param",draw_symops_param)
| |
| </source>
| |
| File: all_axes_new.py
| |
| <source lang="python">
| |
| #! /usr/bin/env python
| |
| # List all axes in the unit cell.
| |
| | |
| # usage:
| |
| # python all_axes.py - show axes for the 230 reference settings.
| |
| # python all_axes.py P2 - show axes for (e.g.) space group P2
| |
| | |
| # RWGK = Ralf W. Grosse-Kunstleve
| |
| # RWGK Some further refinement is required:
| |
| # RWGK - List only the axes of highest order (e.g. only 4, not 4 and 2).
| |
| # RWGK - List only the axes with the smallest intrinsic component
| |
| # RWGK (e.g. list only 3(1), not both 3(1) and 3(2)).
| |
| # RWGK See also: comment regarding shift_range below.
| |
| | |
| from cctbx import sgtbx
| |
| #from cctbx.misc.python_utils import list_plus
| |
| | |
| import numpy as N
| |
| import string, re
| |
| | |
| def list_plus(lhs, rhs):
| |
| return [l + r for l, r in zip(lhs, rhs)]
| |
| | |
| def list_minus(lhs, rhs):
| |
| return [l - r for l, r in zip(lhs, rhs)]
| |
| | |
| def list_multiplies(lhs, rhs):
| |
| return [l * r for l, r in zip(lhs, rhs)]
| |
| | |
| def list_divides(lhs, rhs):
| |
| return [l / r for l, r in zip(lhs, rhs)]
| |
| | |
| def list_modulus(lhs, rhs):
| |
| return [l % r for l, r in zip(lhs, rhs)]
| |
| | |
| def list_dot_product(lhs, rhs=0):
| |
| if (rhs == 0): rhs = lhs
| |
| result = 0
| |
| for l, r in zip(lhs, rhs): result += l * r
| |
| return result
| |
| | |
| def str_ev(EV):
| |
| return "[%d,%d,%d]" % EV
| |
| | |
| ###def fract_2_dec(fraction):
| |
| ### list = fraction.split('/')
| |
| ### if len(list) == 2 and list[1] != 0:
| |
| ### decimal = string.atof(list[0])/string.atof(list[1])
| |
| ### else:
| |
| ### decimal = string.atof(fraction)
| |
| ### return decimal
| |
| | |
| def rlc_RTMxAnalysis(M):
| |
| r_info = sgtbx.rot_mx_info(M.r())
| |
| t_info = sgtbx.translation_part_info(M)
| |
| t_intrinsic = t_info.intrinsic_part().mod_positive().as_double()
| |
| t_shift = t_info.origin_shift().mod_positive().as_double()
| |
| | |
| #End = list_plus(Start + map(None,r_info.ev()))
| |
| ####debug
| |
| ### trans = 0
| |
| ### length = 0
| |
| ####debug
| |
|
| |
| #if (r_info.type() == 1):
| |
| if (r_info.type() < 2):
| |
| #(rt, start, end) = ('1',(0,0,0),(0,0,0))
| |
| return None
| |
| #elif (r_info.type() == -1):
| |
| # (rt, start, end) = (str(r_info.type()),t_shift,())
| |
| elif (abs(r_info.type()) == 2):
| |
| trans = reduce(lambda x,y:x+y,t_intrinsic)
| |
| if trans == 0:
| |
| maxr = max([abs(x) for x in r_info.ev()])
| |
| r = [float(x)/maxr for x in r_info.ev()]
| |
| (rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r)))
| |
| #(rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r_info.ev())))
| |
| else:
| |
| maxr = max([abs(x) for x in r_info.ev()])
| |
| r = [float(x)/maxr for x in r_info.ev()]
| |
| (rt, start, end) = (str(r_info.type())+"^1",t_shift,tuple(list_plus(t_shift,r)))
| |
| #(rt, start, end) = (str(r_info.type())+"^1",t_shift,tuple(list_plus(t_shift,r_info.ev())))
| |
| elif (r_info.type() == 3):
| |
| if (r_info.sense() >= 0) :
| |
| # ignore opposite sense of rotation axes since they superimpose
| |
| trans = N.sqrt(reduce(lambda x,y:x+y,(map(lambda x,y:(y-x)*(y-x),(0,0,0),t_intrinsic))))
| |
| # trans = N.sqrt(t_intrinsic[0]**2 + t_intrinsic[1]**2 + t_intrinsic[2]**2)
| |
| if trans == 0:
| |
| maxr = max([abs(x) for x in r_info.ev()])
| |
| r = [float(x)/maxr for x in r_info.ev()]
| |
| # fudge to make sure that PyMOL actually draws the axis (move it slightly off [1,-1,1]) !!!
| |
| r[0] = r[0]*1.000001
| |
| (rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r)))
| |
| #(rt, start, end) = (str(r_info.type()),t_shift, tuple(list_plus(t_shift,r_info.ev())))
| |
| else:
| |
| maxr = max([abs(x) for x in r_info.ev()])
| |
| r = [float(x)/maxr for x in r_info.ev()]
| |
| #(rt, start, end) = (str(r_info.type())+ "^" + subscript ,t_shift,tuple(list_plus(t_shift,r)))
| |
| (start, end) = (t_shift,tuple(list_plus(t_shift,r)))
| |
| length = N.sqrt(reduce(lambda x,y:x+y,(map(lambda x,y:(y-x)*(y-x),start, end))))
| |
|
| |
|
| # r_info.sense() for 3^1 and 3^2 seems always to be "1" ???
| | ==Installing SuperSym== |
| # if r_info.sense() < 0:
| |
| # subscript = str(1-r_info.sense())
| |
| # else:
| |
| # subscript = str(r_info.sense())
| |
|
| |
|
| # use ratio of trans to length to get the correct axis symbol:
| | To install SuperSym v1.2, download SuperSymPlugin12.py from [https://sourceforge.net/projects/supersym/ https://sourceforge.net/projects/supersym/]. In PyMOL, go to: |
| # fudged the value to get the right numbers. (using length/2., rather than length/3.)
| | *Plugin > Manage Plugins > Install... |
| if trans < length*0.5 :
| | A file selector dialog will appear. Select SuperSymPlugin12.py. PyMOL will direct you to restart, and upon doing so SuperSym will be accessible through the Plugin menu. |
| subscript = '1'
| |
| else:
| |
| subscript = '2'
| |
|
| |
|
| rt = str(r_info.type())+ "^" + subscript
| | To use functions of SuperSym directly, without creating a drop-down menu, use the run command in PyMOL on SuperSymPlugin12.py. |
| #(rt, start, end) = (str(r_info.type()) + "^" + subscript,t_shift, tuple(list_plus(t_shift,r_info.ev())))
| |
| ### print "Type, sense, Start, End, length, trans", rt, r_info.sense(), start, end, length, trans
| |
| # print "type: %s, sense: %s, trans: %s, length: %s," % (r_info.type(), r_info.sense(), trans, length)
| |
| # print "(rt, start, end)", (rt,start,end)
| |
| else:
| |
| return None
| |
| #return (r_info.type(),r_info.ev(), t_intrinsic, t_shift)
| |
| elif (r_info.sense() > 0):
| |
| # ignore opposite sense of rotation axes since they superimpose
| |
| trans = reduce(lambda x,y:x+y,t_intrinsic)
| |
| if trans == 0:
| |
| maxr = max([abs(x) for x in r_info.ev()])
| |
| r = [float(x)/maxr for x in r_info.ev()]
| |
| (rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r)))
| |
| #(rt, start, end) = (str(r_info.type()),t_shift, tuple(list_plus(t_shift,r_info.ev())))
| |
| else:
| |
| maxr = max([abs(x) for x in r_info.ev()])
| |
| r = [float(x)/maxr for x in r_info.ev()]
| |
| subscript = str(int(trans*r_info.type()+.5)) # add 0.5 to fix rounding errors
| |
| (rt, start, end) = (str(r_info.type())+ "^" + subscript ,t_shift,tuple(list_plus(t_shift,r)))
| |
| #(rt, start, end) = (str(r_info.type()) + "^" + subscript,t_shift, tuple(list_plus(t_shift,r_info.ev())))
| |
| #return (r_info.type(),r_info.ev(), t_intrinsic, t_shift)
| |
| else:
| |
| return None
| |
| # print "type: %s, sense: %s, trans: %s, length: %s," % (r_info.type(), r_info.sense(), trans, length),
| |
| # print "(rt, start, end)", (rt,start,end)
| |
| return (rt, start, end)
| |
|
| |
|
| def get_all_axes(space_group_symbol=None, space_group_info=None, extension=0):
| | Note: previous errors resulting from incorrect naming of the plugin file have been resolved in v1.2. |
| assert space_group_symbol is None or space_group_info is None
| |
| shift_range = 1 # RWGK Works for the 230 reference settings; it is not
| |
| # RWGK clear to me (rwgk) what value is needed in general.
| |
| if (space_group_symbol is not None):
| |
| space_group_info = sgtbx.space_group_info(symbol=space_group_symbol)
| |
| #space_group_info.show_summary()
| |
|
| |
|
| axes_dict = {}
| | ==Feedback== |
| for smx in space_group_info.group():
| |
| r = smx.r()
| |
| t = smx.t()
| |
| shift = [0,0,0]
| |
| for shift[0] in range(-shift_range,shift_range+1):
| |
| for shift[1] in range(-shift_range,shift_range+1):
| |
| for shift[2] in range(-shift_range,shift_range+1):
| |
| ts = t.plus(sgtbx.tr_vec(shift, 1)).new_denominator(t.den())
| |
| m = sgtbx.rt_mx(r, ts)
| |
| #print m
| |
| rtmxanal = rlc_RTMxAnalysis(m)
| |
| #print r, t, shift, ts, m
| |
| if rtmxanal:
| |
| #print rtmxanal
| |
| axes_dict[rtmxanal] = 0
| |
| axes_list = axes_dict.keys()
| |
| axes_list.sort()
| |
|
| |
|
| # reject nonenantiomorphic space groups
| | Please post any comments, complaints, bug fix requests, useful tricks, or cool adaptations of SuperSym here. |
| if len(axes_list) > 0 and not re.compile("[A-z]").search(space_group_symbol[1:]):
| |
| try:
| |
| sgtbx.space_group_info(space_group_symbol).show_summary(),
| |
| #print len(axes_list), space_group_symbol
| |
| except:
| |
| print space_group, space_group_symbol
| |
| print
| |
| sys.exit(1)
| |
| axes = []
| |
| for a in axes_list:
| |
| if len(a) == 3 and len(a[1]) == 3 and len(a[2]) == 3:
| |
| tmp_dict = {}
| |
| print "%4s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f " % (a[0],a[1][0],a[1][1],a[1][2],a[2][0],a[2][1],a[2][2])
| |
| tmp_dict['symb'] = a[0]
| |
| start_array = N.asarray(a[1])
| |
| end_array = N.asarray(a[2])
| |
| start_vec = start_array - (end_array - start_array)*extension
| |
| end_vec = end_array + (end_array - start_array)*extension
| |
| tmp_dict['start'] = start_vec
| |
| tmp_dict['end'] = end_vec
| |
| #rlc# tmp_dict['start'] = a[1]
| |
| #rlc# tmp_dict['end'] = a[2]
| |
| axes.append(tmp_dict)
| |
| else:
| |
| print a
| |
| else:
| |
| return None
| |
|
| |
|
| return axes
| | ==The Menu== |
| | *'''Default Symmetry Partner Set''' |
| | ** See '''Build Symmetry Partners > Cell [0,0,0] (default)''' |
| | *'''Draw Unit Cell''' |
| | **Creates a cgo object with unit cell axes as cylinders. This functions similarly to ''show cell'', but the cell axes are cylinders instead of lines, allowing for printing. |
| | *'''Build Symmetry Partners >''' |
| | **All options in this submenu generate sets of symmetry partners |
| | **'''Cell [0,0,0] (default)''' |
| | ***Generates a suite of symmetry partners for a given object for the default unit cell, which is lattice position [0,0,0] |
| | **'''Cell [x,y,z] (custom)''' |
| | ***Generates a suite of symmetry partners for a given object for a lattice position which you specify |
| | **'''2x2x2 Block''' |
| | ***Generates 8 sets of symmetry partners for a given object, filling lattice positions [0,0,0] through [1,1,1] |
| | **'''3x3x3 Block''' |
| | ***Generates 27 sets of symmetry partners for a given object, filling lattice positions [-1,-1,-1] through [1,1,1]. This option may take a long time to execute |
| | **'''By Partner''' |
| | ***Generates only those symmetry partners which the user specifies by their defining symmetry operators |
| | *'''Coloring >''' |
| | **'''Default Rainbow''' |
| | ***Colors all symmetry objects with a specified by their symmetry operations automatically |
| | **'''Select color for each operation''' |
| | ***Select symmetry partners to color by their defining symmetry operation and select the color for each |
| | **'''Select one color for custom set of operations''' |
| | ***Select a set of symmetry partners defined by symmetry operations and select one color for all of them |
| | *'''Graphics >''' |
| | **'''Lines''' |
| | ***Convenience function to display symmetry partners as lines |
| | **'''Ribbon''' |
| | **Convenience function to display symmetry partners as ribbons |
| | **'''Cartoon''' |
| | ***Convenience function to display symmetry partners as cartoons |
| | **'''Sphere Surface (best for printing)''' |
| | ***Uses the findSurfaceResidues function and shows surface residues as spheres. If printing, this option saves at least 60% of materials relative to regular surfaces, with minimal loss in resolution |
| | **'''Surface (high load render)''' |
| | ***Displays symmetry partners as surfaces. This option may take a very long time to execute |
| | *'''Symmetry Axes >''' |
| | **'''Build Axes''' |
| | ***Builds all symmetry axes for the given object. This functionality will be customizable and extended in future versions |
| | *'''Move symmetry partners''' |
| | **Merely displays instructions for using built in hotkeys to move symmetry partners |
| | *'''About''' |
| | **Developer info |
| | *'''Help''' |
| | **Reference to this page |
|
| |
|
| if (__name__ == "__main__"):
| | [[Category:Plugins]] |
| import sys
| | [[Category:Script_Library]] |
| if (len(sys.argv) == 1):
| | [[Category:Math_Scripts]] |
| for i in range(230):
| |
| get_all_axes(i + 1)
| |
| else:
| |
| for symbol in sys.argv[1:]:
| |
| get_all_axes(symbol)
| |
| </source>
| |