def visualize_orientation(direction, center=[0, 0, 0], scale=1.0, symmetric=False, color="green", color2="red"): """ Draw an arrow. Helper function for "helix_orientation" etc. """ from pymol import cgo color_list = cmd.get_color_tuple(color) color2_list = cmd.get_color_tuple(color2) if symmetric: scale *= 0.5 end = cpv.add(center, cpv.scale(direction, scale)) radius = 0.3 obj = [cgo.SAUSAGE] obj.extend(center) obj.extend(end) obj.extend([radius, 0.8, 0.8, 0.8]) obj.extend(color_list) if symmetric: start = cpv.sub(center, cpv.scale(direction, scale)) obj.append(cgo.SAUSAGE) obj.extend(center) obj.extend(start) obj.extend([radius, 0.8, 0.8, 0.8]) obj.extend(color2_list) coneend = cpv.add(end, cpv.scale(direction, 4.0 * radius)) if cmd.get_version()[1] >= 1.2: obj.append(cgo.CONE) obj.extend(end) obj.extend(coneend) obj.extend([radius * 1.75, 0.0]) obj.extend(color_list * 2) obj.extend([1.0, 1.0]) # Caps cmd.load_cgo(obj, get_unused_name("oriVec"), zoom=0)
def planeFromPoints(point1, point2, point3, facetSize): v1 = cpv.normalize(cpv.sub(point2, point1)) v2 = cpv.normalize(cpv.sub(point3, point1)) normal = cpv.cross_product(v1, v2) v2 = cpv.cross_product(normal, v1) x = cpv.scale(v1, facetSize) y = cpv.scale(v2, facetSize) center = point2 corner1 = cpv.add(cpv.add(center, x), y) corner2 = cpv.sub(cpv.add(center, x), y) corner3 = cpv.sub(cpv.sub(center, x), y) corner4 = cpv.add(cpv.sub(center, x), y) return plane(corner1, corner2, corner3, corner4, normal)
def visualize_orientation(direction, center=[0.0]*3, scale=1.0, symmetric=False, color='green', color2='red'): ''' DESCRIPTION Draw an arrow. Helper function for "helix_orientation" etc. ''' from pymol import cgo color_list = cmd.get_color_tuple(color) color2_list = cmd.get_color_tuple(color2) if symmetric: scale *= 0.5 end = cpv.add(center, cpv.scale(direction, scale)) radius = 0.3 obj = [cgo.SAUSAGE] obj.extend(center) obj.extend(end) obj.extend([ radius, 0.8, 0.8, 0.8, ]) obj.extend(color_list) if symmetric: start = cpv.sub(center, cpv.scale(direction, scale)) obj.append(cgo.SAUSAGE) obj.extend(center) obj.extend(start) obj.extend([ radius, 0.8, 0.8, 0.8, ]) obj.extend(color2_list) coneend = cpv.add(end, cpv.scale(direction, 4.0*radius/cpv.length(direction))) obj.append(cgo.CONE) obj.extend(end) obj.extend(coneend) obj.extend([ radius * 1.75, 0.0, ]) obj.extend(color_list * 2) obj.extend([ 1.0, 1.0, # Caps ]) cmd.load_cgo(obj, get_unused_name('oriVec'), zoom=0)
def _vec_sum(vec_list): # this is the same as # return numpy.array(vec_list).sum(0).tolist() vec = cpv.get_null() for x in vec_list: vec = cpv.add(vec, x) return vec
def loop_orientation(selection, visualize=1, quiet=0): ''' DESCRIPTION Get the center and approximate direction of a peptide. Works for any secondary structure. Averages direction of N(i)->C(i) pseudo bonds. USAGE loop_orientation selection [, visualize] SEE ALSO helix_orientation ''' visualize, quiet = int(visualize), int(quiet) stored.x = dict() cmd.iterate_state(STATE, '(%s) and name N+C' % (selection), 'stored.x.setdefault(chain + resi, dict())[name] = x,y,z') vec = cpv.get_null() count = 0 for x in stored.x.itervalues(): if 'C' in x and 'N' in x: vec = cpv.add(vec, cpv.sub(x['C'], x['N'])) count += 1 if count == 0: print 'warning: count == 0' raise CmdException vec = cpv.normalize(vec) return _common_orientation(selection, vec, visualize, quiet)
def __call__(self): if self.name not in cmd.get_names('objects'): import threading threading.Thread(None, cmd.delete, args=(self.cb_name,)).start() return v = cmd.get_view() if v == self.prev_v: return self.prev_v = v t = v[12:15] if self.corner: vp = cmd.get_viewport() R_mc = [v[0:3], v[3:6], v[6:9]] off_c = [0.15 * v[11] * vp[0] / vp[1], 0.15 * v[11], 0.0] if self.corner in [2,3]: off_c[0] *= -1 if self.corner in [3,4]: off_c[1] *= -1 off_m = cpv.transform(R_mc, off_c) t = cpv.add(t, off_m) z = -v[11] / 30.0 m = [z, 0, 0, t[0] / z, 0, z, 0, t[1] / z, 0, 0, z, t[2] / z, 0, 0, 0, 1] cmd.set_object_ttt(self.name, m, homogenous=1)
def cgo_tetrahedron(x, y, z, r): vertices = [cpv.add((x,y,z), cpv.scale(v, r)) for v in [ [0., 1., 0.], [0.0, -0.3338068592337708, 0.9426414910921784], [0.8163514779470693, -0.3338068592337708, -0.471320745546089], [-0.816351477947069, -0.3338068592337708, -0.4713207455460897] ]] return [ cgo.BEGIN, cgo.TRIANGLES, cgo.NORMAL, 0.8165448970931916, 0.33317549135767066, 0.4714324161421696, cgo.VERTEX ] + vertices[0] + [ cgo.VERTEX ] + vertices[1] + [ cgo.VERTEX ] + vertices[2] + [ cgo.NORMAL, 0., 0.3331754913576707, -0.9428648322843389, cgo.VERTEX ] + vertices[0] + [ cgo.VERTEX ] + vertices[2] + [ cgo.VERTEX ] + vertices[3] + [ cgo.NORMAL, -0.8165448970931919, 0.3331754913576705, 0.4714324161421693, cgo.VERTEX ] + vertices[0] + [ cgo.VERTEX ] + vertices[3] + [ cgo.VERTEX ] + vertices[1] + [ cgo.NORMAL, 0., -1., 0., cgo.VERTEX ] + vertices[1] + [ cgo.VERTEX ] + vertices[2] + [ cgo.VERTEX ] + vertices[3] + [ cgo.END, ]
def plane_orientation(selection, state=-1, visualize=1, quiet=1): ''' DESCRIPTION Fit plane (for example beta-sheet). Can also be used with angle_between_helices (even though this does not fit helices). Returns center and normal vector of plane. ''' try: import numpy except ImportError: print ' Error: numpy not available' raise CmdException state, visualize, quiet = int(state), int(visualize), int(quiet) coords = list() cmd.iterate_state(state, '(%s) and guide' % (selection), 'coords.append([x,y,z])', space=locals()) if len(coords) < 3: print 'not enough guide atoms in selection' raise CmdException x = numpy.array(coords) U,s,Vh = numpy.linalg.svd(x - x.mean(0)) # normal vector of plane is 3rd principle component vec = cpv.normalize(Vh[2]) if cpv.dot_product(vec, x[-1] - x[0]) < 0: vec = cpv.negate(vec) center = x.mean(0).tolist() _common_orientation(selection, center, vec, visualize, 4.0, quiet) # plane visualize if visualize: from pymol import cgo dir1 = cpv.normalize(Vh[0]) dir2 = cpv.normalize(Vh[1]) sx = [max(i/4.0, 2.0) for i in s] obj = [ cgo.BEGIN, cgo.TRIANGLES, cgo.COLOR, 0.5, 0.5, 0.5 ] for vertex in [ cpv.scale(dir1, sx[0]), cpv.scale(dir2, sx[1]), cpv.scale(dir2, -sx[1]), cpv.scale(dir1, -sx[0]), cpv.scale(dir2, -sx[1]), cpv.scale(dir2, sx[1]), ]: obj.append(cgo.VERTEX) obj.extend(cpv.add(center, vertex)) obj.append(cgo.END) cmd.load_cgo(obj, cmd.get_unused_name('planeFit')) return center, vec
def cgo_arrow(atom1='pk1', atom2='pk2', radius=0.07, gap=0.0, hlength=-1, hradius=-1, color='blue red', name=''): from chempy import cpv radius, gap = float(radius), float(gap) hlength, hradius = float(hlength), float(hradius) try: color1, color2 = color.split() except: color1 = color2 = color color1 = list(cmd.get_color_tuple(color1)) color2 = list(cmd.get_color_tuple(color2)) 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) xyz1 = get_coord(atom1) xyz2 = get_coord(atom2) normal = cpv.normalize(cpv.sub(xyz1, xyz2)) if hlength < 0: hlength = radius * 3.0 if hradius < 0: hradius = hlength * 0.6 if gap: diff = cpv.scale(normal, gap) xyz1 = cpv.sub(xyz1, diff) xyz2 = cpv.add(xyz2, diff) xyz3 = cpv.add(cpv.scale(normal, hlength), xyz2) obj = [cgo.CYLINDER] + xyz1 + xyz3 + [radius] + color1 + color2 + [ cgo.CONE ] + xyz3 + xyz2 + [hradius, 0.0] + color2 + color2 + [1.0, 0.0] return obj
def loop_orientation(selection, state=STATE, visualize=1, quiet=1): ''' DESCRIPTION Get the center and approximate direction of a peptide. Works for any secondary structure. Averages direction of N(i)->C(i) pseudo bonds. USAGE loop_orientation selection [, visualize ] SEE ALSO helix_orientation ''' state, visualize, quiet = int(state), int(visualize), int(quiet) coords = dict() cmd.iterate_state(state, '(%s) and name N+C' % (selection), 'coords.setdefault(chain + resi, {})[name] = x,y,z', space=locals()) vec = cpv.get_null() center = cpv.get_null() count = 0 for x in coords.values(): if 'C' in x and 'N' in x: vec = cpv.add(vec, cpv.sub(x['C'], x['N'])) for coord in x.values(): center = cpv.add(center, coord) count += 1 if count == 0: print('warning: count == 0') raise CmdException vec = cpv.normalize(vec) center = cpv.scale(center, 1. / count) _common_orientation(selection, center, vec, visualize, 2.0 * len(coords), quiet) return center, vec
def _cgo_quad(pos, normal, radius): '''Return a CGO list specifying a quad.''' v1 = cpv.normalize(_perp_vec(normal)) v2 = cpv.cross_product(normal, v1) v1 = cpv.scale(v1, radius) v2 = cpv.scale(v2, radius) obj = [cgo.BEGIN, cgo.TRIANGLE_STRIP, cgo.NORMAL] obj.extend(normal) obj.append(cgo.VERTEX) obj.extend(cpv.add(pos, v1)) obj.append(cgo.VERTEX) obj.extend(cpv.add(pos, v2)) obj.append(cgo.VERTEX) obj.extend(cpv.sub(pos, v2)) obj.append(cgo.VERTEX) obj.extend(cpv.sub(pos, v1)) obj.append(cgo.END) return obj
def draw_arrow(xyz1, xyz2, radius=0.5, gap=0.0, hlength=-1, hradius=-1, color='blue red', name=''): ''' Draw an arrow; borrows heavily from cgi arrows. ''' radius, gap = float(radius), float(gap) hlength, hradius = float(hlength), float(hradius) xyz1 = list(xyz1) xyz2 = list(xyz2) try: color1, color2 = color.split() except: color1 = color2 = color color1 = list(cmd.get_color_tuple(color1)) color2 = list(cmd.get_color_tuple(color2)) normal = cpv.normalize(cpv.sub(xyz1, xyz2)) if hlength < 0: hlength = radius * 3.0 if hradius < 0: hradius = hlength * 0.6 if gap: diff = cpv.scale(normal, gap) xyz1 = cpv.sub(xyz1, diff) xyz2 = cpv.add(xyz2, diff) xyz3 = cpv.add(cpv.scale(normal, hlength), xyz2) obj = [cgo.CYLINDER] + xyz1 + xyz3 + [radius] + color1 + color2 + \ [cgo.CONE] + xyz3 + xyz2 + [hradius, 0.0] + color2 + color2 + \ [1.0, 0.0] if not name: name = cmd.get_unused_name('arrow') cmd.load_cgo(obj, name)
def visualize_orientation(direction, center=[0, 0, 0], scale=1.0, symmetric=False, color='green', color2='red'): ''' Draw an arrow. Helper function for "helix_orientation" etc. ''' from pymol import cgo color_list = cmd.get_color_tuple(color) color2_list = cmd.get_color_tuple(color2) if symmetric: scale *= 0.5 end = cpv.add(center, cpv.scale(direction, scale)) radius = 0.3 obj = [cgo.SAUSAGE] obj.extend(center) obj.extend(end) obj.extend([ radius, 0.8, 0.8, 0.8, ]) obj.extend(color_list) if symmetric: start = cpv.sub(center, cpv.scale(direction, scale)) obj.append(cgo.SAUSAGE) obj.extend(center) obj.extend(start) obj.extend([ radius, 0.8, 0.8, 0.8, ]) obj.extend(color2_list) coneend = cpv.add(end, cpv.scale(direction, 4.0 * radius)) if cmd.get_version()[1] >= 1.2: obj.append(cgo.CONE) obj.extend(end) obj.extend(coneend) obj.extend([ radius * 1.75, 0.0, ]) obj.extend(color_list * 2) obj.extend([ 1.0, 1.0, # Caps ]) cmd.load_cgo(obj, get_unused_name('oriVec'), zoom=0)
def loop_orientation(selection, state=STATE, visualize=1, quiet=1): ''' DESCRIPTION Get the center and approximate direction of a peptide. Works for any secondary structure. Averages direction of N(i)->C(i) pseudo bonds. USAGE loop_orientation selection [, visualize ] SEE ALSO helix_orientation ''' state, visualize, quiet = int(state), int(visualize), int(quiet) coords = dict() cmd.iterate_state(state, '(%s) and name N+C' % (selection), 'coords.setdefault(chain + resi, {})[name] = x,y,z', space=locals()) vec = cpv.get_null() center = cpv.get_null() count = 0 for x in coords.itervalues(): if 'C' in x and 'N' in x: vec = cpv.add(vec, cpv.sub(x['C'], x['N'])) for coord in x.itervalues(): center = cpv.add(center, coord) count += 1 if count == 0: print 'warning: count == 0' raise CmdException vec = cpv.normalize(vec) center = cpv.scale(center, 1./count) _common_orientation(selection, center, vec, visualize, 2.0*len(coords), quiet) return center, vec
def _cgo_quad(pos, normal, radius): '''Return a CGO list specifying a quad.''' v1 = cpv.normalize(_perp_vec(normal)) v2 = cpv.cross_product(normal, v1) v1 = cpv.scale(v1, radius) v2 = cpv.scale(v2, radius) obj = [ cgo.BEGIN, cgo.TRIANGLE_STRIP, cgo.NORMAL] obj.extend(normal) obj.append(cgo.VERTEX) obj.extend(cpv.add(pos, v1)) obj.append(cgo.VERTEX) obj.extend(cpv.add(pos, v2)) obj.append(cgo.VERTEX) obj.extend(cpv.sub(pos, v2)) obj.append(cgo.VERTEX) obj.extend(cpv.sub(pos, v1)) obj.append(cgo.END) return obj
def centerofmass(selection='(all)', state=CURRENT_STATE, quiet=1, *, _self=cmd): ''' DESCRIPTION Calculates the center of mass. Considers atom mass and occupancy. ARGUMENTS selection = string: atom selection {default: all} state = integer: object state, -1 for current state, 0 for all states {default: -1} NOTES If occupancy is 0.0 for an atom, set it to 1.0 for the calculation (assume it was loaded from a file without occupancy information). SEE ALSO get_extent ''' from chempy import cpv state, quiet = int(state), int(quiet) if state < 0: state = _self.get_selection_state(selection) if state == 0: states = list(range(1, _self.count_states(selection) + 1)) else: states = [state] com = cpv.get_null() totmass = 0.0 for state in states: model = _self.get_model(selection, state) for a in model.atom: m = a.get_mass() * (a.q or 1.0) com = cpv.add(com, cpv.scale(a.coord, m)) totmass += m if not totmass: raise pymol.CmdException('mass is zero') com = cpv.scale(com, 1. / totmass) if not quiet: print(' Center of Mass: [%8.3f,%8.3f,%8.3f]' % tuple(com)) return com
def planeFromPoints(p1, p2, p3, vm1=None, vm2=None, center=True, settings={}): v1 = cpv.sub(p1, p2) v2 = cpv.sub(p3, p2) normal = cpv.cross_product(v1, v2) if 'translate' in settings: vtran = cpv.scale(cpv.normalize(normal), settings['translate']) p1_t = cpv.sub(p1, vtran) p2_t = cpv.sub(p2, vtran) p3_t = cpv.sub(p3, vtran) print("New coordinates are:") print_info("New", p1_t, p2_t, p3_t) print("New coordinates are for normalized plane:") v1_t = cpv.normalize(cpv.sub(p1_t, p2_t)) v2_t = cpv.normalize(cpv.sub(p3_t, p2_t)) normal_t = cpv.normalize(cpv.cross_product(v1_t, v2_t)) v2_t = cpv.normalize(cpv.cross_product(normal_t, v1_t)) p1_t2 = cpv.add(v1_t, p2_t) p3_t2 = cpv.add(v2_t, p2_t) print_info("Newnormal", p1_t2, p2_t, p3_t2) if vm1 != None: v1 = cpv.scale(cpv.normalize(v1), vm1) if vm2 != None: v2 = cpv.scale(cpv.normalize(v2), vm2) centrum = p2 if center: corner1 = cpv.add(cpv.add(centrum, v1), v2) corner2 = cpv.sub(cpv.add(centrum, v1), v2) corner3 = cpv.sub(cpv.sub(centrum, v1), v2) corner4 = cpv.add(cpv.sub(centrum, v1), v2) else: corner1 = cpv.add(cpv.add(centrum, v1), v2) corner2 = cpv.add(centrum, v1) corner3 = centrum corner4 = cpv.add(centrum, v2) return plane(corner1, corner2, corner3, corner4, normal, settings)
def test(self, filename): cmd.load(self.datafile(filename), 'map') ori = ORIGINS[filename] ext = [ori, cpv.add(ori, EDGELENGTHS)] self.assertArrayEqual(cmd.get_extent('map'), ext, delta=1e-3) with testing.mktemp('.map') as filename: cmd.save(filename, 'map') cmd.delete('*') cmd.load(filename, 'map') self.assertArrayEqual(cmd.get_extent('map'), ext, delta=1e-3)
def centerofmass(selection='(all)', state=-1, quiet=1, _self=cmd): ''' DESCRIPTION Calculates the center of mass. Considers atom mass and occupancy. ARGUMENTS selection = string: atom selection {default: all} state = integer: object state, -1 for current state, 0 for all states {default: -1} NOTES If occupancy is 0.0 for an atom, set it to 1.0 for the calculation (assume it was loaded from a file without occupancy information). SEE ALSO get_extent ''' from chempy import cpv state, quiet = int(state), int(quiet) if state < 0: states = [get_selection_state(selection)] elif state == 0: states = range(1, _self.count_states(selection)+1) else: states = [state] com = cpv.get_null() totmass = 0.0 for state in states: model = _self.get_model(selection, state) for a in model.atom: m = a.get_mass() * (a.q or 1.0) com = cpv.add(com, cpv.scale(a.coord, m)) totmass += m if not totmass: raise pymol.CmdException('mass is zero') com = cpv.scale(com, 1./totmass) if not quiet: print ' Center of Mass: [%8.3f,%8.3f,%8.3f]' % tuple(com) return com
def _cgo_arrow(position=(0., 0., 0), direction=(1., 0., 0.), length=1., radius=.2, offset=0., color='red'): ''' Generate and return an arrow CGO from (position + offset * direction) to (position + ((length + offset) * direction)). ''' if isinstance(color, str): color = list(pymol.cmd.get_color_tuple(color)) hlength = radius * 2.5 hradius = radius * 2.0 normal = cpv.normalize(direction) xyz1 = cpv.add(position, cpv.scale(normal, offset)) xyz2 = cpv.add(position, cpv.scale(normal, length + offset)) xyz3 = cpv.add(xyz2, cpv.scale(normal, hlength)) return [cgo.CYLINDER] + xyz1 + xyz2 + [radius] + color + color + \ [cgo.CONE] + xyz2 + xyz3 + [hradius, 0.0] + color + color + \ [1.0, 0.0]
def __init__(self, p1, p2, radius, color1, color2=None, color3=None, hlength=None, hradius=None, hlength_scale=3.0, hradius_scale=0.6): if hlength is None: hlength = radius * hlength_scale if hradius is None: hradius = hlength * hradius_scale normal = cpv.normalize(cpv.sub(p1, p2)) pM = cpv.add(cpv.scale(normal, hlength), p2) line = Cylinder(p1, pM, radius, color1, color2) cone = Cone( pM, p2, hradius, color2 or color1, radius2=0, color2=color3 ) self._primitive = (line + cone).primitive
def append_cyl(self): if self.l_vert and self.c_colr and self.l_radi: if self.tri_flag: self.tri_flag=0 self.obj.append(END) self.obj.append(SAUSAGE) d = cpv.sub(self.l_vert[1],self.l_vert[0]) d = cpv.normalize_failsafe(d) d0 = cpv.scale(d,self.l_radi/4.0) self.obj.extend(cpv.add(self.l_vert[0],d0)) self.obj.extend(cpv.sub(self.l_vert[1],d0)) self.obj.append(self.l_radi) self.obj.extend(self.c_colr[0]) self.obj.extend(self.c_colr[1]) self.l_vert=None self.c_colr=None self.l_radi=None
def centerofmass(selection='(all)', state=-1, quiet=1, *, _self=cmd): ''' DESCRIPTION Calculates the center of mass. Considers atom mass and occupancy. ARGUMENTS selection = string: atom selection {default: all} state = integer: object state, -1 for current state, 0 for all states {default: -1} EXAMPLE from psico.querying import * x = centerofmass('chain A') r = gyradius('chain A') cmd.pseudoatom('com', pos=x, vdw=r) SEE ALSO gyradius ''' from chempy import cpv state, quiet = int(state), int(quiet) if state < 0: states = [_self.get_state()] elif state == 0: states = list(range(1, _self.count_states(selection) + 1)) else: states = [state] com = cpv.get_null() totmass = 0.0 for state in states: model = _self.get_model(selection, state) for a in model.atom: if a.q == 0.0: continue m = a.get_mass() * a.q com = cpv.add(com, cpv.scale(a.coord, m)) totmass += m com = cpv.scale(com, 1. / totmass) if not quiet: print(' Center of Mass: [%8.3f,%8.3f,%8.3f]' % tuple(com)) return com
def centerofmass(selection='(all)', state=-1, quiet=1): ''' DESCRIPTION Calculates the center of mass. Considers atom mass and occupancy. ARGUMENTS selection = string: atom selection {default: all} state = integer: object state, -1 for current state, 0 for all states {default: -1} EXAMPLE from psico.querying import * x = centerofmass('chain A') r = gyradius('chain A') cmd.pseudoatom('com', pos=x, vdw=r) SEE ALSO gyradius ''' from chempy import cpv state, quiet = int(state), int(quiet) if state < 0: states = [cmd.get_state()] elif state == 0: states = list(range(1, cmd.count_states(selection)+1)) else: states = [state] com = cpv.get_null() totmass = 0.0 for state in states: model = cmd.get_model(selection, state) for a in model.atom: if a.q == 0.0: continue m = a.get_mass() * a.q com = cpv.add(com, cpv.scale(a.coord, m)) totmass += m com = cpv.scale(com, 1./totmass) if not quiet: print(' Center of Mass: [%8.3f,%8.3f,%8.3f]' % tuple(com)) return com
def COM(selection='all', center=0, quiet=1): model = cmd.get_model(selection) nAtom = len(model.atom) COM = cpv.get_null() for a in model.atom: COM = cpv.add(COM, a.coord) COM = cpv.scale(COM, 1./nAtom) if not int(quiet): print ' COM: [%8.3f,%8.3f,%8.3f]' % tuple(COM) if int(center): cmd.alter_state(1, selection, "(x,y,z)=sub((x,y,z), COM)", space={'COM': COM, 'sub': cpv.sub}) return COM
def centroid(selection='all', center=0, quiet=1): model = cmd.get_model(selection) nAtom = len(model.atom) centroid = cpv.get_null() for a in model.atom: centroid = cpv.add(centroid, a.coord) centroid = cpv.scale(centroid, 1. / nAtom) if not int(quiet): print ' centroid: [%8.3f,%8.3f,%8.3f]' % tuple(centroid) if int(move): cmd.alter_state(1, selection, "(x,y,z)=sub((x,y,z), centroid)", space={'centroid': centroid, 'sub': cpv.sub}) return centroid
def COM(selection='all', center=0, quiet=1): model = cmd.get_model(selection) nAtom = len(model.atom) COM = cpv.get_null() for a in model.atom: COM = cpv.add(COM, a.coord) COM = cpv.scale(COM, 1. / nAtom) if not int(quiet): print ' COM: [%8.3f,%8.3f,%8.3f]' % tuple(COM) if int(center): cmd.alter_state(1, selection, "(x,y,z)=sub((x,y,z), COM)", space={'COM': COM, 'sub': cpv.sub}) return COM
def random_conic(box, size, min_axis): # return a random ellipsoid record of the form: # [ ELLIPSOID, x_pos, y_pos, z_pos, size, x0, y0, z0, x1, y1, z2, x2, y2, z2 ] # where the xyz vectors are orthogonal and of length 1.0 or less. box = box - size tmp0 = [ size + random() * box, size + random() * box, size + random() * box ] tmp1 = cpv.random_vector() tmp2 = cpv.scale(tmp1,box/10) tmp1 = cpv.add(tmp2,tmp0) return [ CONE, tmp0[0], tmp0[1], tmp0[2], # coordinates tmp1[0], tmp1[1], tmp1[2], (abs(random())*0.4+0.2) * size, # radii (abs(random())*0.1+0.01) * size, random(), random(), random(), # colors random(), random(), random(), 1.0, 1.0 ]
def append_tri(self): if self.l_vert: d0 = cpv.sub(self.l_vert[0],self.l_vert[1]) d1 = cpv.sub(self.l_vert[0],self.l_vert[2]) n0 = cpv.cross_product(d0,d1) n0 = cpv.normalize_failsafe(n0) if not self.tri_flag: self.obj.append(BEGIN) self.obj.append(TRIANGLES) self.tri_flag = 1 indices = [0, 1, 2] if not self.l_norm: # TODO could simplify this if ray tracing would support # object-level two_sided_lighting. Duplicating the # face with an offset is a hack and produces visible # lines on edges. n1 = [-n0[0],-n0[1],-n0[2]] ns = cpv.scale(n0,0.002) indices = [0, 1, 2, 4, 3, 5] l_vert_offsetted = [cpv.add(v, ns) for v in self.l_vert] l_vert_offsetted.extend(cpv.sub(v, ns) for v in self.l_vert) self.l_vert = l_vert_offsetted self.l_norm = [n0, n0, n0, n1, n1, n1] elif cpv.dot_product(self.l_norm[0], n0) < 0: indices = [0, 2, 1] for i in indices: self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[i % 3]) self.obj.append(NORMAL) self.obj.extend(self.l_norm[i]) self.obj.append(VERTEX) self.obj.extend(self.l_vert[i]) self.l_vert=None self.t_colr=None self.l_norm=None
def test(self): try: import numpy except ImportError: self.skip('requires numpy') from chempy.brick import Brick spacing = (.5, .5, .5) origin = (3., 4., 5.) shape = (10, 10, 10) range_ = [a * (b - 1) for (a, b) in zip (spacing, shape)] data = numpy.zeros(shape, float) brick = Brick.from_numpy(data, spacing, origin) self.assertArrayEqual(brick.range, range_) cmd.load_brick(brick, 'map') extent = cmd.get_extent('map') self.assertArrayEqual(extent, [origin, cpv.add(origin, range_)])
def find_center_of_mass(selection='(all)', state=-1): """ Find center of mass of the selection and return the value USAGE find_center_of_mass selection find_center_of_mass selection, state=state ARGUMENTS selection a selection-expression state a state index if positive int, 0 to all, or -1 to current """ state = utils.int_to_state(state) model = cmd.get_model(selection, state=state) com = cpv.get_null() # iterate all atoms and add vectors of center of mass of each atoms for atom in model.atom: com = cpv.add(com, atom.coord) com = cpv.scale(com, 1.0 / len(model.atom)) return com
def centroid(selection='all', center=0, quiet=1): model = cmd.get_model(selection) nAtom = len(model.atom) centroid = cpv.get_null() for a in model.atom: centroid = cpv.add(centroid, a.coord) centroid = cpv.scale(centroid, 1. / nAtom) if not int(quiet): print(' centroid: [%8.3f,%8.3f,%8.3f]' % tuple(centroid)) if int(center): cmd.alter_state(1, selection, "(x,y,z)=sub((x,y,z), centroid)", space={ 'centroid': centroid, 'sub': cpv.sub }) return centroid
def plane_orientation(selection, state=STATE, visualize=1, guide=0, quiet=1): ''' DESCRIPTION Fit plane (for example beta-sheet). Can also be used with angle_between_helices (even though this does not fit helices). Returns center and normal vector of plane. ''' try: import numpy except ImportError: print(' Error: numpy not available') raise CmdException state, visualize, quiet = int(state), int(visualize), int(quiet) if int(guide): selection = '(%s) and guide' % (selection) coords = list() cmd.iterate_state(state, selection, 'coords.append([x,y,z])', space=locals()) if len(coords) < 3: print('not enough guide atoms in selection') raise CmdException x = numpy.array(coords) U, s, Vh = numpy.linalg.svd(x - x.mean(0)) # normal vector of plane is 3rd principle component vec = cpv.normalize(Vh[2]) if cpv.dot_product(vec, x[-1] - x[0]) < 0: vec = cpv.negate(vec) center = x.mean(0).tolist() _common_orientation(selection, center, vec, visualize, 4.0, quiet) # plane visualize if visualize: from pymol import cgo dir1 = cpv.normalize(Vh[0]) dir2 = cpv.normalize(Vh[1]) sx = [max(i / 4.0, 2.0) for i in s] obj = [cgo.BEGIN, cgo.TRIANGLES, cgo.COLOR, 0.5, 0.5, 0.5] for vertex in [ cpv.scale(dir1, sx[0]), cpv.scale(dir2, sx[1]), cpv.scale(dir2, -sx[1]), cpv.scale(dir1, -sx[0]), cpv.scale(dir2, -sx[1]), cpv.scale(dir2, sx[1]), ]: obj.append(cgo.VERTEX) obj.extend(cpv.add(center, vertex)) obj.append(cgo.END) cmd.load_cgo(obj, get_unused_name('planeFit')) return center, vec
normal = normalize(cross_product(x,y)) else: (y,x) = basis[0:2] normal = normalize(cross_product(y,x)) obj.extend( [BEGIN, TRIANGLE_STRIP] + [COLOR, 1.0, 1.0, 1.0] + [NORMAL] + normal ) for i in range(sampling+1): x1 = edge y1 = edge*i/sampling vlen = sqrt(x1*x1+y1*y1) x0 = radius*x1/vlen y0 = radius*y1/vlen v0 = add( scale(x, x0 ), scale(y,y0) ) v1 = add( scale(x, x1 ), scale(y,y1) ) if hand: obj.extend( [ VERTEX ] + v0 + [ VERTEX ] + v1 ) else: obj.extend( [ VERTEX ] + v1 + [ VERTEX ] + v0 ) obj.extend( [END] ) # then we load it into PyMOL cmd.load_cgo(obj,'cgo05') # move the read clipping plane back a bit to that that is it brighter
def cgo_arrow(atom1='pk1', atom2='pk2', radius=0.5, gap=0.0, hlength=-1, hradius=-1, color='black black', name=''): ''' #I modify the color the line just before DESCRIPTION Create a CGO arrow between two picked atoms. ARGUMENTS atom1 = string: single atom selection or list of 3 floats {default: pk1} atom2 = string: single atom selection or list of 3 floats {default: pk2} radius = float: arrow radius {default: 0.5} gap = float: gap between arrow tips and the two atoms {default: 0.0} hlength = float: length of head hradius = float: radius of head color = string: one or two color names {default: blue red} name = string: name of CGO object ''' from chempy import cpv radius, gap = float(radius), float(gap) hlength, hradius = float(hlength), float(hradius) try: color1, color2 = color.split() except: color1 = color2 = color color1 = list(cmd.get_color_tuple(color1)) color2 = list(cmd.get_color_tuple(color2)) 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) xyz1 = get_coord(atom1) xyz2 = get_coord(atom2) normal = cpv.normalize(cpv.sub(xyz1, xyz2)) if hlength < 0: hlength = radius * 3.0 if hradius < 0: hradius = hlength * 0.6 if gap: diff = cpv.scale(normal, gap) xyz1 = cpv.sub(xyz1, diff) xyz2 = cpv.add(xyz2, diff) xyz3 = cpv.add(cpv.scale(normal, hlength), xyz2) obj = [cgo.CYLINDER] + xyz1 + xyz3 + [radius] + color1 + color2 + \ [cgo.CONE] + xyz3 + xyz2 + [hradius, 0.0] + color2 + color2 + \ [1.0, 0.0] if not name: name = cmd.get_unused_name('arrow') cmd.load_cgo(obj, name)
def drawmol(self,model): print 'drawmol' self.sphere_list= glGenLists(1) glNewList(self.sphere_list, GL_COMPILE) print 'making sphere list of ', len(model.atom),' atoms' for a in model.atom: try: z = a.get_number() except Exception: z = 0 r,g,b = colours[z] glColor3f(r,g,b) glPushMatrix() x = a.coord[0] y = a.coord[1] zz = a.coord[2] glTranslatef (x, y, zz) fac = rcov[z] / 2.0 glScale(fac,fac,fac) glutSolidSphere(0.4, 16, 16) glPopMatrix() glEndList() self.line_list= glGenLists(1) glNewList(self.line_list, GL_COMPILE) glLineWidth(2.0) glBegin(GL_LINES) line_count = 0 for a in model.atom: try: c = a.conn except AttributeError: c = [] for t in c: if t.get_index() > a.get_index(): line_count = line_count + 1 vec = cpv.sub(t.coord, a.coord) mid = cpv.add(a.coord,cpv.scale(vec,0.5)) try: z = a.get_number() except Exception: z = 0 r,g,b = colours[z] glColor3f(r, g, b) glVertex3f(a.coord[0],a.coord[1],a.coord[2]) glVertex3f(mid[0],mid[1],mid[2]) try: z = t.get_number() except Exception: z = 0 r,g,b = colours[z] glColor3f(r, g, b) glVertex3f(mid[0],mid[1],mid[2]) glVertex3f(t.coord[0],t.coord[1],t.coord[2]) glEnd() glEndList() print 'made line list of ', line_count, ' lines'
if z1 == 0.0: (y, x) = basis[0:2] else: (x, y) = basis[0:2] normal = normalize(cross_product(y, x)) obj.extend([BEGIN, TRIANGLE_STRIP] + [COLOR, 1.0, 1.0, 1.0] + [NORMAL] + normal) for i in range(sampling + 1): x1 = edge y1 = edge * i / sampling vlen = sqrt(x1 * x1 + y1 * y1) x0 = radius * x1 / vlen y0 = radius * y1 / vlen v0 = add(add(scale(x, x0), scale(y, y0)), scale(normal, z1)) v1 = add(add(scale(x, x1), scale(y, y1)), scale(normal, z1)) if hand: obj.extend([VERTEX] + v0 + [VERTEX] + v1) else: obj.extend([VERTEX] + v1 + [VERTEX] + v0) obj.extend([END]) obj.extend([BEGIN, TRIANGLE_STRIP] + [COLOR, 1.0, 1.0, 1.0]) for i in range(sampling + 1): x1 = edge y1 = edge * i / sampling vlen = sqrt(x1 * x1 + y1 * y1)
def append_tri(self): if self.l_vert and not self.l_norm: d0 = cpv.sub(self.l_vert[0], self.l_vert[1]) d1 = cpv.sub(self.l_vert[0], self.l_vert[2]) n0 = cpv.cross_product(d0, d1) n0 = cpv.normalize_failsafe(n0) n1 = [-n0[0], -n0[1], -n0[2]] ns = cpv.scale(n0, 0.002) if not self.tri_flag: self.obj.append(BEGIN) self.obj.append(TRIANGLES) self.tri_flag = 1 self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[0]) self.obj.append(NORMAL) self.obj.extend(n0) self.obj.append(VERTEX) self.obj.extend(cpv.add(self.l_vert[0], ns)) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[1]) self.obj.append(NORMAL) self.obj.extend(n0) self.obj.append(VERTEX) self.obj.extend(cpv.add(self.l_vert[1], ns)) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[2]) self.obj.append(NORMAL) self.obj.extend(n0) self.obj.append(VERTEX) self.obj.extend(cpv.add(self.l_vert[2], ns)) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[0]) self.obj.append(NORMAL) self.obj.extend(n1) self.obj.append(VERTEX) self.obj.extend(cpv.sub(self.l_vert[0], ns)) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[1]) self.obj.append(NORMAL) self.obj.extend(n1) self.obj.append(VERTEX) self.obj.extend(cpv.sub(self.l_vert[1], ns)) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[2]) self.obj.append(NORMAL) self.obj.extend(n1) self.obj.append(VERTEX) self.obj.extend(cpv.sub(self.l_vert[2], ns)) elif self.l_vert and self.t_colr and self.l_norm: if not self.tri_flag: self.obj.append(BEGIN) self.obj.append(TRIANGLES) self.tri_flag = 1 self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[0]) self.obj.append(NORMAL) self.obj.extend(self.l_norm[0]) self.obj.append(VERTEX) self.obj.extend(self.l_vert[0]) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[1]) self.obj.append(NORMAL) self.obj.extend(self.l_norm[1]) self.obj.append(VERTEX) self.obj.extend(self.l_vert[1]) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[2]) self.obj.append(NORMAL) self.obj.extend(self.l_norm[2]) self.obj.append(VERTEX) self.obj.extend(self.l_vert[2]) self.l_vert = None self.t_colr = None self.l_norm = None
def cgo_modevec(atom1='pk1', atom2='pk2', radius=0.05, gap=0.0, hlength=-1, hradius=-1, color='green', name='',scalefactor=10.0, cutoff=0.6, transparency=1.0): #was 0.6cut 12 scale ## scalefactor was 10.0 ''' DESCRIPTION Create a CGO mode vector starting at atom1 and pointint in atom2 displacement ARGUMENTS atom1 = string: single atom selection or list of 3 floats {default: pk1} atom2 = string: displacement to atom1 for modevec radius = float: arrow radius {default: 0.5} gap = float: gap between arrow tips and the two atoms {default: 0.0} hlength = float: length of head hradius = float: radius of head color = string: one or two color names {default: blue red} name = string: name of CGO object scalefactor = scale how big of an arrow to make. Default 5 transparency = 0.0 ~ 1.0, default=1.0 means being totally opaque ''' from chempy import cpv radius, gap = float(radius), float(gap) hlength, hradius = float(hlength), float(hradius) scalefactor, cutoff = float(scalefactor), float(cutoff) transparency = float(transparency) try: color1, color2 = color.split() except: color1 = color2 = color color1 = list(cmd.get_color_tuple(color1)) color2 = list(cmd.get_color_tuple(color2)) 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) xyz1 = get_coord(atom1) xyz2 = get_coord(atom2) newxyz2 = cpv.scale(xyz2, scalefactor) newxyz2 = cpv.add(newxyz2, xyz1) xyz2 = newxyz2 # xyz2 = xyz2[0]*scalefactor, xyz2[1]*scalefactor, xyz2[2]*scalefactor normal = cpv.normalize(cpv.sub(xyz1, xyz2)) if hlength < 0: hlength = radius * 3.0 if hradius < 0: hradius = hlength * 0.6 if gap: diff = cpv.scale(normal, gap) xyz1 = cpv.sub(xyz1, diff) xyz2 = cpv.add(xyz2, diff) xyz3 = cpv.add(cpv.scale(normal, hlength), xyz2) # dont draw arrow if distance is too small distance = cpv.distance(xyz1, xyz2) if distance <= cutoff: return #### generate transparent arrows; #### The original codes are the next block #### --Ran obj = [25.0, transparency, 9.0] + xyz1 + xyz3 + [radius] + color1 + color2 + \ [25.0, transparency, 27.0] + xyz3 + xyz2 + [hradius, 0.0] + color2 + color2 + \ [1.0, 0.0] # obj = [cgo.CYLINDER] + xyz1 + xyz3 + [radius] + color1 + color2 + \ # [cgo.CONE] + xyz3 + xyz2 + [hradius, 0.0] + color2 + color2 + \ # [1.0, 0.0] if not name: name = cmd.get_unused_name('arrow') cmd.load_cgo(obj, name)
def obscure(selection, hiding="medium", keep=0, state=-1, name_map='', name_iso='', quiet=0, _self=cmd): """ DESCRIPTION Given an object or selection, usually a small molecule, obscure it to protect its exact identity. USAGE obscure selection [, hiding [, keep ]] ARGUMENTS selection = str: atom selection to hide hiding = low|medium|high: level to which PyMOL obscures the object {default: medium} keep = 0/1: by default, PyMOL removes the obscured atoms from your file, this flag will keep the atoms in the file. Be careful! NOTES Large molecules are very slow. """ from chempy.cpv import add, scale, random_vector keep = bool(keep) if not keep else int(keep) quiet = int(quiet) hiding = hiding_sc.auto_err(hiding, 'hiding level') hiding = ['low', 'medium', 'high'].index(hiding) # these parameters are fine-tuned for a good visual experience resolution, grid, level = [ [2.00, 0.18, 2.00], # low [3.75, 0.25, 2.50], # medium [4.00, 0.33, 2.00], # high ][hiding] # detect if we're hiding a subset of a molecule, then add one bond, so ensure that what sticks out looks good tmp_sele = _self.get_unused_name("_target") natoms = _self.select(tmp_sele, "(%s) extend 1" % (selection), 0) if not quiet: print(' Obscuring %d atoms' % natoms) # get a new name for the map/surf if not name_map: name_map = _self.get_unused_name("obsc_map") if not name_iso: name_iso = _self.get_unused_name("obsc_surf") if not keep: # randomize the coordinates _self.alter_state(state, tmp_sele, "(x,y,z)=perturb([x,y,z])", space={'perturb': lambda v: add(v, scale(random_vector(), 0.4))}) # clear out charge and b-factor _self.alter(tmp_sele, "(b,q) = (10.0, 1.0)") # make the gaussian map and draw its surface _self.map_new(name_map, "gaussian", grid, tmp_sele, resolution=resolution, quiet=quiet) _self.isosurface(name_iso, name_map, level, quiet=quiet) if not keep: if natoms == _self.count_atoms('byobject (%s)' % (tmp_sele)): names = ' '.join(_self.get_object_list('(%s)' % (selection))) if not quiet: print(' Deleting object:', names) _self.delete(names) else: _self.remove(selection, quiet=quiet) _self.delete(tmp_sele)
def sidechaincenters(object='scc', selection='all', method='bahar1996', name='PS1', *, _self=cmd): ''' DESCRIPTION Creates an object with sidechain representing pseudoatoms for each residue in selection. Two methods are available: (1) Sidechain interaction centers as defined by Bahar and Jernigan 1996 http://www.ncbi.nlm.nih.gov/pubmed/9080182 (2) Sidechain centroids, the pseudoatom is the centroid of all atoms except hydrogens and backbone atoms (N, C and O). NOTE With method "bahar1996", if a residue has all relevant sidechain center atoms missing (for example a MET without SD), it will be missing in the created pseudoatom object. With method "centroid", if you want to exclude C-alpha atoms from sidechains, modify the selection like in this example: sidechaincenters newobject, all and (not name CA or resn GLY), method=2 USAGE sidechaincenters object [, selection [, method ]] ARGUMENTS object = string: name of object to create selection = string: atoms to consider {default: (all)} method = string: bahar1996 or centroid {default: bahar1996} name = string: atom name of pseudoatoms {default: PS1} SEE ALSO pseudoatom ''' from chempy import Atom, cpv, models atmap = dict() if method in ['bahar1996', '1', 1]: modelAll = _self.get_model('(%s) and resn %s' % (selection, '+'.join(sidechaincenteratoms))) for at in modelAll.atom: if at.name in sidechaincenteratoms[at.resn]: atmap.setdefault((at.segi, at.chain, at.resn, at.resi), []).append(at) elif method in ['centroid', '2', 2]: modelAll = _self.get_model('(%s) and polymer and not (hydro or name C+N+O)' % selection) for at in modelAll.atom: atmap.setdefault((at.segi, at.chain, at.resn, at.resi), []).append(at) else: raise CmdException('unknown method: {}'.format(method)) model = models.Indexed() for centeratoms in atmap.values(): center = cpv.get_null() for at in centeratoms: center = cpv.add(center, at.coord) center = cpv.scale(center, 1./len(centeratoms)) atom = Atom() atom.coord = center atom.index = model.nAtom + 1 atom.name = name for key in [ 'segi', 'chain', 'resi_number', 'resi', 'resn', 'hetatm', 'ss', 'b', ]: setattr(atom, key, getattr(at, key)) model.add_atom(atom) model.update_index() if object in _self.get_object_list(): _self.delete(object) _self.load_model(model, object) return model
def torus(center=(0., 0., 0.), normal=(0., 0., 1.), radius=1., color='', cradius=.25, samples=20, csamples=20): ''' Generate and return a torus CGO with given center, normal and ring radius. ''' from math import cos, sin, pi if color and isinstance(color, str): color = list(cmd.get_color_tuple(color)) obj = [] axis = cpv.cross_product(normal, (0., 0., 1.)) angle = -cpv.get_angle(normal, (0., 0., 1.)) matrix = cpv.rotation_matrix(angle, cpv.normalize(axis)) obj_vertex = lambda x, y, z: obj.extend([VERTEX] + cpv.add(center, cpv.transform(matrix, [x, y, z]))) obj_normal = lambda x, y, z: obj.extend([NORMAL] + cpv.transform(matrix, [x, y, z])) r = radius cr = cradius rr = 1.5 * cr dv = 2 * pi / csamples dw = 2 * pi / samples v = 0.0 w = 0.0 while w < 2 * pi: v = 0.0 c_w = cos(w) s_w = sin(w) c_wdw = cos(w + dw) s_wdw = sin(w + dw) obj.append(BEGIN) obj.append(TRIANGLE_STRIP) if color: obj.append(COLOR) obj.extend(color) while v < 2 * pi + dv: c_v = cos(v) s_v = sin(v) c_vdv = cos(v + dv) s_vdv = sin(v + dv) obj_normal( (r + rr * c_v) * c_w - (r + cr * c_v) * c_w, (r + rr * c_v) * s_w - (r + cr * c_v) * s_w, (rr * s_v - cr * s_v)) obj_vertex( (r + cr * c_v) * c_w, (r + cr * c_v) * s_w, cr * s_v) obj_normal( (r + rr * c_vdv) * c_wdw - (r + cr * c_vdv) * c_wdw, (r + rr * c_vdv) * s_wdw - (r + cr * c_vdv) * s_wdw, rr * s_vdv - cr * s_vdv) obj_vertex( (r + cr * c_vdv) * c_wdw, (r + cr * c_vdv) * s_wdw, cr * s_vdv) v += dv obj.append(END) w += dw return obj
def torus(center=(0., 0., 0.), normal=(0., 0., 1.), radius=1., color='', cradius=.25, samples=20, csamples=20, _self=cmd): ''' Generate and return a torus CGO with given center, normal and ring radius. ''' from math import cos, sin, pi if color and isinstance(color, str): color = list(_self.get_color_tuple(color)) obj = [] axis = cpv.cross_product(normal, (0., 0., 1.)) angle = -cpv.get_angle(normal, (0., 0., 1.)) matrix = cpv.rotation_matrix(angle, cpv.normalize(axis)) obj_vertex = lambda x, y, z: obj.extend([VERTEX] + cpv.add(center, cpv.transform(matrix, [x, y, z]))) obj_normal = lambda x, y, z: obj.extend([NORMAL] + cpv.transform(matrix, [x, y, z])) r = radius cr = cradius rr = 1.5 * cr dv = 2 * pi / csamples dw = 2 * pi / samples v = 0.0 w = 0.0 while w < 2 * pi: v = 0.0 c_w = cos(w) s_w = sin(w) c_wdw = cos(w + dw) s_wdw = sin(w + dw) obj.append(BEGIN) obj.append(TRIANGLE_STRIP) if color: obj.append(COLOR) obj.extend(color) while v < 2 * pi + dv: c_v = cos(v) s_v = sin(v) c_vdv = cos(v + dv) s_vdv = sin(v + dv) obj_normal( (r + rr * c_v) * c_w - (r + cr * c_v) * c_w, (r + rr * c_v) * s_w - (r + cr * c_v) * s_w, (rr * s_v - cr * s_v)) obj_vertex( (r + cr * c_v) * c_w, (r + cr * c_v) * s_w, cr * s_v) obj_normal( (r + rr * c_vdv) * c_wdw - (r + cr * c_vdv) * c_wdw, (r + rr * c_vdv) * s_wdw - (r + cr * c_vdv) * s_wdw, rr * s_vdv - cr * s_vdv) obj_vertex( (r + cr * c_vdv) * c_wdw, (r + cr * c_vdv) * s_wdw, cr * s_vdv) v += dv obj.append(END) w += dw return obj
def append_tri(self): if self.l_vert and not self.l_norm: d0 = cpv.sub(self.l_vert[0],self.l_vert[1]) d1 = cpv.sub(self.l_vert[0],self.l_vert[2]) n0 = cpv.cross_product(d0,d1) n0 = cpv.normalize_failsafe(n0) n1 = [-n0[0],-n0[1],-n0[2]] ns = cpv.scale(n0,0.002) if not self.tri_flag: self.obj.append(BEGIN) self.obj.append(TRIANGLES) self.tri_flag = 1 self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[0]) self.obj.append(NORMAL) self.obj.extend(n0) self.obj.append(VERTEX) self.obj.extend(cpv.add(self.l_vert[0],ns)) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[1]) self.obj.append(NORMAL) self.obj.extend(n0) self.obj.append(VERTEX) self.obj.extend(cpv.add(self.l_vert[1],ns)) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[2]) self.obj.append(NORMAL) self.obj.extend(n0) self.obj.append(VERTEX) self.obj.extend(cpv.add(self.l_vert[2],ns)) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[0]) self.obj.append(NORMAL) self.obj.extend(n1) self.obj.append(VERTEX) self.obj.extend(cpv.sub(self.l_vert[0],ns)) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[1]) self.obj.append(NORMAL) self.obj.extend(n1) self.obj.append(VERTEX) self.obj.extend(cpv.sub(self.l_vert[1],ns)) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[2]) self.obj.append(NORMAL) self.obj.extend(n1) self.obj.append(VERTEX) self.obj.extend(cpv.sub(self.l_vert[2],ns)) elif self.l_vert and self.t_colr and self.l_norm: if not self.tri_flag: self.obj.append(BEGIN) self.obj.append(TRIANGLES) self.tri_flag = 1 self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[0]) self.obj.append(NORMAL) self.obj.extend(self.l_norm[0]) self.obj.append(VERTEX) self.obj.extend(self.l_vert[0]) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[1]) self.obj.append(NORMAL) self.obj.extend(self.l_norm[1]) self.obj.append(VERTEX) self.obj.extend(self.l_vert[1]) self.obj.append(COLOR) # assuming unicolor self.obj.extend(self.t_colr[2]) self.obj.append(NORMAL) self.obj.extend(self.l_norm[2]) self.obj.append(VERTEX) self.obj.extend(self.l_vert[2]) self.l_vert=None self.t_colr=None self.l_norm=None
def angle_between_helices(selection1, selection2, method='helix', state1=STATE, state2=STATE, visualize=1, quiet=1): ''' DESCRIPTION Calculates the angle between two helices USAGE angle_between_helices selection1, selection2 [, method [, visualize]] ARGUMENTS selection1 = string: atom selection of first helix selection2 = string: atom selection of second helix method = string: function to calculate orientation {default: helix_orientation} visualize = 0 or 1: show fitted vector as arrow {default: 1} EXAMPLE fetch 2x19, async=0 select hel1, /2x19//B/23-36/ select hel2, /2x19//B/40-54/ angle_between_helices hel1, hel2 angle_between_helices hel1, hel2, cafit SEE ALSO helix_orientation, loop_orientation, cafit_orientation, angle_between_domains ''' import math state1, state2 = int(state1), int(state2) visualize, quiet = int(visualize), int(quiet) try: orientation = globals()[methods_sc[str(method)]] except KeyError: print 'no such method:', method raise CmdException if not int(quiet): print ' Using method:', orientation.__name__ cen1, dir1 = orientation(selection1, state1, visualize, quiet=1) cen2, dir2 = orientation(selection2, state2, visualize, quiet=1) angle = cpv.get_angle(dir1, dir2) angle = math.degrees(angle) if not quiet: print ' Angle: %.2f deg' % (angle) if visualize: # measurement object for angle center = cpv.scale(cpv.add(cen1, cen2), 0.5) tmp = get_unused_name('_') for pos in [center, cpv.add(center, cpv.scale(dir1, 5.0)), cpv.add(center, cpv.scale(dir2, 5.0))]: cmd.pseudoatom(tmp, pos=list(pos), state=1) name = get_unused_name('angle') cmd.angle(name, *[(tmp, i) for i in [2,1,3]]) cmd.delete(tmp) cmd.zoom('(%s) or (%s)' % (selection1, selection2), 2, state1 if state1 == state2 else 0) return angle
def sidechaincenters(object='scc', selection='all', method='bahar1996', name='PS1'): ''' DESCRIPTION Creates an object with sidechain representing pseudoatoms for each residue in selection. Two methods are available: (1) Sidechain interaction centers as defined by Bahar and Jernigan 1996 http://www.ncbi.nlm.nih.gov/pubmed/9080182 (2) Sidechain centroids, the pseudoatom is the centroid of all atoms except hydrogens and backbone atoms (N, C and O). NOTE With method "bahar1996", if a residue has all relevant sidechain center atoms missing (for example a MET without SD), it will be missing in the created pseudoatom object. With method "centroid", if you want to exclude C-alpha atoms from sidechains, modify the selection like in this example: sidechaincenters newobject, all and (not name CA or resn GLY), method=2 USAGE sidechaincenters object [, selection [, method ]] ARGUMENTS object = string: name of object to create selection = string: atoms to consider {default: (all)} method = string: bahar1996 or centroid {default: bahar1996} name = string: atom name of pseudoatoms {default: PS1} SEE ALSO pseudoatom ''' from chempy import Atom, cpv, models atmap = dict() if method in ['bahar1996', '1', 1]: modelAll = cmd.get_model('(%s) and resn %s' % (selection, '+'.join(sidechaincenteratoms))) for at in modelAll.atom: if at.name in sidechaincenteratoms[at.resn]: atmap.setdefault((at.segi, at.chain, at.resn, at.resi), []).append(at) elif method in ['centroid', '2', 2]: modelAll = cmd.get_model('(%s) and polymer and not (hydro or name C+N+O)' % selection) for at in modelAll.atom: atmap.setdefault((at.segi, at.chain, at.resn, at.resi), []).append(at) else: print('Error: unknown method:', method) raise CmdException model = models.Indexed() for centeratoms in atmap.values(): center = cpv.get_null() for at in centeratoms: center = cpv.add(center, at.coord) center = cpv.scale(center, 1./len(centeratoms)) atom = Atom() atom.coord = center atom.index = model.nAtom + 1 atom.name = name for key in ['resn','chain','resi','resi_number','hetatm','ss','segi']: atom.__dict__[key] = at.__dict__[key] model.add_atom(atom) model.update_index() if object in cmd.get_object_list(): cmd.delete(object) cmd.load_model(model, object) return model
def angle_between_domains(selection1, selection2, method='align', state1=STATE, state2=STATE, visualize=1, quiet=1): ''' DESCRIPTION Angle by which a molecular selection would be rotated when superposing on a selection2. Do not use for measuring angle between helices, since the alignment of the helices might involve a rotation around the helix axis, which will result in a larger angle compared to the angle between helix axes. USAGE angle_between_domains selection1, selection2 [, method ] ARGUMENTS selection1 = string: atom selection of first helix selection2 = string: atom selection of second helix method = string: alignment command like "align" or "super" {default: align} EXAMPLE fetch 3iplA 3iplB, async=0 select domain1, resi 1-391 select domain2, resi 392-475 align 3iplA and domain1, 3iplB and domain1 angle_between_domains 3iplA and domain2, 3iplB and domain2 SEE ALSO align, super, angle_between_helices ''' import math try: import numpy except ImportError: print ' Error: numpy not available' raise CmdException state1, state2 = int(state1), int(state2) visualize, quiet = int(visualize), int(quiet) if cmd.is_string(method): try: method = cmd.keyword[method][0] except KeyError: print 'no such method:', method raise CmdException mobile_tmp = get_unused_name('_') cmd.create(mobile_tmp, selection1, state1, 1, zoom=0) try: method(mobile=mobile_tmp, target=selection2, mobile_state=1, target_state=state2, quiet=quiet) mat = cmd.get_object_matrix(mobile_tmp) except: print ' Error: superposition with method "%s" failed' % (method.__name__) raise CmdException finally: cmd.delete(mobile_tmp) try: # Based on transformations.rotation_from_matrix # Copyright (c) 2006-2012, Christoph Gohlke R33 = [mat[i:i+3] for i in [0,4,8]] R33 = numpy.array(R33, float) # direction: unit eigenvector of R33 corresponding to eigenvalue of 1 w, W = numpy.linalg.eig(R33.T) i = w.real.argmax() direction = W[:, i].real # rotation angle depending on direction m = direction.argmax() i,j,k,l = [ [2,1,1,2], [0,2,0,2], [1,0,0,1]][m] cosa = (R33.trace() - 1.0) / 2.0 sina = (R33[i, j] + (cosa - 1.0) * direction[k] * direction[l]) / direction[m] angle = math.atan2(sina, cosa) angle = abs(math.degrees(angle)) except: print ' Error: rotation from matrix failed' raise CmdException if not quiet: try: # make this import optional to support running this script standalone from .querying import centerofmass, gyradius except (ValueError, ImportError): gyradius = None try: # PyMOL 1.7.1.6+ centerofmass = cmd.centerofmass except AttributeError: centerofmass = lambda s: cpv.scale(cpv.add(*cmd.get_extent(s)), 0.5) center1 = centerofmass(selection1) center2 = centerofmass(selection2) print ' Angle: %.2f deg, Displacement: %.2f angstrom' % (angle, cpv.distance(center1, center2)) if visualize: center1 = numpy.array(center1, float) center2 = numpy.array(center2, float) center = (center1 + center2) / 2.0 if gyradius is not None: rg = numpy.array(gyradius(selection1), float) else: rg = 10.0 h1 = numpy.cross(center2 - center1, direction) h2 = numpy.dot(R33, h1) h1 *= rg / cpv.length(h1) h2 *= rg / cpv.length(h2) for pos in [center1, center2, center1 + h1, center1 + h2]: cmd.pseudoatom(mobile_tmp, pos=list(pos), state=1) # measurement object for angle and displacement name = get_unused_name('measurement') cmd.distance(name, *['%s`%d' % (mobile_tmp, i) for i in [1,2]]) cmd.angle(name, *['%s`%d' % (mobile_tmp, i) for i in [3,1,4]]) # CGO arrow for axis of rotation visualize_orientation(direction, center1, rg, color='blue') cmd.delete(mobile_tmp) return angle
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 = map(sum, zip(v, [-1, -1, -1])) v = 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
def cgo_arrow(atom1='pk1', atom2='pk2', radius=0.5, gap=0.0, hlength=-1, hradius=-1, color='blue red', name=''): ''' DESCRIPTION Create a CGO arrow between two picked atoms. ARGUMENTS atom1 = string: single atom selection or list of 3 floats {default: pk1} atom2 = string: single atom selection or list of 3 floats {default: pk2} radius = float: arrow radius {default: 0.5} gap = float: gap between arrow tips and the two atoms {default: 0.0} hlength = float: length of head hradius = float: radius of head color = string: one or two color names {default: blue red} name = string: name of CGO object ''' from chempy import cpv radius, gap = float(radius), float(gap) hlength, hradius = float(hlength), float(hradius) try: color1, color2 = color.split() except: color1 = color2 = color color1 = list(cmd.get_color_tuple(color1)) color2 = list(cmd.get_color_tuple(color2)) 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) xyz1 = get_coord(atom1) xyz2 = get_coord(atom2) normal = cpv.normalize(cpv.sub(xyz1, xyz2)) if hlength < 0: hlength = radius * 3.0 if hradius < 0: hradius = hlength * 0.6 if gap: diff = cpv.scale(normal, gap) xyz1 = cpv.sub(xyz1, diff) xyz2 = cpv.add(xyz2, diff) xyz3 = cpv.add(cpv.scale(normal, hlength), xyz2) obj = [cgo.CYLINDER] + xyz1 + xyz3 + [radius] + color1 + color2 + \ [cgo.CONE] + xyz3 + xyz2 + [hradius, 0.0] + color2 + color2 + \ [1.0, 0.0] #obj = [cgo.CYLINDER] + xyz1 + xyz3 + [radius] + color1 + color2 + \ #[cgo.CONE] + xyz3 + xyz2 + [hradius, 0.0] + color2 + color2 + \ #[1.0, 0.0] if not name: name = cmd.get_unused_name('arrow') cmd.load_cgo(obj, name)
def angle_between_domains(selection1, selection2, method='align', state1=STATE, state2=STATE, visualize=1, quiet=1): ''' DESCRIPTION Angle by which a molecular selection would be rotated when superposing on a selection2. Do not use for measuring angle between helices, since the alignment of the helices might involve a rotation around the helix axis, which will result in a larger angle compared to the angle between helix axes. USAGE angle_between_domains selection1, selection2 [, method ] ARGUMENTS selection1 = string: atom selection of first helix selection2 = string: atom selection of second helix method = string: alignment command like "align" or "super" {default: align} EXAMPLE fetch 3iplA 3iplB, bsync=0 select domain1, resi 1-391 select domain2, resi 392-475 align 3iplA and domain1, 3iplB and domain1 angle_between_domains 3iplA and domain2, 3iplB and domain2 SEE ALSO align, super, angle_between_helices ''' import math try: import numpy except ImportError: print(' Error: numpy not available') raise CmdException state1, state2 = int(state1), int(state2) visualize, quiet = int(visualize), int(quiet) if cmd.is_string(method): try: method = cmd.keyword[method][0] except KeyError: print('no such method:', method) raise CmdException mobile_tmp = get_unused_name('_') cmd.create(mobile_tmp, selection1, state1, 1, zoom=0) try: method(mobile=mobile_tmp, target=selection2, mobile_state=1, target_state=state2, quiet=quiet) mat = cmd.get_object_matrix(mobile_tmp) except: print(' Error: superposition with method "%s" failed' % (method.__name__)) raise CmdException finally: cmd.delete(mobile_tmp) try: # Based on transformations.rotation_from_matrix # Copyright (c) 2006-2012, Christoph Gohlke R33 = [mat[i:i + 3] for i in [0, 4, 8]] R33 = numpy.array(R33, float) # direction: unit eigenvector of R33 corresponding to eigenvalue of 1 w, W = numpy.linalg.eig(R33.T) i = w.real.argmax() direction = W[:, i].real # rotation angle depending on direction m = direction.argmax() i, j, k, l = [[2, 1, 1, 2], [0, 2, 0, 2], [1, 0, 0, 1]][m] cosa = (R33.trace() - 1.0) / 2.0 sina = (R33[i, j] + (cosa - 1.0) * direction[k] * direction[l]) / direction[m] angle = math.atan2(sina, cosa) angle = abs(math.degrees(angle)) except: print(' Error: rotation from matrix failed') raise CmdException if not quiet: try: # make this import optional to support running this script standalone from .querying import centerofmass, gyradius except (ValueError, ImportError): gyradius = None try: # PyMOL 1.7.1.6+ centerofmass = cmd.centerofmass except AttributeError: centerofmass = lambda s: cpv.scale(cpv.add(*cmd.get_extent(s)), 0.5) center1 = centerofmass(selection1) center2 = centerofmass(selection2) print(' Angle: %.2f deg, Displacement: %.2f angstrom' % (angle, cpv.distance(center1, center2))) if visualize: center1 = numpy.array(center1, float) center2 = numpy.array(center2, float) center = (center1 + center2) / 2.0 if gyradius is not None: rg = numpy.array(gyradius(selection1), float) else: rg = 10.0 h1 = numpy.cross(center2 - center1, direction) h2 = numpy.dot(R33, h1) h1 *= rg / cpv.length(h1) h2 *= rg / cpv.length(h2) for pos in [center1, center2, center1 + h1, center1 + h2]: cmd.pseudoatom(mobile_tmp, pos=list(pos), state=1) # measurement object for angle and displacement name = get_unused_name('measurement') cmd.distance(name, *['%s`%d' % (mobile_tmp, i) for i in [1, 2]]) cmd.angle(name, *['%s`%d' % (mobile_tmp, i) for i in [3, 1, 4]]) # CGO arrow for axis of rotation visualize_orientation(direction, center1, rg, color='blue') cmd.delete(mobile_tmp) return angle
def obj_vertex(x, y, z): return [cgo.VERTEX] + cpv.add(self.center.array(), cpv.transform(matrix, [x, y, z]))
def angle_between_helices(selection1, selection2, method='helix', state1=STATE, state2=STATE, visualize=1, quiet=1): ''' DESCRIPTION Calculates the angle between two helices USAGE angle_between_helices selection1, selection2 [, method [, visualize]] ARGUMENTS selection1 = string: atom selection of first helix selection2 = string: atom selection of second helix method = string: function to calculate orientation {default: helix_orientation} visualize = 0 or 1: show fitted vector as arrow {default: 1} EXAMPLE fetch 2x19, bsync=0 select hel1, /2x19//B/23-36/ select hel2, /2x19//B/40-54/ angle_between_helices hel1, hel2 angle_between_helices hel1, hel2, cafit SEE ALSO helix_orientation, loop_orientation, cafit_orientation, angle_between_domains ''' import math state1, state2 = int(state1), int(state2) visualize, quiet = int(visualize), int(quiet) try: orientation = globals()[methods_sc[str(method)]] except KeyError: print('no such method:', method) raise CmdException if not int(quiet): print(' Using method:', orientation.__name__) cen1, dir1 = orientation(selection1, state1, visualize, quiet=1) cen2, dir2 = orientation(selection2, state2, visualize, quiet=1) angle = cpv.get_angle(dir1, dir2) angle = math.degrees(angle) if not quiet: print(' Angle: %.2f deg' % (angle)) if visualize: # measurement object for angle center = cpv.scale(cpv.add(cen1, cen2), 0.5) tmp = get_unused_name('_') for pos in [ center, cpv.add(center, cpv.scale(dir1, 5.0)), cpv.add(center, cpv.scale(dir2, 5.0)) ]: cmd.pseudoatom(tmp, pos=list(pos), state=1) name = get_unused_name('angle') cmd.angle(name, *[(tmp, i) for i in [2, 1, 3]]) cmd.delete(tmp) cmd.zoom('(%s) or (%s)' % (selection1, selection2), 2, state1 if state1 == state2 else 0) return angle
def update_box(self): if self.points_name in self.cmd.get_names(): model = self.cmd.get_model(self.points_name) self.coord = ( model.atom[0].coord, model.atom[1].coord, model.atom[2].coord, model.atom[3].coord, ) p = self.coord[0] d10 = sub(self.coord[1], p) d20 = sub(self.coord[2], p) d30 = sub(self.coord[3], p) x10_20 = cross_product(d10,d20) if self.mode != 'quad': if dot_product(d30,x10_20)<0.0: p = model.atom[1].coord d10 = sub(self.coord[0], p) d20 = sub(self.coord[2], p) d30 = sub(self.coord[3], p) n10_20 = normalize(x10_20) n10 = normalize(d10) d100 = d10 d010 = remove_component(d20, n10) if self.mode != 'quad': d001 = project(d30, n10_20) else: d001 = n10_20 n100 = normalize(d100) n010 = normalize(d010) n001 = normalize(d001) f100 = reverse(n100) f010 = reverse(n010) f001 = reverse(n001) if self.mode == 'quad': p000 = p p100 = add(p, remove_component(d10,n001)) p010 = add(p, remove_component(d20,n001)) p001 = add(p, remove_component(d30,n001)) else: p000 = p p100 = add(p,d100) p010 = add(p,d010) p001 = add(p,d001) p110 = add(p100, d010) p011 = add(p010, d001) p101 = add(p100, d001) p111 = add(p110, d001) obj = [] if self.mode == 'box': # standard box obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(f001) obj.append(VERTEX); obj.extend(p000) obj.append(VERTEX); obj.extend(p010) obj.append(VERTEX); obj.extend(p100) obj.append(VERTEX); obj.extend(p110) obj.append(END) obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(n001) obj.append(VERTEX); obj.extend(p001) obj.append(VERTEX); obj.extend(p101) obj.append(VERTEX); obj.extend(p011) obj.append(VERTEX); obj.extend(p111) obj.append(END) obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(f010) obj.append(VERTEX); obj.extend(p000) obj.append(VERTEX); obj.extend(p100) obj.append(VERTEX); obj.extend(p001) obj.append(VERTEX); obj.extend(p101) obj.append(END) obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(n010) obj.append(VERTEX); obj.extend(p010) obj.append(VERTEX); obj.extend(p011) obj.append(VERTEX); obj.extend(p110) obj.append(VERTEX); obj.extend(p111) obj.append(END) obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(f100) obj.append(VERTEX); obj.extend(p000) obj.append(VERTEX); obj.extend(p001) obj.append(VERTEX); obj.extend(p010) obj.append(VERTEX); obj.extend(p011) obj.append(END) obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(n100) obj.append(VERTEX); obj.extend(p100) obj.append(VERTEX); obj.extend(p110) obj.append(VERTEX); obj.extend(p101) obj.append(VERTEX); obj.extend(p111) obj.append(END) model.atom[0].coord = p000 model.atom[1].coord = p100 model.atom[2].coord = add(p010, scale(d100,0.5)) model.atom[3].coord = add(add(p001, scale(d010,0.5)),d100) elif self.mode=='walls': obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(n001) obj.append(VERTEX); obj.extend(p000) obj.append(VERTEX); obj.extend(p100) obj.append(VERTEX); obj.extend(p010) obj.append(VERTEX); obj.extend(p110) obj.append(END) obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(n010) obj.append(VERTEX); obj.extend(p000) obj.append(VERTEX); obj.extend(p001) obj.append(VERTEX); obj.extend(p100) obj.append(VERTEX); obj.extend(p101) obj.append(END) obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(n100) obj.append(VERTEX); obj.extend(p000) obj.append(VERTEX); obj.extend(p010) obj.append(VERTEX); obj.extend(p001) obj.append(VERTEX); obj.extend(p011) obj.append(END) model.atom[0].coord = p000 model.atom[1].coord = p100 model.atom[2].coord = p010 model.atom[3].coord = p001 elif self.mode=='plane': obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(n001) obj.append(VERTEX); obj.extend(p000) obj.append(VERTEX); obj.extend(p100) obj.append(VERTEX); obj.extend(p010) obj.append(VERTEX); obj.extend(p110) obj.append(END) model.atom[0].coord = p000 model.atom[1].coord = p100 model.atom[2].coord = p010 model.atom[3].coord = add(add(p001, scale(d010,0.5)),scale(d100,0.5)) elif self.mode=='quad': obj.extend([ BEGIN, TRIANGLE_STRIP ]) obj.append(NORMAL); obj.extend(n001) obj.append(VERTEX); obj.extend(p000) obj.append(VERTEX); obj.extend(p100) obj.append(VERTEX); obj.extend(p010) obj.append(VERTEX); obj.extend(p001) obj.append(END) model.atom[0].coord = p000 model.atom[1].coord = p100 model.atom[2].coord = p010 model.atom[3].coord = p001 self.cmd.load_model(model, '_tmp', zoom=0) self.cmd.update(self.points_name,"_tmp") self.cmd.delete("_tmp") # then we load it into PyMOL self.cmd.delete(self.cgo_name) self.cmd.load_cgo(obj,self.cgo_name,zoom=0) self.cmd.order(self.cgo_name+" "+self.points_name,sort=1,location='bottom') self.cmd.set("nonbonded_size",math.sqrt(dot_product(d10,d10))/10,self.points_name)
(y,x) = basis[0:2] else: (x,y) = basis[0:2] normal = normalize(cross_product(y,x)) obj.extend( [BEGIN, TRIANGLE_STRIP] + [COLOR, 1.0, 1.0, 1.0] + [NORMAL] + normal ) for i in range(sampling+1): x1 = edge y1 = edge*i/sampling vlen = sqrt(x1*x1+y1*y1) x0 = radius*x1/vlen y0 = radius*y1/vlen v0 = add( add( scale(x, x0 ), scale(y,y0) ), scale(normal,z1) ) v1 = add( add( scale(x, x1 ), scale(y,y1) ), scale(normal,z1) ) if hand: obj.extend( [ VERTEX ] + v0 + [ VERTEX ] + v1 ) else: obj.extend( [ VERTEX ] + v1 + [ VERTEX ] + v0 ) obj.extend( [END] ) obj.extend( [BEGIN, TRIANGLE_STRIP] + [COLOR, 1.0, 1.0, 1.0]) for i in range(sampling+1): x1 = edge