import multiprocessing
from rdkit import Chem
from rdkit.Chem.Pharm2D import Generate
[docs]def compute_anti_fp(mols_smiles, sig_fac, antifp_old=None):
"""
Computes an anti-fingerprint from the given molecules.
It is possible to specify an existing anti-fingerprint
for an update. In this case, the returned fingerprint
will be the result of doing a bitwise :samp:`or` between
the old fingerprint and the one generated from the
supplied structures.
:param mols_smiles: SMILES of the molecules to generate the anti-fingerprint from
:param sig_fac: RDKit's signature factory used in the 2D pharmacophore fingerprint computation
:param antifp_old: an old anti-fingerprint to update
:return: new or updated anti-fingerprint
"""
antifp_new = antifp_old
for smiles in mols_smiles:
mol = Chem.MolFromSmiles(smiles)
if not antifp_new:
antifp_new = Generate.Gen2DFingerprint(mol, sig_fac)
else:
antifp_new = antifp_new | Generate.Gen2DFingerprint(mol, sig_fac)
return antifp_new
def _eval_morphs(mols, anti_fp, sig_fac):
path_fp = compute_anti_fp(mols, sig_fac)
common_fp = path_fp & anti_fp
on_bits = path_fp.GetNumOnBits()
common_bits = common_fp.GetNumOnBits()
common_bits_perc = common_bits / on_bits if on_bits else 0.0
assert common_bits_perc <= 1.0
return common_bits_perc
def _compute_antifp_score(data):
smiles, anti_fp = data
return smiles, _eval_morphs([smiles], anti_fp, _compute_antifp_score.sig_fac)
[docs]def compute_antifp_scores(mols, anti_fp, settings):
"""
Computes (in parallel) the anti-fingerprint scores
for the given molecules.
:param mols: molecules as a list of SMILES strings
:param anti_fp: the anti-fingerprint
:param settings: `AntidecoysSettings`
:return: a `dict` mapping SMILES of the given molecules to the anti-fingerprint scores
"""
data = [(x.smiles, anti_fp) for x in mols]
_compute_antifp_score.sig_fac = settings.signature_factory # RDKit's signature factory cannot be pickled; hence, this dirty hack
pool = multiprocessing.Pool(settings.max_threads)
results = pool.map(func=_compute_antifp_score, iterable=data)
pool.close()
pool.join()
return dict(results)
[docs]def update_target(tree, target):
"""
Change the tree's target molecule.
:param tree: an `exploration tree`
:type tree: :class:`~molpher.core.ExplorationTree.ExplorationTree`
:param target: SMILES string of the new target
:type target: `str`
"""
if target != tree.params['source']:
tree.params = {
'target' : target
}