def gyradius(selection='(all)', state=-1, quiet=1, *, _self=cmd): ''' DESCRIPTION Radius of gyration Based on: http://pymolwiki.org/index.php/Radius_of_gyration SEE ALSO centerofmass ''' 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] rg_sq_list = [] for state in states: model = _self.get_model(selection, state) x = [i.coord for i in model.atom] mass = [i.get_mass() * i.q for i in model.atom if i.q > 0] xm = [cpv.scale(v, m) for v, m in zip(x, mass)] tmass = sum(mass) rr = sum(cpv.dot_product(v, vm) for v, vm in zip(x, xm)) mm = sum((sum(i) / tmass)**2 for i in zip(*xm)) rg_sq_list.append(rr / tmass - mm) rg = (sum(rg_sq_list) / len(rg_sq_list))**0.5 if not quiet: print(' Radius of gyration: %.2f' % (rg)) return rg
def gyradius(selection='(all)', state=-1, quiet=1): ''' DESCRIPTION Radius of gyration Based on: http://pymolwiki.org/index.php/Radius_of_gyration SEE ALSO centerofmass ''' 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] rg_sq_list = [] for state in states: model = cmd.get_model(selection, state) x = [i.coord for i in model.atom] mass = [i.get_mass() * i.q for i in model.atom if i.q > 0] xm = [cpv.scale(v,m) for v,m in zip(x,mass)] tmass = sum(mass) rr = sum(cpv.dot_product(v,vm) for v,vm in zip(x,xm)) mm = sum((sum(i)/tmass)**2 for i in zip(*xm)) rg_sq_list.append(rr/tmass - mm) rg = (sum(rg_sq_list)/len(rg_sq_list))**0.5 if not quiet: print(' Radius of gyration: %.2f' % (rg)) return rg
def cafit_orientation(selection, visualize=1, quiet=0): ''' DESCRIPTION Get the center and direction of a peptide by least squares linear fit on CA atoms. USAGE cafit_orientation selection [, visualize] NOTES Requires python module "numpy". SEE ALSO helix_orientation ''' visualize, quiet = int(visualize), int(quiet) import numpy stored.x = list() cmd.iterate_state(STATE, '(%s) and name CA' % (selection), 'stored.x.append([x,y,z])') x = numpy.array(stored.x) U, s, Vh = numpy.linalg.svd(x - x.mean(0)) vec = cpv.normalize(Vh[0]) if cpv.dot_product(vec, x[-1] - x[0]) < 0: vec = cpv.negate(vec) return _common_orientation(selection, vec, visualize, quiet)
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 cafit_orientation(selection, state=STATE, visualize=1, guide=1, quiet=1, *, _self=cmd): ''' DESCRIPTION Get the center and direction of a peptide by least squares linear fit on CA atoms. USAGE cafit_orientation selection [, visualize ] NOTES Requires python module "numpy". SEE ALSO helix_orientation ''' import numpy state, visualize, quiet = int(state), int(visualize), int(quiet) if int(guide): selection = '(%s) and guide' % (selection) coords = [] _self.iterate_state(state, selection, 'coords.append([x,y,z])', space=locals()) x = numpy.array(coords) center = x.mean(0).tolist() U, s, Vh = numpy.linalg.svd(x - center) vec = cpv.normalize(Vh[0]) if cpv.dot_product(vec, x[-1] - x[0]) < 0: vec = cpv.negate(vec) _common_orientation(selection, center, vec, visualize, s[0], quiet, _self=_self) return center, vec
def cafit_orientation(selection, state=STATE, visualize=1, guide=1, quiet=1): ''' DESCRIPTION Get the center and direction of a peptide by least squares linear fit on CA atoms. USAGE cafit_orientation selection [, visualize ] NOTES Requires python module "numpy". SEE ALSO helix_orientation ''' 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 = [] cmd.iterate_state(state, selection, 'coords.append([x,y,z])', space=locals()) x = numpy.array(coords) center = x.mean(0).tolist() U,s,Vh = numpy.linalg.svd(x - center) vec = cpv.normalize(Vh[0]) if cpv.dot_product(vec, x[-1] - x[0]) < 0: vec = cpv.negate(vec) _common_orientation(selection, center, vec, visualize, s[0], quiet) return center, vec
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 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)
def bbPlane(selection='(all)', color='gray', transp=0.3, state=-1, name=None, quiet=1): """ DESCRIPTION Draws a plane across the backbone for a selection ARGUMENTS selection = string: protein object or selection {default: (all)} color = string: color name or number {default: white} transp = float: transparency component (0.0--1.0) {default: 0.0} state = integer: object state, 0 for all states {default: 1} NOTES You need to pass in an object or selection with at least two amino acids. The plane spans CA_i, O_i, N-H_(i+1), and CA_(i+1) """ from pymol.cgo import BEGIN, TRIANGLES, COLOR, VERTEX, END from pymol import cgo from chempy import cpv # format input transp = float(transp) state, quiet = int(state), int(quiet) if name is None: name = cmd.get_unused_name("backbonePlane") if state < 0: state = cmd.get_state() elif state == 0: for state in range(1, cmd.count_states(selection) + 1): bbPlane(selection, color, transp, state, name, quiet) return AAs = [] coords = dict() # need hydrogens on peptide nitrogen cmd.h_add('(%s) and n. N' % selection) # get the list of residue ids for obj in cmd.get_object_list(selection): sel = obj + " and (" + selection + ")" for a in cmd.get_model(sel + " and n. CA", state).atom: key = '/%s/%s/%s/%s' % (obj, a.segi, a.chain, a.resi) AAs.append(key) coords[key] = [a.coord, None, None] for a in cmd.get_model(sel + " and n. O", state).atom: key = '/%s/%s/%s/%s' % (obj, a.segi, a.chain, a.resi) if key in coords: coords[key][1] = a.coord for a in cmd.get_model(sel + " and ((n. N extend 1 and e. H) or (r. PRO and n. CD))", state).atom: key = '/%s/%s/%s/%s' % (obj, a.segi, a.chain, a.resi) if key in coords: coords[key][2] = a.coord # need at least two amino acids if len(AAs) <= 1: print("ERROR: Please provide at least two amino acids, the alpha-carbon on the 2nd is needed.") return # prepare the cgo obj = [ BEGIN, TRIANGLES, COLOR, ] obj.extend(cmd.get_color_tuple(color)) for res in range(0, len(AAs) - 1): curIdx, nextIdx = str(AAs[res]), str(AAs[res + 1]) # populate the position array pos = [coords[curIdx][0], coords[curIdx][1], coords[nextIdx][2], coords[nextIdx][0]] # if the data are incomplete for any residues, ignore if None in pos: if not quiet: print(' bbPlane: peptide bond %s -> %s incomplete' % (curIdx, nextIdx)) continue if cpv.distance(pos[0], pos[3]) > 4.0: if not quiet: print(' bbPlane: %s and %s not adjacent' % (curIdx, nextIdx)) continue normal = cpv.normalize(cpv.cross_product( cpv.sub(pos[1], pos[0]), cpv.sub(pos[2], pos[0]))) obj.append(cgo.NORMAL) obj.extend(normal) # need to order vertices to generate correct triangles for plane if cpv.dot_product(cpv.sub(pos[0], pos[1]), cpv.sub(pos[2], pos[3])) < 0: vorder = [0, 1, 2, 2, 3, 0] else: vorder = [0, 1, 2, 3, 2, 1] # fill in the vertex data for the triangles; for i in vorder: obj.append(VERTEX) obj.extend(pos[i]) # finish the CGO obj.append(END) # update the UI cmd.load_cgo(obj, name, state, zoom=0) cmd.set("cgo_transparency", transp, name)
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