def intra_theseus(selection, state=1, cov=0, cycles=200, exe='theseus', preserve=0, quiet=1): ''' DESCRIPTION Fits all states of an object to an atom selection with maximum likelihood. THESEUS: Maximum likelihood multiple superpositioning http://www.theseus3d.org ARGUMENTS selection = string: atoms to fit state = integer: keep transformation of this state unchanged {default: 1} cov = 0/1: 0 is variance weighting, 1 is covariance weighting (slower) {default: 0} SEE ALSO intra_fit, intra_rms_cur ''' import tempfile, os state, cov, cycles = int(state), int(cov), int(cycles) preserve, quiet = int(preserve), int(quiet) tempdir = tempfile.mkdtemp() filename = os.path.join(tempdir, 'mobile.pdb') cmd.save(filename, selection, 0) exe = cmd.exp_path(exe) args = [exe, '-a0', '-c' if cov else '-v', '-i%d' % cycles, filename] translations = [] rotations = [] translations, rotations = _run_theseus(args, tempdir, preserve, quiet) matrices = [R[0:3] + [-t[0]] + R[3:6] + [-t[1]] + R[6:9] + [-t[2], 0,0,0, 1] for (R, t) in zip(rotations, translations)] # intra fit states obj_list = cmd.get_object_list('(' + selection + ')') for i, m in enumerate(matrices): for obj in obj_list: cmd.transform_object(obj, m, i+1, transpose=1) # fit back to given state if 0 < state <= len(matrices): m = list(matrices[state-1]) for i in [3,7,11]: m[i] *= -1 for obj in obj_list: cmd.transform_object(obj, m, 0) if not quiet: print(' intra_theseus: %d states aligned' % (len(matrices)))
def symexpcell(prefix='mate', object=None, a=0, b=0, c=0): """ DESCRIPTION Creates all symmetry-related objects for the specified object that occur with their bounding box center within the unit cell. USAGE symexpcell prefix, object, [a, b, c] ARGUMENTS prefix = string: prefix of new objects object = string: object for which to create symmetry mates a, b, c = integer: create neighboring cell {default: 0,0,0} SEE ALSO symexp, http://www.pymolwiki.org/index.php/SuperSym """ if object is None: object = cmd.get_object_list()[0] sym = cmd.get_symmetry(object) cell_edges = sym[0:3] cell_angles = sym[3:6] spacegroup = sym[6] basis = cellbasis(cell_angles, cell_edges) basis = numpy.matrix(basis) extent = cmd.get_extent(object) center = sum(numpy.array(extent)) * 0.5 center = numpy.matrix(center.tolist() + [1.0]).T center_cell = basis.I * center extra_shift = [[float(i)] for i in (a,b,c)] i = 0 matrices = xray.sg_sym_to_mat_list(spacegroup) for mat in matrices: i += 1 mat = numpy.matrix(mat) shift = numpy.floor(mat * center_cell) mat[0:3,3] -= shift[0:3,0] mat[0:3,3] += extra_shift mat = basis * mat * basis.I mat_list = list(mat.flat) name = '%s%d' % (prefix, i) cmd.create(name, object) cmd.transform_object(name, mat_list, 0) cmd.color(i+1, name)
def prosmart(mobile, target, mobile_state=1, target_state=1, exe='prosmart', transform=1, object=None, quiet=0): ''' DESCRIPTION ProSMART wrapper. http://www2.mrc-lmb.cam.ac.uk/groups/murshudov/ ''' import subprocess, tempfile, os, shutil, glob quiet = int(quiet) tempdir = tempfile.mkdtemp() mobile_filename = os.path.join(tempdir, 'mobile.pdb') target_filename = os.path.join(tempdir, 'target.pdb') cmd.save(mobile_filename, mobile, state=mobile_state) cmd.save(target_filename, target, state=target_state) exe = cmd.exp_path(exe) args = [exe, '-p1', mobile_filename, '-p2', target_filename, '-a'] xglob = lambda x: glob.glob(os.path.join(tempdir, 'ProSMART_Output/Output_Files', x)) try: subprocess.check_call(args, cwd=tempdir) transfiles = xglob('Superposition/Transformations/*/*.txt') with open(transfiles[0]) as f: f = iter(f) for line in f: if line.startswith('ROTATION'): matrix = [list(map(float, next(f).split())) + [0] for _ in range(3)] elif line.startswith('TRANSLATION'): matrix.append([-float(v) for v in next(f).split()] + [1]) break if int(transform): matrix = [v for m in matrix for v in m] assert len(matrix) == 4*4 for model in cmd.get_object_list('(' + mobile + ')'): cmd.transform_object(model, matrix, state=0) if object: from .importing import load_aln alnfiles = xglob('Residue_Alignment_Scores/*/*.txt') alnfiles = [x for x in alnfiles if not x.endswith('_clusters.txt')] load_aln(alnfiles[0], object, mobile, target) except OSError: print(' Error: Cannot execute "%s", please provide full path to prosmart executable' % (exe)) raise CmdException finally: shutil.rmtree(tempdir) if not quiet: print(' prosmart: done')
def symexpcell(prefix='mate', object=None, a=0, b=0, c=0): ''' DESCRIPTION Creates all symmetry-related objects for the specified object that occur with their bounding box center within the unit cell. USAGE symexpcell prefix, object, [a, b, c] ARGUMENTS prefix = string: prefix of new objects object = string: object for which to create symmetry mates a, b, c = integer: create neighboring cell {default: 0,0,0} SEE ALSO symexp, http://www.pymolwiki.org/index.php/SuperSym ''' if object is None: object = cmd.get_object_list()[0] sym = cmd.get_symmetry(object) cell_edges = sym[0:3] cell_angles = sym[3:6] spacegroup = sym[6] basis = cellbasis(cell_angles, cell_edges) basis = numpy.matrix(basis) extent = cmd.get_extent(object) center = sum(numpy.array(extent)) * 0.5 center = numpy.matrix(center.tolist() + [1.0]).T center_cell = basis.I * center extra_shift = [[float(i)] for i in (a,b,c)] i = 0 matrices = xray.sg_sym_to_mat_list(spacegroup) for mat in matrices: i += 1 mat = numpy.matrix(mat) shift = numpy.floor(mat * center_cell) mat[0:3,3] -= shift[0:3,0] mat[0:3,3] += extra_shift mat = basis * mat * basis.I mat_list = list(mat.flat) name = '%s%d' % (prefix, i) cmd.create(name, object) cmd.transform_object(name, mat_list) cmd.color(i+1, name)
def poke_pymol(self, matrix): """Forces PyMOL object to move. Argument: matrix -- transformation-rotation-transformation matrix in PyMOL format. """ for attached_structure in Registry.objects[self.derived_from].attachment: if cmd.get_title(*Registry.get(attached_structure, "name", "state")) == "PD": cmd.transform_object(Registry.get(attached_structure, "name"), matrix)
def pymol_xform(name, xform): """TODO: Summary Args: name (TYPE): Description xform (TYPE): Description """ from pymol import cmd assert name in cmd.get_object_list() cmd.transform_object(name, xform.flatten())
def theseus(mobile, target, match='align', cov=0, cycles=200, mobile_state=1, target_state=1, exe='theseus', preserve=0, quiet=1): ''' DESCRIPTION Structural superposition of two molecules with maximum likelihood. THESEUS: Maximum likelihood multiple superpositioning http://www.theseus3d.org ARGUMENTS mobile = string: atom selection for mobile atoms target = string: atom selection for target atoms match = string: in, like, align, none or the name of an alignment object (see "local_rms" help for details) {default: align} cov = 0/1: 0 is variance weighting, 1 is covariance weighting (slower) {default: 0} SEE ALSO align, super, cealign ''' import tempfile, os cov, cycles = int(cov), int(cycles) mobile_state, target_state = int(mobile_state), int(target_state) preserve, quiet = int(preserve), int(quiet) tempdir = tempfile.mkdtemp() mobile_filename = os.path.join(tempdir, 'mobile.pdb') target_filename = os.path.join(tempdir, 'target.pdb') mm = MatchMaker(mobile, target, match) cmd.save(mobile_filename, mm.mobile, mobile_state) cmd.save(target_filename, mm.target, target_state) exe = cmd.exp_path(exe) args = [exe, '-a0', '-c' if cov else '-v', '-i%d' % cycles, mobile_filename, target_filename] translations, rotations = _run_theseus(args, tempdir, preserve, quiet) matrices = [R[0:3] + [i*t[0]] + R[3:6] + [i*t[1]] + R[6:9] + [i*t[2], 0,0,0, 1] for (R, t, i) in zip(rotations, translations, [-1,1])] obj_list = cmd.get_object_list('(' + mobile + ')') for obj in obj_list: cmd.transform_object(obj, matrices[0], 0, transpose=1) cmd.transform_object(obj, matrices[1], 0) if not quiet: print(' theseus: done')
def transform_odb( name, selection, matrix_file='matrix.odb', transpose=0): # open the file for reading matrix_file = os.path.expanduser(matrix_file) matrix_file = os.path.expandvars(matrix_file) theInFile = open ( matrix_file,"r") # what we'll store the results in theMatrix = [] # read every line in the file and ... for theCurrLine in theInFile.readlines(): if (theCurrLine) and (theCurrLine[0] != '!') and (theCurrLine[0] != '.'): # if the line isn't blank, make a list of items seperated by tabs theNewRow = string.split (theCurrLine) # add it in the matrix theMatrix.extend ( theNewRow ) # change matrix to pymol unsupported format theMatrix = [ theMatrix[0], theMatrix[3], theMatrix[6], theMatrix[9], theMatrix[1], theMatrix[4], theMatrix[7], theMatrix[10], theMatrix [2], theMatrix [5], theMatrix[8], theMatrix[11], 0.0, 0.0, 0.0, 0.0 ] theMatrix = [ float(x) for x in theMatrix] # close the file theInFile.close () r = cmd.create ( name, selection) r = cmd.transform_object( name, theMatrix, transpose=transpose) return r
def save_transformed(object, file): """Saves the molecule with coordinates from the current orientation. Args: object (string): PyMOL name file (string): a file name to output file Example:: PyMOL>save_transformed 6bk8_RNA_only_Oriented, 6bk8_RNA_only_Oriented.pdb Source: <https://pymolwiki.org/index.php/Modeling_and_Editing_Structures> """ m = cmd.get_view(0) ttt = [ m[0], m[1], m[2], 0.0, m[3], m[4], m[5], 0.0, m[6], m[7], m[8], 0.0, 0.0, 0.0, 0.0, 1.0 ] cmd.transform_object(object, ttt, transpose=1) cmd.save(file, object)
def main(): """ Center PDB and oritent the principal axes to x, y and x directions """ parser = argparse.ArgumentParser( description='Orient and center a molecule') parser.add_argument('pdb_file', help='Input file', metavar='molecule.pdb') parser.add_argument('-o', '--output', dest='output', help='Output filename', metavar='output.pdb') args = parser.parse_args() cmd = initialize_pymol(window=False) # cmd = initialize_pymol(window=True) cmd.set('retain_order', 1) cmd.load(args.pdb_file, object='molecule') # cmd.run('axes.py') rot_mat, com = inertia_tensor('molecule') # import inertia_tensor as it # rot_mat = it.tensor('molecule') # com = cmd.centerofmass('molecule') if numpy.linalg.det(rot_mat) < 0: reflect = numpy.matrix([[1, 0, 0], [0, -1, 0], [0, 0, 1]]) inverse = numpy.linalg.inv(numpy.array(reflect * rot_mat)) else: inverse = numpy.linalg.inv(numpy.array(rot_mat)) print(numpy.linalg.det(inverse)) transform = numpy.zeros((4, 4)) transform[:3, :3] = inverse transform[3, :3] = [-i for i in com] transform[3, 3] = 1 cmd.transform_object('molecule', matrix=transform.flatten()) if args.output: cmd.save(filename=args.output, selection='molecule')
def matrix_to_ttt(names, reverse=0, state=-1, quiet=1): ''' DESCRIPTION Objects can have state matrices and view (frames) matrices. This function takes the total matrix and stores it either as view matrix or as state matrix (reverse=1). For movie frames, movie_auto_store must be set. ''' from . import querying reverse, state, quiet = int(reverse), int(state), int(quiet) ostate = state for object in cmd.get_object_list('(' + names + ')'): if ostate < 1: state = querying.get_object_state(object) matrix = cmd.get_object_matrix(object, state) cmd.matrix_reset(object) if reverse: cmd.reset(object) cmd.transform_object(object, matrix, homogenous=1) else: cmd.set_object_ttt(object, matrix)
def matrix_to_ttt(names, reverse=0, state=-1, quiet=1): ''' DESCRIPTION Objects can have state matrices and view (frames) matrices. This function takes the total matrix and stores it either as view matrix or as state matrix (reverse=1). For movie frames, movie_auto_store must be set. ''' from . import querying reverse, state, quiet = int(reverse), int(state), int(quiet) ostate = state for object in cmd.get_object_list('(' + names + ')'): if ostate < 1: state = querying.get_object_state(object) matrix = cmd.get_object_matrix(object, state) for i in range(cmd.count_states(object)): cmd.matrix_reset(object, i + 1) if reverse: cmd.reset(object) cmd.transform_object(object, matrix, homogenous=1) else: cmd.set_object_ttt(object, matrix)
def symexpcell(prefix='mate', object=None, a=0, b=0, c=0,transformation=None,cutoff=None): ''' DESCRIPTION Creates all symmetry-related objects for the specified object that occur with their bounding box center within the unit cell. USAGE symexpcell prefix, object, [a, b, c] ARGUMENTS prefix = string: prefix of new objects object = string: object for which to create symmetry mates a, b, c = integer: create neighboring cell {default: 0,0,0} transformation = list: list of 16 floats giving the transformation matrix to apply to the generated symmetry mates {default: identity matrix} cutoff = int: restrict symmetry mates to within cutoff angstroms of the origin. Use 0 to generate all symmetry mates. {default: 0} SEE ALSO symexp, http://www.pymolwiki.org/index.php/SuperSym ''' #print "symexpcell %s,%s,%d,%d,%d,%s"%(prefix,object,int(a),int(b),int(c),transformation) if object is None: object = cmd.get_object_list()[0] if cutoff is not None: cutoff = int(cutoff) if cutoff <= 0: cutoff = None sym = cmd.get_symmetry(object) cell_edges = sym[0:3] cell_angles = sym[3:6] spacegroup = sym[6] basis = cellbasis(cell_angles, cell_edges) extent = cmd.get_extent(object) center = sum(numpy.array(extent)) * 0.5 center = numpy.append(center,1.0).reshape(4,1) center_cell = numpy.linalg.inv(basis) * center extra_shift = numpy.array([[float(i)] for i in (a,b,c)]) origin = numpy.array([[0,0,0,1]]).T if transformation is not None: transmat = transformation_to_numpy(transformation) #print "%s\n*\n%s\n=\n%s\n" % (origin,transmat, # numpy.dot(numpy.linalg.inv(transmat),origin) ) origin = numpy.dot(numpy.linalg.inv(transmat),origin) i = 0 matrices = xray.sg_sym_to_mat_list(spacegroup) for mat in matrices: i += 1 mat = numpy.array(mat) shift = numpy.floor(numpy.dot(mat, center_cell)) mat[0:3,3] -= shift[0:3,0] mat[0:3,3] += extra_shift[0:3,0] mat = numpy.dot(numpy.dot(basis, mat), numpy.linalg.inv(basis) ) mat_list = list(mat.flat) new_center = numpy.dot(mat,center) #print "%s\n* (%d)\n%s\n=\n%s\n" % (center,i,mat, new_center) if cutoff is not None: dist = new_center - origin dist = numpy.dot(dist.T,dist) if dist > cutoff**2: #print "Skipping %d%d%d_%d at distance %f" % (a,b,c,i,sqrt(dist)) continue name = '%s%d' % (prefix, i) cmd.create(name, object) cmd.transform_object(name, mat_list) # Apply extra transformation afterwards if transformation is not None: cmd.transform_object(name, transformation) cmd.color(i+1, name)
def quat(name=None, filename=None, prefix=None, quiet=0): ''' DESCRIPTION Read REMARK 350 from `filename` and create biological unit (quaternary structure) USAGE quat [name [, filename [, prefix]]] ARGUMENTS name = string: name of object and basename of PDB file, if filename is not given {default: first loaded object} filename = string: file path {default: <name>.pdb} prefix = string: prefix for new objects {default: <name>} EXAMPLE fetch 1rmv quat 1rmv ''' quiet = int(quiet) if name is None: name = cmd.get_object_list()[0] if prefix is None: prefix = name if filename is None: candidates = [ '%s.pdb' % (name), '%s/%s.pdb' % (cmd.get('fetch_path'), name), '%s/%s/pdb%s.ent.gz' % (local_mirror_divided, name[1:3], name), ] for filename in candidates: if os.path.exists(filename): break else: print 'please provide filename' return if not quiet: print 'loading from %s' % (filename) remarks = pdbremarks(filename) if 350 not in remarks: print 'There is no REMARK 350 in', filename return quat = quat350(remarks[350]) for chains in quat: matrices = quat[chains] for num in matrices: mat = matrices[num][0:12] mat.extend([0, 0, 0, 1]) copy = '%s_%d' % (prefix, num) if not quiet: print 'creating %s' % (copy) cmd.create(copy, '/%s//%s' % (name, '+'.join(chains))) cmd.alter(copy, 'segi="%d"' % (num)) cmd.transform_object(copy, mat) cmd.disable(name) cmd.group('%s_quat' % (prefix), '%s_*' % (prefix))
def tmalign(mobile, target, mobile_state=1, target_state=1, args='', exe='TMalign', ter=0, transform=1, object=None, quiet=0): ''' DESCRIPTION TMalign wrapper. You may also use this as a TMscore or MMalign wrapper if you privide the corresponding executable with the "exe" argument. Reference: Y. Zhang and J. Skolnick, Nucl. Acids Res. 2005 33, 2302-9 http://zhanglab.ccmb.med.umich.edu/TM-align/ ARGUMENTS mobile, target = string: atom selections mobile_state, target_state = int: object states {default: 1} args = string: Extra arguments like -d0 5 -L 100 exe = string: Path to TMalign (or TMscore, MMalign) executable {default: TMalign} ter = 0/1: If ter=0, then ignore chain breaks because TMalign will stop at first TER record {default: 0} ''' import subprocess, tempfile, os, re from .exporting import save_pdb_without_ter ter, quiet = int(ter), int(quiet) mobile_filename = tempfile.mktemp('.pdb', 'mobile') target_filename = tempfile.mktemp('.pdb', 'target') matrix_filename = tempfile.mktemp('.txt', 'matrix') mobile_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % (mobile) target_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % (target) if ter: save = cmd.save else: save = save_pdb_without_ter save(mobile_filename, mobile_ca_sele, state=mobile_state) save(target_filename, target_ca_sele, state=target_state) exe = cmd.exp_path(exe) args = [exe, mobile_filename, target_filename, '-m', matrix_filename] + args.split() try: process = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True) lines = process.stdout.readlines() except OSError: print('Cannot execute "%s", please provide full path to TMscore or TMalign executable' % (exe)) raise CmdException finally: os.remove(mobile_filename) os.remove(target_filename) # TMalign >= 2012/04/17 if os.path.exists(matrix_filename): lines += open(matrix_filename).readlines() os.remove(matrix_filename) r = None re_score = re.compile(r'TM-score\s*=\s*(\d*\.\d*)') rowcount = 0 matrix = [] line_it = iter(lines) headercheck = False alignment = [] for line in line_it: if 4 >= rowcount > 0: if rowcount >= 2: a = list(map(float, line.split())) matrix.extend(a[2:5]) matrix.append(a[1]) rowcount += 1 elif not headercheck and line.startswith(' * '): a = line.split(None, 2) if len(a) == 3: headercheck = a[1] elif line.lower().startswith(' -------- rotation matrix'): rowcount = 1 elif line.startswith('(":" denotes'): alignment = [next(line_it).rstrip() for i in range(3)] else: match = re_score.search(line) if match is not None: r = float(match.group(1)) if not quiet: print(line.rstrip()) if not quiet: for i in range(0, len(alignment[0])-1, 78): for line in alignment: print(line[i:i+78]) print('') assert len(matrix) == 3*4 matrix.extend([0,0,0,1]) if int(transform): for model in cmd.get_object_list('(' + mobile + ')'): cmd.transform_object(model, matrix, state=0, homogenous=1) # alignment object if object is not None: mobile_idx, target_idx = [], [] space = {'mobile_idx': mobile_idx, 'target_idx': target_idx} cmd.iterate_state(mobile_state, mobile_ca_sele, 'mobile_idx.append("%s`%d" % (model, index))', space=space) cmd.iterate_state(target_state, target_ca_sele, 'target_idx.append("%s`%d" % (model, index))', space=space) for i, aa in enumerate(alignment[0]): if aa == '-': mobile_idx.insert(i, None) for i, aa in enumerate(alignment[2]): if aa == '-': target_idx.insert(i, None) if (len(mobile_idx) == len(target_idx) == len(alignment[2])): cmd.rms_cur( ' '.join(idx for (idx, m) in zip(mobile_idx, alignment[1]) if m in ':.'), ' '.join(idx for (idx, m) in zip(target_idx, alignment[1]) if m in ':.'), cycles=0, matchmaker=4, object=object) else: print('Could not load alignment object') if not quiet: if headercheck: print('Finished Program:', headercheck) if r is not None: print('Found in output TM-score = %.4f' % (r)) return r
def biomolecule(name=None, filename=None, prefix=None, number=1, suffix=None, quiet=0): ''' DESCRIPTION Create biological unit (quaternary structure) as annotated by the REMARK 350 BIOMOLECULE record. USAGE biomolecule name [, filename [, prefix [, number ]]] ARGUMENTS name = string: name of object and basename of PDB file, if filename is not given {default: first loaded object} filename = string: file to read remarks from {default: <name>.pdb} prefix = string: prefix for new objects {default: <name>} EXAMPLE fetch 1rmv, async=0 biomolecule 1rmv ''' import os from .importing import local_mirror_pdb try: import numpy except ImportError: numpy = None number, quiet = int(number), int(quiet) if name is None: name = cmd.get_object_list()[0] if prefix is None: prefix = name if suffix is None: suffix = str(number) if filename is None: candidates = [ '%s.pdb' % (name), '%s/%s.pdb' % (cmd.get('fetch_path'), name), local_mirror_pdb(name), ] for filename in candidates: if os.path.exists(filename): break else: print('please provide filename') raise CmdException if not quiet: print('loading from %s' % (filename)) remarks = pdbremarks(filename) if 350 not in remarks: print('There is no REMARK 350 in ' + filename) raise CmdException current = 1 biomt = {current: {}} chains = tuple() for line in remarks[350]: if line.startswith('BIOMOLECULE:'): current = int(line[12:]) biomt[current] = {} elif line.startswith('APPLY THE FOLLOWING TO CHAINS:'): chains = tuple(chain.strip() for chain in line[30:].split(',')) elif line.startswith(' AND CHAINS:'): chains += tuple(chain.strip() for chain in line[30:].split(',')) elif line.startswith(' BIOMT'): row = int(line[7]) num = int(line[8:12]) vec = line[12:].split() vec = list(map(float, vec)) biomt[current].setdefault(chains, dict()).setdefault(num, []).extend(vec) if number not in biomt or len(biomt[number]) == 0: print(' Error: no BIOMOLECULE number %d' % (number)) raise CmdException if numpy is not None: mat_source = numpy.reshape(cmd.get_object_matrix(name), (4, 4)) mat_source = numpy.matrix(mat_source) for chains, matrices in biomt[number].items(): for num in matrices: mat = matrices[num][0:12] mat.extend([0, 0, 0, 1]) copy = '%s_%s_%d' % (prefix, suffix, num) if not quiet: print('creating %s' % (copy)) cmd.create(copy, 'model %s and chain %s' % (name, '+'.join(chains))) cmd.alter(copy, 'segi="%d"' % (num)) if numpy is not None: mat = mat_source * numpy.reshape(mat, (4, 4)) * mat_source.I mat = list(mat.flat) cmd.transform_object(copy, mat) cmd.disable(name) cmd.group('%s_%s' % (prefix, suffix), '%s_%s_*' % (prefix, suffix))
def pymol_xform(name, xform): from pymol import cmd assert name in cmd.get_object_list() cmd.transform_object(name, xform.flatten())
def xfit(mobile, target, mobile_state=-1, target_state=-1, load_b=0, cycles=10, match='align', guide=1, seed=0, quiet=1, bfit=0, distribution='student', _self=cmd): ''' DESCRIPTION Weighted superposition of the model in the first selection on to the model in the second selection. The weights are estimated with maximum likelihood. The result should be very similar to "theseus". Requires CSB, http://csb.codeplex.com ARGUMENTS mobile = string: atom selection target = string: atom selection mobile_state = int: object state of mobile selection {default: current} target_state = int: object state of target selection {default: current} load_b = 0 or 1: save -log(weights) into B-factor column {default: 0} SEE ALSO intra_xfit, align, super, fit, cealign, theseus ''' from numpy import asarray, identity, log, dot, zeros from csb.bio.utils import distance_sq, wfit, fit from . import querying cycles, quiet = int(cycles), int(quiet) mobile_state, target_state = int(mobile_state), int(target_state) mobile_obj = querying.get_object_name(mobile, 1) if mobile_state < 1: mobile_state = querying.get_object_state(mobile_obj) if target_state < 1: target_state = querying.get_selection_state(target) if int(guide): mobile = '(%s) and guide' % (mobile) target = '(%s) and guide' % (target) mm = MatchMaker(mobile, target, match) Y = asarray(querying.get_coords(mm.mobile, mobile_state)) X = asarray(querying.get_coords(mm.target, target_state)) if int(seed): R, t = identity(3), zeros(3) else: R, t = fit(X, Y) if int(bfit): # adapted from csb.apps.bfit from csb.bio.utils import distance, probabilistic_fit from csb.statistics.scalemixture import ScaleMixture mixture = ScaleMixture(scales=X.shape[0], prior=_bfit_get_prior(distribution), d=3) for _ in range(cycles): data = distance(Y, dot(X - t, R)) mixture.estimate(data) R, t = probabilistic_fit(X, Y, mixture.scales) scales = mixture.scales else: for _ in range(cycles): data = distance_sq(Y, dot(X - t, R)) scales = 1.0 / data.clip(1e-3) R, t = wfit(X, Y, scales) m = identity(4) m[0:3, 0:3] = R m[0:3, 3] = t cmd.transform_object(mobile_obj, list(m.flat)) if int(load_b): b_iter = iter(-log(scales)) cmd.alter(mm.mobile, 'b = b_iter.next()', space=locals()) if not quiet: print(' xfit: %d atoms aligned' % (len(X)))
def intra_xfit(selection, load_b=0, cycles=20, guide=1, seed=0, quiet=1, bfit=0, distribution='student', _self=cmd): ''' DESCRIPTION Weighted superposition of all states of an object to the intermediate structure over all states. The weights are estimated with maximum likelihood. The result should be very similar to "intra_theseus". Requires CSB, https://github.com/csb-toolbox/CSB ARGUMENTS selection = string: atom selection load_b = 0 or 1: save -log(weights) into B-factor column {default: 0} NOTE Assumes all states to have identical number of CA-atoms. SEE ALSO xfit, intra_fit, intra_theseus ''' from numpy import asarray, identity, log, dot, zeros from csb.bio.utils import wfit, fit from .querying import get_ensemble_coords, get_object_name cycles, quiet = int(cycles), int(quiet) mobile_obj = get_object_name(selection, 1) n_models = cmd.count_states(mobile_obj) if int(guide): selection = '(%s) and guide' % (selection) X = asarray(get_ensemble_coords(selection)) R, t = [identity(3)] * n_models, [zeros(3)] * n_models if int(bfit): # adapted from csb.apps.bfite from csb.bio.utils import average_structure, distance from csb.statistics.scalemixture import ScaleMixture average = average_structure(X) mixture = ScaleMixture(scales=X.shape[1], prior=_bfit_get_prior(distribution), d=3) for i in range(n_models): R[i], t[i] = fit(X[i], average) for _ in range(cycles): data = asarray([distance(average, dot(X[i] - t[i], R[i])) for i in range(n_models)]) mixture.estimate(data.T) for i in range(n_models): R[i], t[i] = wfit(X[i], average, mixture.scales) scales = mixture.scales else: if int(seed): ensemble = X else: ensemble = [] for i in range(n_models): R[i], t[i] = fit(X[i], X[0]) ensemble.append(dot(X[i] - t[i], R[i])) for _ in range(cycles): ensemble = asarray(ensemble) average = ensemble.mean(0) data = ensemble.var(0).sum(1) scales = 1.0 / data.clip(1e-3) ensemble = [] for i in range(n_models): R[i], t[i] = wfit(X[i], average, scales) ensemble.append(dot(X[i] - t[i], R[i])) m = identity(4) back = identity(4) back[0:3,0:3] = R[0] back[0:3,3] = t[0] for i in range(n_models): m[0:3,0:3] = R[i].T m[3,0:3] = -t[i] cmd.transform_object(mobile_obj, list(m.flat), state=i+1) # fit back to first state cmd.transform_object(mobile_obj, list(back.flat), state=0) if int(load_b): b_iter = iter(-log(scales)) cmd.alter(mm.mobile, 'b = next(b_iter)', space={'b_iter': b_iter, 'next': next}) if not quiet: print(' intra_xfit: %d atoms in %d states aligned' % (len(X[0]), n_models))
def intra_xfit(selection, load_b=0, cycles=20, guide=1, seed=0, quiet=1, bfit=0, distribution='student', _self=cmd): ''' DESCRIPTION Weighted superposition of all states of an object to the intermediate structure over all states. The weights are estimated with maximum likelihood. The result should be very similar to "intra_theseus". Requires CSB, https://github.com/csb-toolbox/CSB ARGUMENTS selection = string: atom selection load_b = 0 or 1: save -log(weights) into B-factor column {default: 0} NOTE Assumes all states to have identical number of CA-atoms. SEE ALSO xfit, intra_fit, intra_theseus ''' from numpy import asarray, identity, log, dot, zeros from csb.bio.utils import wfit, fit from .querying import get_ensemble_coords, get_object_name cycles, quiet = int(cycles), int(quiet) if int(guide): selection = '(%s) and guide' % (selection) mobile_objs = cmd.get_object_list(selection) n_states_objs = [] X = [] for obj in mobile_objs: X_obj = get_ensemble_coords('({}) & {}'.format(selection, obj)) if X and X_obj and len(X[0]) != len(X_obj[0]): raise CmdException('objects have different number of atoms') X.extend(X_obj) n_states_objs.append(len(X_obj)) n_models = len(X) X = asarray(X) R, t = [identity(3)] * n_models, [zeros(3)] * n_models if int(bfit): # adapted from csb.apps.bfite from csb.bio.utils import average_structure, distance from csb.statistics.scalemixture import ScaleMixture average = average_structure(X) mixture = ScaleMixture(scales=X.shape[1], prior=_bfit_get_prior(distribution), d=3) for i in range(n_models): R[i], t[i] = fit(X[i], average) for _ in range(cycles): data = asarray([ distance(average, dot(X[i] - t[i], R[i])) for i in range(n_models) ]) mixture.estimate(data.T) for i in range(n_models): R[i], t[i] = wfit(X[i], average, mixture.scales) scales = mixture.scales else: if int(seed): ensemble = X else: ensemble = [] for i in range(n_models): R[i], t[i] = fit(X[i], X[0]) ensemble.append(dot(X[i] - t[i], R[i])) for _ in range(cycles): ensemble = asarray(ensemble) average = ensemble.mean(0) data = ensemble.var(0).sum(1) scales = 1.0 / data.clip(1e-3) ensemble = [] for i in range(n_models): R[i], t[i] = wfit(X[i], average, scales) ensemble.append(dot(X[i] - t[i], R[i])) m = identity(4) back = identity(4) back[0:3, 0:3] = R[0] back[0:3, 3] = t[0] transformation_i = 0 for mobile_obj, n_states in zip(mobile_objs, n_states_objs): for state_i in range(n_states): m[0:3, 0:3] = R[transformation_i].T m[3, 0:3] = -t[transformation_i] cmd.transform_object(mobile_obj, list(m.flat), state=state_i + 1) transformation_i += 1 # fit back to first state cmd.transform_object(mobile_obj, list(back.flat), state=0) if int(load_b): b_iter = iter(-log(scales)) cmd.alter('({}) & {} & state 1'.format(selection, mobile_obj), 'b = next(b_iter)', space={ 'b_iter': b_iter, 'next': next }) if not quiet: print(' intra_xfit: %d atoms in %d states aligned' % (len(X[0]), n_models))
def biomolecule(name=None, filename=None, prefix=None, number=1, suffix=None, quiet=0): ''' DESCRIPTION Create biological unit (quaternary structure) as annotated by the REMARK 350 BIOMOLECULE record. USAGE biomolecule name [, filename [, prefix [, number ]]] ARGUMENTS name = string: name of object and basename of PDB file, if filename is not given {default: first loaded object} filename = string: file to read remarks from {default: <name>.pdb} prefix = string: prefix for new objects {default: <name>} EXAMPLE fetch 1rmv, async=0 biomolecule 1rmv ''' import os from .importing import local_mirror_pdb try: import numpy except ImportError: numpy = None number, quiet = int(number), int(quiet) if name is None: name = cmd.get_object_list()[0] if prefix is None: prefix = name if suffix is None: suffix = str(number) if filename is None: candidates = [ '%s.pdb' % (name), '%s/%s.pdb' % (cmd.get('fetch_path'), name), local_mirror_pdb(name), ] for filename in candidates: if os.path.exists(filename): break else: print('please provide filename') raise CmdException if not quiet: print('loading from %s' % (filename)) remarks = pdbremarks(filename) if 350 not in remarks: print('There is no REMARK 350 in', filename) raise CmdException current = 1 biomt = {current: {}} chains = tuple() for line in remarks[350]: if line.startswith('BIOMOLECULE:'): current = int(line[12:]) biomt[current] = {} elif line.startswith('APPLY THE FOLLOWING TO CHAINS:'): chains = tuple(chain.strip() for chain in line[30:].split(',')) elif line.startswith(' AND CHAINS:'): chains += tuple(chain.strip() for chain in line[30:].split(',')) elif line.startswith(' BIOMT'): row = int(line[7]) num = int(line[8:12]) vec = line[12:].split() vec = list(map(float, vec)) biomt[current].setdefault(chains, dict()).setdefault(num, []).extend(vec) if number not in biomt or len(biomt[number]) == 0: print(' Error: no BIOMOLECULE number %d' % (number)) raise CmdException if numpy is not None: mat_source = numpy.reshape(cmd.get_object_matrix(name), (4,4)) mat_source = numpy.matrix(mat_source) for chains, matrices in biomt[number].items(): for num in matrices: mat = matrices[num][0:12] mat.extend([0,0,0,1]) copy = '%s_%s_%d' % (prefix, suffix, num) if not quiet: print('creating %s' % (copy)) cmd.create(copy, 'model %s and chain %s' % (name, '+'.join(chains))) cmd.alter(copy, 'segi="%d"' % (num)) if numpy is not None: mat = mat_source * numpy.reshape(mat, (4,4)) * mat_source.I mat = list(mat.flat) cmd.transform_object(copy, mat) cmd.disable(name) cmd.group('%s_%s' % (prefix, suffix), '%s_%s_*' % (prefix, suffix))
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)
def transform_object(self, trtm): cmd.transform_object(Registry.get(self, "name"), trtm.convert_to_flat_pymol_matrix())
def intra_xfit(selection, load_b=0, cycles=20, guide=1, seed=0, quiet=1, bfit=0, distribution='student', _self=cmd): ''' DESCRIPTION Weighted superposition of all states of an object to the intermediate structure over all states. The weights are estimated with maximum likelihood. The result should be very similar to "intra_theseus". Requires CSB, http://csb.codeplex.com ARGUMENTS selection = string: atom selection load_b = 0 or 1: save -log(weights) into B-factor column {default: 0} NOTE Assumes all states to have identical number of CA-atoms. SEE ALSO xfit, intra_fit, intra_theseus ''' from numpy import asarray, identity, log, dot, zeros from csb.bio.utils import wfit, fit from .querying import get_ensemble_coords, get_object_name cycles, quiet = int(cycles), int(quiet) mobile_obj = get_object_name(selection, 1) n_models = cmd.count_states(mobile_obj) if int(guide): selection = '(%s) and guide' % (selection) X = asarray(get_ensemble_coords(selection)) R, t = [identity(3)] * n_models, [zeros(3)] * n_models if int(bfit): # adapted from csb.apps.bfite from csb.bio.utils import average_structure, distance from csb.statistics.scalemixture import ScaleMixture average = average_structure(X) mixture = ScaleMixture(scales=X.shape[1], prior=_bfit_get_prior(distribution), d=3) for i in range(n_models): R[i], t[i] = fit(X[i], average) for _ in range(cycles): data = asarray([ distance(average, dot(X[i] - t[i], R[i])) for i in range(n_models) ]) mixture.estimate(data.T) for i in range(n_models): R[i], t[i] = wfit(X[i], average, mixture.scales) scales = mixture.scales else: if int(seed): ensemble = X else: ensemble = [] for i in range(n_models): R[i], t[i] = fit(X[i], X[0]) ensemble.append(dot(X[i] - t[i], R[i])) for _ in range(cycles): ensemble = asarray(ensemble) average = ensemble.mean(0) data = ensemble.var(0).sum(1) scales = 1.0 / data.clip(1e-3) ensemble = [] for i in range(n_models): R[i], t[i] = wfit(X[i], average, scales) ensemble.append(dot(X[i] - t[i], R[i])) m = identity(4) back = identity(4) back[0:3, 0:3] = R[0] back[0:3, 3] = t[0] for i in range(n_models): m[0:3, 0:3] = R[i].T m[3, 0:3] = -t[i] cmd.transform_object(mobile_obj, list(m.flat), state=i + 1) # fit back to first state cmd.transform_object(mobile_obj, list(back.flat), state=0) if int(load_b): b_iter = iter(-log(scales)) cmd.alter(selection, 'b = b_iter.next()', space=locals()) if not quiet: print(' intra_xfit: %d atoms in %d states aligned' % (len(X[0]), n_models))
def symexpcell(prefix='mate', object=None, a=0, b=0, c=0): ''' DESCRIPTION Creates all symmetry-related objects for the specified object that occur with their bounding box center within the unit cell. USAGE symexpcell prefix, object, [a, b, c] ARGUMENTS prefix = string: prefix of new objects object = string: object for which to create symmetry mates a, b, c = integer: create neighboring cell {default: 0,0,0} SEE ALSO symexp ''' import numpy from pymol import xray if object is None: object = cmd.get_object_list()[0] sym = cmd.get_symmetry(object) cell_edges = sym[0:3] cell_angles = sym[3:6] spacegroup = sym[6] basis = cellbasis(cell_angles, cell_edges) basis = numpy.matrix(basis) extent = cmd.get_extent(object) center = sum(numpy.array(extent)) * 0.5 center = numpy.matrix(center.tolist() + [1.0]).T center_cell = basis.I * center spacegroup = xray.space_group_map.get(spacegroup, spacegroup) i = 0 matrices = xray.sg_sym_to_mat_list(spacegroup) for mat in matrices: i += 1 mat = numpy.matrix(mat) shift = -numpy.floor(numpy.array(mat * center_cell)[0:3, 0]) shift = shift.flatten().astype(int) shift += [a, b, c] mat[0:3, 3] += shift.reshape((3, 1)) mat = basis * mat * basis.I mat_list = list(mat.flat) name = '%s%d' % (prefix, i) cmd.create(name, object) cmd.transform_object(name, mat_list, 0) cmd.set_title(name, 1, "{}_{}{}{}".format(i, *(shift + 5).tolist())) if len(matrices) > 1: cmd.color(i + 1, name)
def xfit(mobile, target, mobile_state=-1, target_state=-1, load_b=0, cycles=10, match='align', guide=1, seed=0, quiet=1, bfit=0, distribution='student', _self=cmd): ''' DESCRIPTION Weighted superposition of the model in the first selection on to the model in the second selection. The weights are estimated with maximum likelihood. The result should be very similar to "theseus". Requires CSB, https://github.com/csb-toolbox/CSB ARGUMENTS mobile = string: atom selection target = string: atom selection mobile_state = int: object state of mobile selection {default: current} target_state = int: object state of target selection {default: current} load_b = 0 or 1: save -log(weights) into B-factor column {default: 0} SEE ALSO intra_xfit, align, super, fit, cealign, theseus ''' from numpy import asarray, identity, log, dot, zeros from csb.bio.utils import distance_sq, wfit, fit from . import querying cycles, quiet = int(cycles), int(quiet) mobile_state, target_state = int(mobile_state), int(target_state) mobile_obj = querying.get_object_name(mobile, 1) if mobile_state < 1: mobile_state = querying.get_object_state(mobile_obj) if target_state < 1: target_state = querying.get_selection_state(target) if int(guide): mobile = '(%s) and guide' % (mobile) target = '(%s) and guide' % (target) mm = MatchMaker(mobile, target, match) Y = asarray(querying.get_coords(mm.mobile, mobile_state)) X = asarray(querying.get_coords(mm.target, target_state)) if int(seed): R, t = identity(3), zeros(3) else: R, t = fit(X, Y) if int(bfit): # adapted from csb.apps.bfit from csb.bio.utils import distance, probabilistic_fit from csb.statistics.scalemixture import ScaleMixture mixture = ScaleMixture(scales=X.shape[0], prior=_bfit_get_prior(distribution), d=3) for _ in range(cycles): data = distance(Y, dot(X - t, R)) mixture.estimate(data) R, t = probabilistic_fit(X, Y, mixture.scales) scales = mixture.scales else: for _ in range(cycles): data = distance_sq(Y, dot(X - t, R)) scales = 1.0 / data.clip(1e-3) R, t = wfit(X, Y, scales) m = identity(4) m[0:3,0:3] = R m[0:3,3] = t cmd.transform_object(mobile_obj, list(m.flat)) if int(load_b): b_iter = iter(-log(scales)) cmd.alter(mm.mobile, 'b = next(b_iter)', space={'b_iter': b_iter, 'next': next}) if not quiet: print(' xfit: %d atoms aligned' % (len(X)))
def quat(name=None, filename=None, prefix=None, quiet=0): ''' DESCRIPTION Read REMARK 350 from `filename` and create biological unit (quaternary structure) USAGE quat [name [, filename [, prefix]]] ARGUMENTS name = string: name of object and basename of PDB file, if filename is not given {default: first loaded object} filename = string: file path {default: <name>.pdb} prefix = string: prefix for new objects {default: <name>} EXAMPLE fetch 1rmv quat 1rmv ''' quiet = int(quiet) if name is None: name = cmd.get_object_list()[0] if prefix is None: prefix = name if filename is None: candidates = [ '%s.pdb' % (name), '%s/%s.pdb' % (cmd.get('fetch_path'), name), '%s/%s/pdb%s.ent.gz' % (local_mirror_divided, name[1:3], name), ] for filename in candidates: if os.path.exists(filename): break else: print 'please provide filename' return if not quiet: print 'loading from %s' % (filename) remarks = pdbremarks(filename) if 350 not in remarks: print 'There is no REMARK 350 in', filename return quat = quat350(remarks[350]) for chains in quat: matrices = quat[chains] for num in matrices: mat = matrices[num][0:12] mat.extend([0,0,0,1]) copy = '%s_%d' % (prefix, num) if not quiet: print 'creating %s' % (copy) cmd.create(copy, '/%s//%s' % (name, '+'.join(chains))) cmd.alter(copy, 'segi="%d"' % (num)) cmd.transform_object(copy, mat) cmd.disable(name) cmd.group('%s_quat' % (prefix), '%s_*' % (prefix))
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 tmalign(mobile, target, mobile_state=1, target_state=1, args='', exe='TMalign', ter=0, transform=1, object=None, quiet=0): ''' DESCRIPTION TMalign wrapper. You may also use this as a TMscore or MMalign wrapper if you privide the corresponding executable with the "exe" argument. Reference: Y. Zhang and J. Skolnick, Nucl. Acids Res. 2005 33, 2302-9 http://zhanglab.ccmb.med.umich.edu/TM-align/ ARGUMENTS mobile, target = string: atom selections mobile_state, target_state = int: object states {default: 1} args = string: Extra arguments like -d0 5 -L 100 exe = string: Path to TMalign (or TMscore, MMalign) executable {default: TMalign} ter = 0/1: If ter=0, then ignore chain breaks because TMalign will stop at first TER record {default: 0} ''' import subprocess, tempfile, os, re from .exporting import save_pdb_without_ter ter, quiet = int(ter), int(quiet) mobile_filename = tempfile.mktemp('.pdb', 'mobile') target_filename = tempfile.mktemp('.pdb', 'target') matrix_filename = tempfile.mktemp('.txt', 'matrix') mobile_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % (mobile) target_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % (target) if ter: save = cmd.save else: save = save_pdb_without_ter save(mobile_filename, mobile_ca_sele, state=mobile_state) save(target_filename, target_ca_sele, state=target_state) exe = cmd.exp_path(exe) args = [exe, mobile_filename, target_filename, '-m', matrix_filename ] + args.split() try: process = subprocess.Popen(args, stdout=subprocess.PIPE) lines = process.stdout.readlines() except OSError: print( 'Cannot execute "%s", please provide full path to TMscore or TMalign executable' % (exe)) raise CmdException finally: os.remove(mobile_filename) os.remove(target_filename) # TMalign >= 2012/04/17 if os.path.exists(matrix_filename): lines += open(matrix_filename).readlines() os.remove(matrix_filename) r = None re_score = re.compile(r'TM-score\s*=\s*(\d*\.\d*)') rowcount = 0 matrix = [] line_it = iter(lines) headercheck = False alignment = [] for line in line_it: if 4 >= rowcount > 0: if rowcount >= 2: a = list(map(float, line.split())) matrix.extend(a[2:5]) matrix.append(a[1]) rowcount += 1 elif not headercheck and line.startswith(' * '): a = line.split(None, 2) if len(a) == 3: headercheck = a[1] elif line.lower().startswith(' -------- rotation matrix'): rowcount = 1 elif line.startswith('(":" denotes'): alignment = [line_it.next().rstrip() for i in range(3)] else: match = re_score.search(line) if match is not None: r = float(match.group(1)) if not quiet: print(line.rstrip()) if not quiet: for i in range(0, len(alignment[0]) - 1, 78): for line in alignment: print(line[i:i + 78]) print('') assert len(matrix) == 3 * 4 matrix.extend([0, 0, 0, 1]) if int(transform): for model in cmd.get_object_list('(' + mobile + ')'): cmd.transform_object(model, matrix, state=0, homogenous=1) # alignment object if object is not None: mobile_idx, target_idx = [], [] space = {'mobile_idx': mobile_idx, 'target_idx': target_idx} cmd.iterate(mobile_ca_sele, 'mobile_idx.append("%s`%d" % (model, index))', space=space) cmd.iterate(target_ca_sele, 'target_idx.append("%s`%d" % (model, index))', space=space) for i, aa in enumerate(alignment[0]): if aa == '-': mobile_idx.insert(i, None) for i, aa in enumerate(alignment[2]): if aa == '-': target_idx.insert(i, None) if (len(mobile_idx) == len(target_idx) == len(alignment[2])): cmd.rms_cur(' '.join(idx for (idx, m) in zip(mobile_idx, alignment[1]) if m in ':.'), ' '.join(idx for (idx, m) in zip(target_idx, alignment[1]) if m in ':.'), cycles=0, matchmaker=4, object=object) else: print('Could not load alignment object') if not quiet: if headercheck: print('Finished Program:', headercheck) if r is not None: print('Found in output TM-score = %.4f' % (r)) return r