def find_symmetry(seqhashes, chains, outsymfile, rmsd_threshold=3.): seqmatch = {h: [] for h in seqhashes} for h, c in zip(seqhashes, chains): seqmatch[h].append(c) Rlist = [] chainlist = [] tlist = [] for h in seqmatch: chains = seqmatch[h] if len(chains) > 1: chain1 = chains[0] B = cmd.get_coords(f'inpdb and chain {chain1} and name CA') for chain2 in chains[1:]: A = cmd.get_coords(f'inpdb and chain {chain2} and name CA') R, t, rmsd, theta_x, theta_y, theta_z = find_rigid_alignment( A, B) if rmsd <= rmsd_threshold: print( f'{chain1}={chain2} (RMSD={rmsd:.2f}Å, θx={theta_x:.2f}°, θy={theta_y:.2f}°, θz={theta_z:.2f}°, tx={t[0]:.2f}Å, ty={t[1]:.2f}Å, tz={t[2]:.2f}Å)' ) Rlist.append(R) tlist.append(t) chainlist.append((chain1, chain2)) numpy.savez(f'{os.path.splitext(outsymfile)[0]}.npz', R=Rlist, t=tlist, chain=chainlist)
def testLoadCoords(self): import numpy cmd.fragment('gly', 'm1') coords = cmd.get_coords('m1') coords += 5.0 cmd.load_coords(coords, 'm1') self.assertTrue(numpy.allclose(coords, cmd.get_coords('m1')))
def calculate_kozakov2015(*args, **kwargs): """ Calculate a hotspot following Kozakov et al (2015). USAGE calculate_kozakov2015 sel1, ... EXAMPLES calculate_kozakov2015 *CS.000_*, *CS.002_* calculate_kozakov2015 *.000_*, *.001_* """ clusters = [] for sel in args: cluster = Cluster("", sel, pm.get_coords(sel)) clusters.append(cluster) ensemble = Kozakov2015Ensemble(clusters) print( textwrap.dedent(f""" {ensemble} Class {ensemble.klass} S {ensemble.strength} S0 {ensemble.strength0} CD {ensemble.max_center_to_center} MD {ensemble.max_dist} """))
def apply_symmetry(R, t, inchain, outchain): cmd.copy('symm', f'inpdb') coords = cmd.get_coords('symm') cmd.remove(f'symm and not chain {inchain}') coords_symm = (R.dot(coords.T)).T + t cmd.load_coords(coords_symm, 'symm') myspace = {'outchain': outchain} cmd.alter('symm', 'chain=f"{outchain}"', space=myspace)
def testLoadCoordset(self): import numpy cmd.fragment('gly', 'm1') coords = cmd.get_coordset('m1') cmd.load_coordset(coords, 'm1', state=2) self.assertEqual(2, cmd.count_states('m1')) # data manipulation with copy=0 cmd.get_coordset('m1', copy=0)[:] += 5.0 self.assertTrue(numpy.allclose(coords + 5.0, cmd.get_coords('m1')))
def get_coords(pdbfilename, object, device, selection=None): if selection is None: selection = f'{object} and name CA' else: selection = f'{object} and name CA and {selection}' cmd.load(pdbfilename, object=object) cmd.remove(f'not ({selection}) and {object}') coords = cmd.get_coords(selection=object) coords = torch.from_numpy(coords) coords = coords.to(device) return coords
def generate_grid(rna, outname="test", grid_size=2, padding=2.0, mindist=2.5, maxdist=5.0, debug=False): # goto working directory # setup 3D grid extent = cmd.get_extent(selection=rna) x = np.arange(extent[0][0] - padding, extent[1][0] + padding, grid_size) y = np.arange(extent[0][1] - padding, extent[1][1] + padding, grid_size) z = np.arange(extent[0][2] - padding, extent[1][2] + padding, grid_size) xx, yy, zz = np.meshgrid(x, y, z) nx, ny, nz = xx.shape[0], xx.shape[1], xx.shape[2] # place pseudoatoms along grid k = 1 for ix in tqdm(range(nx)): for iy in range(ny): for iz in range(nz): cmd.pseudoatom("tmpPoint", hetatm=1, name="C", resn="UNK", resi=k, chain="ZZ", pos=[ float(xx[ix, iy, iz]), float(yy[ix, iy, iz]), float(zz[ix, iy, iz]) ]) # prune cmd.remove("resn UNK and resi %s within %s of polymer" % (k, mindist)) cmd.remove("resn UNK and resi %s beyond %s of polymer" % (k, maxdist)) # write out grid file coor = "%s_grid.xyz" % (outname) xyz = cmd.get_coords('tmpPoint', 1) df = pd.DataFrame.from_records(xyz) df.insert(0, "element", "C") df.to_csv(coor, index=False, header=False, sep=" ") # write out complex cmd.create("complex", "%s tmpPoint" % rna) coor = "%s_grid.pdb" % (outname) cmd.save(coor, "complex") if debug: cmd.show("surface", "polymer") cmd.show("spheres", "resn UNK")
def determineDist(inputFile, pseudoAtomCoord): dist2Dlist = [] for i in range(1, cmd.count_states(inputFile.split(".")[0])): ligcoords = cmd.get_coords(inputFile.split(".")[0], i) distList = [] for coord1 in ligcoords: distVector = coord1 - pseudoAtomCoord distList.append(np.sqrt(np.vdot(distVector, distVector))) dist2Dlist.append(distList) #print dist2Dlist return dist2Dlist
def collect(cls): for id in range(0, 50): obj_mask = "consensus.{id:03}.*".format(id=id) objs = fnmatch.filter(pm.get_object_list(), obj_mask) if len(objs) == 0: break if len(objs) > 1: raise Exception(f"Too much objects found: {', '.join(objs)}") obj = objs[0] pm.flag("ignore", obj, "clear", True) coords = pm.get_coords(obj) yield Cluster(id, obj, coords)
def fix_coords_len(obj, offset, device): """ Add or remove C-alpha if needed - offset > 0: add offset ca - offset < 0: remove offset ca """ n = cmd.select(obj) if offset < 0: print(f'Removing {-offset} CA') # torm = numpy.random.choice(n, size=-offset, replace=False) + 1 torm = numpy.arange(n)[::-1][:-offset] cmd.remove(f'{obj} and index {torm[-1]}-{torm[0]}') if offset > 0: print(f'Adding {offset} CA') pos = tuple(cmd.get_coords(obj).mean(axis=0)) for i in range(offset): cmd.pseudoatom(obj, pos=pos, resn='ALA', hetatm=False, name='CA') coords_out = cmd.get_coords(obj) coords_out = torch.from_numpy(coords_out) coords_out = coords_out.to(device) return coords_out
def determineSide(inputFile, centerpos, normalvector): dot2Dlist = [] for i in range(1, cmd.count_states(inputFile.split(".")[0])): ligcoords = cmd.get_coords(inputFile.split(".")[0], i) dotList = [] for coord1 in ligcoords: if np.dot(coord1 - centerpos, normalvector) > 0: # Positive means outside dotList.append(True) else: dotList.append(False) dot2Dlist.append(dotList) return dot2Dlist
def pdb_to_surf(pdbfilename, sel): cmd.reinitialize() cmd.load(pdbfilename, 'tosurf') selection = f'tosurf and {sel}' cmd.remove(f'not {sel}') coords = cmd.get_coords(selection) cmd.hide('everything') cmd.show_as('surface', selection) outwrl = f"{os.path.splitext(pdbfilename)[0]}.wrl" cmd.save(outwrl) pts = read_wrl(outwrl) pts += coords.mean(axis=0) return pts
def get_atoms(sel, attrs, state=1): """Get the atoms and attributes of a selection.""" coords = None if "coords" in attrs: coords = pm.get_coords(sel, state) attrs.remove("coords") atoms = pd.DataFrame(coords, columns=["x", "y", "z"]) if attrs: fields_str = ", ".join(attrs) stored.atoms = [] pm.iterate_state(state, sel, f"stored.atoms.append(({fields_str}))") atoms = pd.concat( [atoms, pd.DataFrame(stored.atoms, columns=attrs)], axis=1) del stored.atoms return atoms
def display_graphkernel(pdb_id, pdb_path): ''' ''' # Load PDB cmd.bg_color('white') cmd.load(pdb_path + pdb_id[:-2] + '.pdb') cmd.split_chains(pdb_id[:-2]) for name in cmd.get_names('objects', 0, '(all)'): if not name.endswith(pdb_id[-1].upper()) and name.startswith( pdb_id[:4]): cmd.delete(name) else: zero_residues(name) cmd.reset() pdb_id2 = pdb_id + 'copy' cmd.create(pdb_id2, pdb_id) cmd.hide('everything', pdb_id) cmd.show_as('lines', pdb_id + ' and (name ca or name c or name n)') cmd.set('line_width', 5) cmd.set_bond('line_width', 5, pdb_id + ' and (name ca or name c or name n)') cmd.show('spheres', pdb_id + ' and name ca') cmd.set('sphere_transparency', 0.0, pdb_id + ' and name ca') cmd.set('sphere_scale', 0.5, pdb_id + ' and name ca') cmd.hide('everything', pdb_id2) cmd.show('spheres', pdb_id2 + ' and name ca') cmd.set('sphere_transparency', 0.8, pdb_id2 + ' and name ca') cmd.set('sphere_scale', code2[elem], elem + '&' + selection) #cmd.set('sphere_scale', 2, pdb_id2 + ' and name ca') data = cmd.get_coords(selection=pdb_id + ' and name ca', state=1) j = 55 cmd.set('dash_width', 1.0) cmd.set('dash_color', 'marine') for i in range(len(data)): cmd.distance('d' + str(i) + str(j), pdb_id2 + ' and name ca and res ' + str(i), pdb_id2 + ' and name ca and res ' + str(j)) cmd.hide('labels', 'd' + str(i) + str(j)) resicolor(pdb_id) resicolor(pdb_id) resicolor(pdb_id2, True)
def get_non_collinearity(angles, resmin, resmax, resistep, selection='all', helicize=True): if helicize: helicize_beta_peptide(angles, selection) angles = [] for r, rstep in zip(range(resmin, resmax + 1), itertools.cycle(resistep)): if rstep==0: continue if r<resmin or r+rstep<resmin or r>resmax or r+rstep>resmax: continue selections = ['({}) and resi {} and name N'.format(selection, r), '({}) and resi {} and name HN'.format(selection, r), '({}) and resi {} and name O'.format(selection, r + rstep), '({}) and resi {} and name C'.format(selection, r + rstep)] if any([cmd.count_atoms(sel) == 0 for sel in selections]): continue coords = [cmd.get_coords(sel) for sel in selections] vec1 = coords[1] - coords[0] # N->HN vector vec2 = coords[2] - coords[3] # C->O vector cosphi = (vec1 * vec2).sum() / (vec1 ** 2).sum() ** 0.5 / (vec2 ** 2).sum() ** 0.5 angles.append(np.arccos(cosphi) * 180 / np.pi) return angles
def testChemCompCartnUse(self): xyz_model = (1., 2., 3.) xyz_ideal = (4., 5., 6.) xyz_short = (7., 8., 9.) for (value, xyz) in [ (0x00, xyz_ideal), (0x01, xyz_ideal), (0x02, xyz_model), (0x03, xyz_ideal), (0x04, xyz_short), (0x05, xyz_ideal), (0x06, xyz_model), (0x07, xyz_ideal), ]: cmd.set('chem_comp_cartn_use', value) cmd.load(self.datafile('chem_comp-fe.cif'), 'm1') self.assertArrayEqual(xyz, cmd.get_coords('m1').reshape(-1)) cmd.delete('*')
def save_zone(self): coords = cmd.get_coords(selection='zone_selection') mrc = mrcutils.MRC('%s.mrc' % self.current_mrc) zone_filename = '%s_zone.mrc' % self.current_mrc mrc.zone(coords, radius=self.zone_radius, mrcfilename=zone_filename)
def display_graphconv(pdb_id, pdb_path): ''' ''' cmd.bg_color('white') cmd.load(pdb_path + pdb_id[:-2] + '.pdb') cmd.split_chains(pdb_id[:-2]) for name in cmd.get_names('objects', 0, '(all)'): if not name.endswith(pdb_id[-1].upper()) and name.startswith( pdb_id[:4]): cmd.delete(name) else: zero_residues(name) cmd.reset() pdb_id2 = pdb_id + 'copy' cmd.create(pdb_id2, pdb_id) cmd.color('white', pdb_id) cmd.hide('everything', pdb_id) cmd.show('spheres', pdb_id + ' and name ca') cmd.set('sphere_transparency', 0.0, pdb_id + ' and name ca') cmd.set('sphere_scale', 0.5, pdb_id + ' and name ca') data = cmd.get_coords(selection=pdb_id + ' and name ca', state=1) j = 55 cmd.set('dash_width', 1.0) cmd.set('dash_color', 'marine') data = np.random.uniform(0, 0.25, len(data)) for i in range(len(data)): cmd.distance('d' + str(i) + str(j), pdb_id + ' and name ca and res ' + str(i), pdb_id + ' and name ca and res ' + str(j)) cmd.hide('labels', 'd' + str(i) + str(j)) cmd.select('toBecolored', pdb_id + ' and name ca and res ' + str(i)) if i == j: cmd.set_color('saliency' + str(i) + pdb_id, list(cmap(norm(1)))[:3]) else: cmd.set_color('saliency' + str(i) + pdb_id, list(cmap(norm(data[i])))[:3]) cmd.color('saliency' + str(i) + pdb_id, 'toBecolored') cmd.color('white', pdb_id2) cmd.hide('everything', pdb_id2) cmd.show('spheres', pdb_id2 + ' and name ca') cmd.set('sphere_transparency', 0.0, pdb_id2 + ' and name ca') cmd.set('sphere_scale', 0.5, pdb_id2 + ' and name ca') j = 55 cmd.set('dash_width', 1.0) cmd.set('dash_color', 'marine') #data = np.random.uniform(0,0.25,len(data)) for i in range(len(data)): cmd.distance('d' + str(i) + str(j), pdb_id2 + ' and name ca and res ' + str(i), pdb_id2 + ' and name ca and res ' + str(j)) cmd.hide('labels', 'd' + str(i) + str(j)) cmd.select('toBecolored', pdb_id2 + ' and name ca and res ' + str(i)) if i == j: cmd.set_color('saliency' + str(i) + pdb_id2, list(cmap(norm(0)))[:3]) else: cmd.set_color('saliency' + str(i) + pdb_id2, list(cmap(norm(data[i])))[:3]) cmd.color('saliency' + str(i) + pdb_id2, 'toBecolored')
def display_graphpool(pdb_id, pdb_path): ''' ''' # Load PDB cmd.bg_color('white') cmd.load(pdb_path + pdb_id[:-2] + '.pdb') cmd.split_chains(pdb_id[:-2]) for name in cmd.get_names('objects', 0, '(all)'): if not name.endswith(pdb_id[-1].upper()) and name.startswith( pdb_id[:4]): cmd.delete(name) else: zero_residues(name) cmd.reset() pdb_id2 = pdb_id + 'copy' cmd.create(pdb_id2, pdb_id) cmd.color('grey', pdb_id) cmd.hide('everything', pdb_id) cmd.show_as('lines', pdb_id + ' and (name ca)') cmd.set('line_width', 5) cmd.set_bond('line_width', 5, pdb_id + ' and (name ca)') cmd.show('spheres', pdb_id + ' and name ca') cmd.set('sphere_transparency', 0.0, pdb_id + ' and name ca') cmd.set('sphere_scale', 0.5, pdb_id + ' and name ca') data = cmd.get_coords(selection=pdb_id + ' and name ca', state=1) data_ = [] cmd.set('dash_color', 'marine') cmd.set('dash_width', 1.0) j = 55 for i in range(len(data)): if i % 2 == 0 and i + 1 < len(data): data[i] = np.mean(data[i:i + 2], axis=0) data[i + 1] = np.array([10000, 10000, 10000]) #cmd.distance('d'+str(i)+str(j), pdb_id + ' and name ca and res ' + str(i), pdb_id + ' and name ca and res ' + str(j)) #cmd.hide('labels', 'd'+str(i)+str(j)) cmd.color('red', pdb_id2) cmd.hide('everything', pdb_id2) cmd.show_as('lines', pdb_id2 + ' and (name ca)') cmd.set('line_width', 5) cmd.set_bond('line_width', 5, pdb_id2 + ' and (name ca)') cmd.show('spheres', pdb_id2 + ' and name ca') cmd.set('sphere_transparency', 0.0, pdb_id2 + ' and name ca') cmd.set('sphere_scale', 0.5, pdb_id2 + ' and name ca') for i in range(len(data)): if i % 2 == 0 and i + 1 < len(data): cmd.alter_state(1, pdb_id2 + ' and name ca and res ' + str(i), '(x,y,z)=' + str(tuple(data[i]))) else: cmd.hide('spheres', pdb_id2 + ' and name ca and res ' + str(i)) pdb_id3 = pdb_id + 'copy2' cmd.create(pdb_id3, pdb_id2) cmd.color('red', pdb_id3) cmd.hide('everything', pdb_id3) cmd.show_as('lines', pdb_id3 + ' and (name ca)') cmd.set('line_width', 5) cmd.set_bond('line_width', 5, pdb_id3 + ' and (name ca)') cmd.show('spheres', pdb_id3 + ' and name ca') cmd.set('sphere_transparency', 0.8, pdb_id3 + ' and name ca') for i in range(len(data)): if i % 2 == 0 and i + 1 < len(data): cmd.set('sphere_scale', np.random.uniform(1.0, 4.5), pdb_id3 + ' and name ca and res ' + str(i)) else: cmd.hide('spheres', pdb_id2 + ' and name ca and res ' + str(i))
def load_pdb(pdbfile, obj, sel): cmd.load(pdbfile, object=obj) cmd.remove(f'(not ({obj} and {sel} and name CA)) and {obj}') coords = cmd.get_coords(selection=f'{obj}') return coords
centerpos = np.array((12.5, 36.7, 8.3)) pointa = np.array([15.18700027, 36.02099991, 3.9849999]) pointb = np.array([17.23699951, 37.56800079, 8.26000023]) pointc = np.array([9.17000008, 34.95100021, 9.55500031]) normalvector = np.cross(pointa - pointb, pointa - pointc) pymol.finish_launching() cmd.load( "/Users/dghosh/Desktop/FreqHitterProject/Luciferase/Analysis/Docking/withPhem.pse" ) superListAtomwise = {} superDistList = [] lenList = [] avgList = [] #inputFile = "1010824.ouput.pdbqt" #cmd.load(pc.vinaOutputDir+inputFile) pseudoAtomCoord = cmd.get_coords("phem") processcount = 0 totalcount = len(os.listdir(pc.vinaOutputDir)) for inputFile in os.listdir(pc.vinaOutputDir): processMolecules(os, pc, centerpos, np, normalvector, cmd, superListAtomwise, superDistList, lenList, avgList, pseudoAtomCoord, inputFile) processcount = processcount + 1 print processcount #print superListAtomwise explicitCountList, percDict = getCountAndPerc( superListAtomwise ) #Read from that earlier list and calculate fractions of molecules INSIDE, averaged over their poses. cmd.quit() percList = [] for v in percDict.values():
name = 'all_' cmd.read_pdbstr(pdb_string, name) return nrg #aa = ['W'] for res_name in aa: ## Get coordinates and offset cmd.load('templates/glycan/{}.pdb'.format(res_name)) stored.IDs = [] cmd.iterate('all','stored.IDs.append((ID))') cmd.alter('all', 'ID = ID - stored.IDs[0] - 1') #cmd.fab(res_name) nrg = minimize(selection=sel, forcefield='GAFF', method='cg', nsteps=2000) #print(nrg) xyz = cmd.get_coords(sel) offset = len(xyz) ## get atom names stored.atom_names = [] cmd.iterate(sel, 'stored.atom_names.append(name)') ## get bonds stored.bonds = [] model = cmd.get_model(sel) for at in model.atom: cmd.iterate('neighbor ID %s' % at.id, 'stored.bonds.append((%s-1, ID-1))' % at.id) bonds = list(set([tuple(sorted(i)) for i in stored.bonds])) bonds.sort()
def make_segis(model, resi1, resi2, resi3, absent_segis_names): segis = [] for resi in (resi1, resi2, resi3): segis.append([]) cmd.iterate('/{}///{}/CA'.format(model, resi), \ 'segis[-1].append(segi)', \ space={'segis': segis}) segis = [set(x) for x in segis] segis = sorted(segis[0] & segis[1] & segis[2]) # xyzs_segis format: # [ # {segi1}[ # {resi1}[x,y,z], # {resi2}[x,y,z], # {resi3}[x,y,z] # ], # {segi2}[...], # {segi3}[...], # ... # ] xyzs_segis = \ cmd.get_coords('/{}/{}//{}+{}+{}/CA'.\ format(model, str_riffle(segis, '+'), resi1, resi2, resi3)) xyzs_segis = np.split(xyzs_segis, len(segis)) # normal vectors for each segi n_vecs = [get_n_vec(*xyzs_segi) for xyzs_segi in xyzs_segis] # angles between each adjacent pair angles = [get_angle(n_vecs[i], n_vecs[i + 1]) for i in range(len(n_vecs) - 1)] # rotation angle between two adjacent aminoacids with error angle_value, angle_error = mean(angles), pstdev(angles) segi_count = int(round(360/angle_value)) real_angle = 360 // segi_count print(angle_value, angle_error) print(real_angle) # main axis parameters axis, axis_error, point, point_error = \ find_mean_line(np.transpose(xyzs_segis, axes=[1,0,2])) # create missing segis (by creating objects) by copying last segi # if segi model names [A,B,C,D,E], used names [A,B,C], then created will be: # [D,E,Fmod1,Gmod1,Hmod1,Imod1,Jmod1,Kmod2,Lmod2,...] # # rotate objects using parameters found previously pattern = segis[-1] sel_pattern = '/{}/{}'.format(model, pattern) segi_num = int(round(360 / angle_value - len(segis))) new_models = ['{}_cp_{}'.format(model, i) for i in range(segi_num)] for i in range(segi_num): segi_name = absent_segis_names[(i+len(segis)) % len(absent_segis_names)] new_segi_count = (i+len(segis)) // len(absent_segis_names) mod_string_i = '{}{}'.format(mod_string, new_segi_count) if new_segi_count != 0 else '' cmd.create(new_models[i], sel_pattern) cmd.alter('/{}/{}'.format(new_models[i], pattern), \ 'segi="{}{}"'.format(segi_name, mod_string_i)) cmd.rotate(axis, (i+1) * real_angle, \ '/{}/{}{}'.format(new_models[i], segi_name, mod_string_i), \ camera=0, origin=point) ### CREATE FINAL OBJECT by merging accessory models ### new = '{}_calc'.format(model) cmd.create(new, \ (str_riffle(new_models, ' | ') + ' | ' if len(new_models) != 0 else '') + \ '/{}/{}'.format(model, str_riffle(segis, '+'))) # delete accessory models for new_model in new_models: cmd.delete(new_model) return new, segi_count
def mcsalign(mobile, target, mobile_state=-1, target_state=-1, cycles=5, timeout=10, method='', exact=0, quiet=1, object=None, _self=cmd): ''' DESCRIPTION Align two (ligand) selections based on Maximum-Common-Substructure. Requires: (rdkit | indigo), csb ARGUMENTS mobile = str: atom selection of mobile object target = str: atom selection of target object mobile_state = int: object state of mobile selection {default: -1 = current state} target_state = int: object state of target selection {default: -1 = current state} cycles = int: number of weight-refinement iterations for weighted RMS fitting {default: 5} timeout = int: MCS search timeout {default: 10} method = indigo or rdkit {default: check availability} exact = 0/1: match elements and bond orders {default: 0} object = str: create an aligment object (requires PyMOL 2.3) EXAMPLE fetch 3zcf 4n8t, async=0 mcsalign /3zcf//A/HEC, /4n8t//A/HEM zoom /4n8t//A/HEM, animate=2, buffer=3 ''' from numpy import identity, dot, take from csb.bio.utils import distance_sq, wfit, fit # moving object m_objects = cmd.get_object_list(mobile) if len(m_objects) != 1: # If selection covers multiple objects, call "mcsalign" for every object for m_object in m_objects: mcsalign('(%s) & model %s' % (mobile, m_object), target, mobile_state, target_state, cycles, timeout, method, quiet) return # get molecules from selections m_sdf = get_molstr(mobile, mobile_state) t_sdf = get_molstr(target, target_state) # find maximum common substructure m_indices, t_indices = get_mcs_indices(method, quiet, m_sdf, t_sdf, timeout, int(exact)) if len(m_indices) < 3: raise CmdException('not enough atoms in MCS') if not int(quiet): print(' MCS-Align: found MCS with %d atoms (%s)' % (len(m_indices), m_objects[0])) # coordinates Y = take(cmd.get_coords(mobile, mobile_state), m_indices, 0) X = take(cmd.get_coords(target, target_state), t_indices, 0) # weighted RMS fitting R, t = fit(X, Y) for _ in range(int(cycles)): data = distance_sq(Y, dot(X - t, R)) scales = 1.0 / data.clip(1e-3) R, t = wfit(X, Y, scales) # superpose m = identity(4) m[0:3, 0:3] = R m[0:3, 3] = t cmd.transform_object(m_objects[0], list(m.flat), mobile_state) if object: t_idx_list = iterate_state_to_list(target_state, target, 'model, index') m_idx_list = iterate_state_to_list(mobile_state, mobile, 'model, index') raw = [[t_idx_list[i], m_idx_list[j]] for (i, j) in zip(t_indices, m_indices)] try: _self.set_raw_alignment(object, raw, guide=t_idx_list[0][0]) except AttributeError: raise CmdException( 'Creating an alignment object requires PyMOL 2.3')
def pocket(protein, mode=None, ligand=None, pocket_coordinate=None, residue=None, resid=None, prefix=None, min_rad=1.4, max_rad=3.4, lig_excl_rad=None, lig_incl_rad=None, display_mode="solid", color='marine', alpha=0.85, output_dir=None, subdivide=None, minimum_volume=200, min_subpocket_rad=1.7, min_subpocket_surf_rad=1.0, max_clusters=None, excl_org=False, constrain_inputs=True): """Calculates the SAS for a binding pocket and displays it Args: protein (str): PyMOL selection string for the protein mode (str): pocket identification mode (can be largest, all, or specific) (Default value = None) ligand (str): PyMOL selection string for the ligand (Default value = None) pocket_coordinate ([float]): 3D coordinate used for pocket specification (Default value = None) residue (str): PyMOL residue selection string for pocket specification (Default value = None) resid (str): residue identifier for pocket specification (Default value = None) prefix (str): identifying string for output (Default value = None) min_rad (float): radius for SAS calculations (Default value = 1.4) max_rad (float): radius used to identify the outer, bulk solvent exposed surface (Default value = 3.4) lig_excl_rad (float): maximum distance from a provided ligand that can be included in calculated pockets (Default value = None) lig_incl_rad (float): minimum distance from a provided ligand that should be included in calculated pockets when solvent border is ambiguous (Default value = None) display_mode (str): display mode for calculated pockets (Default value = "solid") color (str): PyMOL color string (Default value = 'marine') alpha (float): transparency value (Default value = 0.85) output_dir (str): filename of the directory in which to place all output; can be absolute or relative (Default value = None) subdivide (bool): calculate subpockets? (Default value = None) minimum_volume (float): minimum volume of pockets returned when running in 'all' mode (Default value = 200) min_subpocket_rad (float): minimum radius that identifies distinct subpockets (Default value = 1.7) min_subpocket_surf_rad (float): radius used to calculate subpocket surfaces (Default value = 1.0) max_clusters (int): maximum number of clusters (Default value = None) excl_org (bool): exclude non-peptide atoms from the protein selection? (Default value = False) constrain_inputs (bool): constrain input quantitative values to tested ranges? (Default value = True) """ timestamp = time.strftime("%H%M%S") if output_dir is None: output_dir = tempfile.mkdtemp() else: logging.debug("Output directory set to {0}".format(output_dir)) utilities.check_dir(output_dir) if excl_org: # protein = "({0}) and (not org)".format(protein) protein = "({0}) and (poly)".format(protein) if ligand is not None: protein = "({0}) and not ({1})".format(protein, ligand) lig_file = os.path.join(output_dir, "{0}_lig.pdb".format(timestamp)) cmd.save(lig_file, ligand) logger.debug("Ligand selection: {0}".format(ligand)) else: lig_file = None logger.debug("Final protein selection: {0}".format(protein)) prot_atoms = cmd.count_atoms(protein) if prot_atoms == 0: logger.error("No atoms included in protein selection") return elif prot_atoms < 50: logger.warning( "Only {0} atoms included in protein selection".format(prot_atoms)) prot_file = os.path.join( output_dir, "{0}_{1}.pdb".format(timestamp, protein.split()[0].strip("(").strip(")"))) cmd.save(prot_file, protein) residue_coordinates = None if residue is not None: residue_coordinates = cmd.get_coords(residue, 1) if (mode is None) and ((ligand is not None) or (pocket_coordinate is not None) or (resid is not None) or (residue_coordinates is not None)): mode = "specific" elif mode is None: mode = "largest" logger.info("Running in mode: {0}".format(mode)) spheres = identify.pocket(prot_file, mode=mode, lig_file=lig_file, resid=resid, residue_coordinates=residue_coordinates, coordinate=pocket_coordinate, min_rad=min_rad, max_rad=max_rad, lig_excl_rad=lig_excl_rad, lig_incl_rad=lig_incl_rad, subdivide=subdivide, minimum_volume=minimum_volume, min_subpocket_rad=min_subpocket_rad, prefix=prefix, output_dir=output_dir, min_subpocket_surf_rad=min_subpocket_surf_rad, max_clusters=max_clusters, constrain_inputs=constrain_inputs) if mode in ["specific", "largest"]: if not subdivide: try: # logger.info("Pocket Volume: {0} A^3".format(format(spheres[0].mesh.volume, '.2f'))) logger.info("Pocket Volume: {0} A^3".format( round(spheres[0].mesh.volume))) pymol_utilities.display_spheres_object(spheres[0], spheres[0].name, state=1, color=color, alpha=alpha, mode=display_mode) except: logger.warning("Volume not calculated for pocket") else: try: logger.info("Whole Pocket Volume: {0} A^3".format( round(spheres[0].mesh.volume))) except: logger.warning("Volume not calculated for the whole pocket") pymol_utilities.display_spheres_object(spheres[0], spheres[0].name, state=1, color=color, alpha=alpha, mode=display_mode) palette = pymol_utilities.construct_palette( max_value=(len(spheres) - 1)) for index, sps in enumerate(spheres[1:]): group = int(sps.g[0]) try: logger.info("{0} volume: {1} A^3".format( sps.name, round(sps.mesh.volume))) pymol_utilities.display_spheres_object( sps, sps.name, state=1, color=palette[index], alpha=alpha, mode=display_mode) except: logger.warning( "Volume not calculated for pocket: {0}".format( sps.name)) cmd.disable(spheres[0].name) if display_mode == "spheres": cmd.group("{0}_sg".format(spheres[0].name), "{0}*_g".format(spheres[0].name)) else: cmd.group("{0}_g".format(spheres[0].name), "{0}*".format(spheres[0].name)) else: # mode is all if len(spheres) == 0: logger.warning("No pockets found with volume > {0} A^3".format( minimum_volume)) return else: logger.info("Pockets found: {0}".format(len(spheres))) palette = pymol_utilities.construct_palette(max_value=len(spheres)) for index, s in enumerate(spheres): try: logger.info("{0} volume: {1} A^3".format( s.name, round(s.mesh.volume))) pymol_utilities.display_spheres_object(s, s.name, state=1, color=palette[index], alpha=alpha, mode=display_mode) except: logger.warning("Volume not calculated for pocket: {0}".format( s.name)) name_template = "p".join(spheres[0].name.split("p")[:-1]) if display_mode == "spheres": cmd.group("{0}sg".format(name_template), "{0}*_g".format(name_template)) else: cmd.group("{0}g".format(name_template), "{0}*".format(name_template)) if output_dir is None: shutil.rmtree(output_dir) return
def inner_lddt(interface=False): # Save the camera save_view = cmd.get_view(output=1, quiet=1) pdbname = cmd.get_object_list()[0] file_path = os.path.join(my_lddt_path, pdbname + ".npz") if ( not os.path.exists(file_path) ): print("Could not find npz file: %s"%file_path) return dat = np.load(file_path) ### Stuff from Nao digitizations = [-20.0, -15.0, -10.0, -4.0, -2.0, -1.0, -0.5, 0.5, 1.0, 2.0, 4.0, 10.0, 15.0, 20.0] masses = [digitizations[0]]+[(digitizations[i]+digitizations[i+1])/2 for i in range(len(digitizations)-1)]+[digitizations[-1]] def get_lddt(estogram, mask, center=7, weights=[1,1,1,1]): # Remove diagonal from the mask. mask = np.multiply(mask, np.ones(mask.shape)-np.eye(mask.shape[0])) # Masking the estogram except for the last cahnnel masked = np.transpose(np.multiply(np.transpose(estogram, [2,0,1]), mask), [1,2,0]) p0 = np.sum(masked[:,:,center], axis=-1) p1 = np.sum(masked[:,:,center-1]+masked[:,:,center+1], axis=-1) p2 = np.sum(masked[:,:,center-2]+masked[:,:,center+2], axis=-1) p3 = np.sum(masked[:,:,center-3]+masked[:,:,center+3], axis=-1) p4 = np.sum(mask, axis=-1) p4[p4==0] = 1 # Only work on parts where interaction happen output = np.divide((weights[0]*p0 + weights[1]*(p0+p1) + weights[2]*(p0+p1+p2) + weights[3]*(p0+p1+p2+p3))/np.sum(weights), p4) return output ##### # if interface, mask out the binder and the target to get individual lddts if ( interface ): blen = len(cmd.get_coords('name CA and chain A', 1)) mask2 = np.zeros(dat['mask'].shape) mask2[:blen, blen:] = 1 mask2[blen:, :blen] = 1 my_lddt = get_lddt(dat['estogram'].transpose([1,2,0]), np.multiply(dat['mask'], mask2)) else: my_lddt = get_lddt(dat['estogram'].transpose([1,2,0]), dat['mask']) print("========== Mean LDDT: %.2f"%np.mean(my_lddt)) # colorspace for lddt visualization max_color = 121 min_color = 0 # interpolate on RGB so we don't see every color in between # set saturation to 0.5 so that we can distinguish from cylinders max_rgb = colorsys.hsv_to_rgb(max_color/360, 0.5, 1) min_rgb = colorsys.hsv_to_rgb(min_color/360, 0.5, 1) max_lddt = 1.0 min_lddt = 0.5 # color each residue the corresponding lddt color for seqpos in range(1, len(dat['mask'])): this_lddt = my_lddt[seqpos-1] r = np.interp(this_lddt, [min_lddt, max_lddt], [min_rgb[0], max_rgb[0]]) * 255 g = np.interp(this_lddt, [min_lddt, max_lddt], [min_rgb[1], max_rgb[1]]) * 255 b = np.interp(this_lddt, [min_lddt, max_lddt], [min_rgb[2], max_rgb[2]]) * 255 color = "0x%02x%02x%02x"%(int(r), int(g), int(b)) colorCPK("resi %i"%seqpos, color) # cmd.color(color, "resi %i"%seqpos,) # get 1 indexed ca positions cas = np.r_[ [[0, 0, 0]], cmd.get_coords('name CA', 1)] # max radius of cylinders (A) max_rad = 0.25 # standard cylinder drawing function. color in HSV def get_cyl(start, end, rad_frac=1.0, color=[360, 0, 1]): rgb = colorsys.hsv_to_rgb(color[0]/360, color[1], color[2]) radius = max_rad * rad_frac cyl = [ # Tail of cylinder cgo.CYLINDER, start[0], start[1], start[2] , end[0], end[1], end[2] , radius, rgb[0], rgb[1], rgb[2], rgb[0], rgb[1], rgb[2] # Radius and RGB for each cylinder tail ] return cyl def obj_exists(sele): return sele in cmd.get_names("objects") # clear out the old ones if we ran this twice for name in cmd.get_names("objects"): if (name.startswith("esto_res")): cmd.delete(name) estogram = np.transpose(dat['estogram'], [1, 2, 0]) # parameters for cylinder colors # Since the lddt calculation maxes out at 4, we do so too # Also, fade near-0 to white so that we don't see sharp edges close_range_colors = [58, 0] far_range_colors = [167, 296] max_range = 4 white_fade = 0.2 # interpolate in hue space so that we do see all colors in-between def dist_to_color(dist): dist = np.clip(dist, -max_range, max_range) # dist = 2 if ( dist < 0 ): bounds = close_range_colors dist = - dist else: bounds = far_range_colors hue = np.interp(dist, [0, max_range], bounds) sat = np.interp(dist, [0, white_fade], [0, 1]) return [hue, sat, 1] # Mask is how likely the model things two residues are within 15A of each other # Don't draw cylinders for super distant residues min_mask = 0.1 # actually draw the cylinders for seqpos in range(1, len(cas)): # pull out the estogram and mask for this position esto = estogram[seqpos-1] # shape (N x 15) mask = dat['mask'][seqpos-1] # shape (N) this_cgo = [] for other in range(1, len(cas)): mask_edge = mask[other-1] if ( mask_edge < min_mask ): continue # estogram is a histogram of distances # this method comes directly from nao and takes the "center_of_mass" of that histogram esto_dist = np.sum(esto[other-1]*masses) color = dist_to_color(esto_dist) this_cgo += get_cyl(cas[seqpos], cas[other], rad_frac=mask_edge, color=color) if ( len(this_cgo) > 0): name = "esto_res%i"%seqpos cmd.load_cgo(this_cgo, name) cmd.disable(name) # disables all estograms and then enables the ones you've selected def enable_selected(): selected = list(set([int(x.resi) for x in cmd.get_model("sele").atom])) for name in cmd.get_names("objects"): if (name.startswith("esto_res")): cmd.disable(name) for seqpos in selected: name = "esto_res%i"%seqpos cmd.enable(name) cmd.delete("sele") cmd.set_key( 'CTRL-C' , enable_selected ) # restore the camera cmd.set_view(save_view)
parser = argparse.ArgumentParser(description='') # parser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest]) parser.add_argument('-p', '--pdb') parser.add_argument('--random', action='store_true', help='Random rotations') parser.add_argument('--translate', action='store_true', help='Random translations') parser.add_argument('--nframes', type=int, default=1000) args = parser.parse_args() cmd.set('retain_order', 1) cmd.load(args.pdb, 'inpdb') coords = cmd.get_coords('inpdb') center = coords.mean(axis=0) coords -= center if not args.random: angles = np.linspace(0, 2 * np.pi, args.nframes // 3) axes = [np.array([1, 0, 0]), np.array([0, 1, 0]), np.array([0, 0, 1])] else: angles = np.random.uniform(low=0, high=2 * np.pi, size=int(np.sqrt(args.nframes))) axes = [ np.random.choice([0, 1], size=3) for _ in range(int(np.sqrt(args.nframes))) ] i = 0
def mcsalign(mobile, target, mobile_state=-1, target_state=-1, cycles=5, timeout=10, method="", quiet=1): """ DESCRIPTION Align two (ligand) selections based on Maximum-Common-Substructure. Requires: (rdkit | indigo), csb ARGUMENTS mobile = str: atom selection of mobile object target = str: atom selection of target object mobile_state = int: object state of mobile selection {default: -1 = current state} target_state = int: object state of target selection {default: -1 = current state} cycles = int: number of weight-refinement iterations for weighted RMS fitting {default: 5} timeout = int: MCS search timeout {default: 10} method = indigo or rdkit {default: check availability} EXAMPLE fetch 3zcf 4n8t, async=0 mcsalign /3zcf//A/HEC, /4n8t//A/HEM zoom /4n8t//A/HEM, animate=2, buffer=3 """ from numpy import identity, dot, take from csb.bio.utils import distance_sq, wfit, fit # moving object m_objects = cmd.get_object_list(mobile) if len(m_objects) != 1: # If selection covers multiple objects, call "mcsalign" for every object for m_object in m_objects: mcsalign( "(%s) & model %s" % (mobile, m_object), target, mobile_state, target_state, cycles, timeout, method, quiet, ) return # get molecules from selections m_sdf = get_molstr(mobile, mobile_state) t_sdf = get_molstr(target, target_state) # find maximum common substructure m_indices, t_indices = get_mcs_indices(method, quiet, m_sdf, t_sdf, timeout) if len(m_indices) < 3: raise CmdException("not enough atoms in MCS") if not int(quiet): print(" MCS-Align: found MCS with %d atoms (%s)" % (len(m_indices), m_objects[0])) # coordinates Y = take(cmd.get_coords(mobile, mobile_state), m_indices, 0) X = take(cmd.get_coords(target, target_state), t_indices, 0) # weighted RMS fitting R, t = fit(X, Y) for _ in range(int(cycles)): data = distance_sq(Y, dot(X - t, R)) scales = 1.0 / data.clip(1e-3) R, t = wfit(X, Y, scales) # superpose m = identity(4) m[0:3, 0:3] = R m[0:3, 3] = t cmd.transform_object(m_objects[0], list(m.flat), mobile_state)
if __name__ == '__main__': import argparse from pymol import cmd # argparse.ArgumentParser(prog=None, usage=None, description=None, epilog=None, parents=[], formatter_class=argparse.HelpFormatter, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True, allow_abbrev=True, exit_on_error=True) parser = argparse.ArgumentParser(description='') # parser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest]) parser.add_argument('--pdb1') parser.add_argument( '--pdb2', help='PDB filename for the reference structure to fit on') parser.add_argument('--sel1', help='Selection for pdb1 (default: all)', default='all') parser.add_argument('--sel2', help='Selection for pdb2 (equal to sel1 if not given)') args = parser.parse_args() cmd.load(args.pdb1, 'pdb1') cmd.load(args.pdb2, 'pdb2') if args.sel2 is None: args.sel2 = args.sel1 coords1 = cmd.get_coords(f'pdb1 and {args.sel1}') coords2 = cmd.get_coords(f'pdb2 and {args.sel2}') R, t = rigid_body_fit(coords1, coords2) print(R) toalign = cmd.get_coords('pdb1') coords_aligned = (R.dot(toalign.T)).T + t cmd.load_coords(coords_aligned, f'pdb1') cmd.save('aligned.pdb', 'pdb1')
def construct_3d_surfaces(*domains, **kwargs): # test = Cylinder(np.array([0,0,1]), np.array([0, 0, 1]), g=9) surface_rad = 1.4 atomic_spheres = None domain_names = [] for index, domain in enumerate(domains): output_dir = tempfile.mkdtemp() prefix = "domain_{0}".format(index) domain_names.append(domain.split(" ")[0]) domain_pdb_file = os.path.join(output_dir, "{0}.pdb".format(prefix)) cmd.save(domain_pdb_file, "{0} and poly".format(domain)) d_p = Spheres(pdb=domain_pdb_file, g=np.float64(index + 1)) if atomic_spheres is None: atomic_spheres = d_p else: atomic_spheres = atomic_spheres + d_p cluster.remove_overlap(atomic_spheres) domains = cluster.extract_groups(atomic_spheres, surf_radius=surface_rad, group_names=domain_names) # add the connectors if True: g1 = 2 g2 = 1 gc = len(domains) + 1 residue_coordinates = cmd.get_coords("2wtk and chain B and resi 185", 1) coord, normal = utilities.closest_vertex_normals( domains[g1 - 1].mesh, domains[g2 - 1].mesh, ref_coordinates=residue_coordinates) p1p, p1n, p2p, p2n, connector = make_interface(coord, normal, gc=gc, g1=g1, g2=g2) # domains = p1p, p1n, p2p, p2n g1_name = domains[g1 - 1].name cluster.remove_included_spheres(domains[g1 - 1], p2n, 1.5) domains[g1 - 1] = domains[g1 - 1] + p1p domains[g1 - 1].g = g1 domains[g1 - 1].name = g1_name g2_name = domains[g2 - 1].name cluster.remove_included_spheres(domains[g2 - 1], p1n, 1.5) domains[g2 - 1] = domains[g2 - 1] + p2p domains[g2 - 1].g = g2 domains[g2 - 1].name = g2_name domains.append(connector) domains[-1].g = gc gestalt = cluster.merge_sphere_list(domains) print(gestalt, gestalt.xyzrg.shape, np.unique(gestalt.g)) cluster.remove_overlap(gestalt, static_last_group=True) print(gestalt.xyzrg.shape, np.unique(gestalt.g)) gestalt_names = [domain.name for domain in domains] domains = cluster.extract_groups(gestalt, surf_radius=surface_rad, group_names=gestalt_names) print(domains) colors = ['tv_red', 'tv_orange', 'tv_blue', 'tv_green'] for index, domain in enumerate(domains): print(domain.name, domain.xyzrg.shape) if not "connection" in domain.name: pymol_utilities.display_spheres_object(domain, domain.name, mode="mesh", color=colors[index]) else: pymol_utilities.display_spheres_object(domain, domain.name, mode="spheres", color=colors[index])
help= 'Project atomic coordinates for selection in caption instead of surface', action='store_true') parser.add_argument('--spheric', help='Project the protein surface on a sphere', action='store_true') parser.add_argument( '--geom', help='Project the geometric center of the caption selections', action='store_true') parser.add_argument('--save', help='Save as a figure') args = parser.parse_args() if args.center is not None: cmd.load(args.pdb) args.center = cmd.get_coords(args.center) cmd.reinitialize() miller = Miller(center=args.center, spheric=args.spheric) surfpts = pdbsurf.pdb_to_surf(args.pdb, args.sel) proj = miller.fit_transform(surfpts) X, Y, Z = grid(proj[:, 0], proj[:, 1], miller.alt) plt.contourf(X, Y, Z, cmap='coolwarm', levels=args.levels) clb = plt.colorbar() clb.set_label('z (Å)') if args.caption is not None: captions = recutils.load(args.caption) print( " ---------------------------------------------------------------" ) for caption in captions: sel = caption['sel']