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 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, _self=_self) if mobile_state < 1: mobile_state = querying.get_object_state(mobile_obj, _self=_self) if target_state < 1: target_state = querying.get_selection_state(target, _self=_self) if int(guide): mobile = '(%s) and guide' % (mobile) target = '(%s) and guide' % (target) mm = MatchMaker(mobile, target, match, _self=_self) Y = asarray(_self.get_coords(mm.mobile, mobile_state)) X = asarray(_self.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 _self.transform_object(mobile_obj, list(m.flat)) if int(load_b): b_iter = iter(-log(scales)) _self.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 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 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)