fragmenstein/multivictor/multivictor.py
import copy
import random
from typing import Optional, Dict, Union
from rdkit import Chem
from fragmenstein import Victor
class MultiVictorPlacement():
"""
MultiVictorPlacement is a class to execute multiple times victor.place over the same smile using different seeds.
The idea is to be able to do something more like docking for those cases in which the parent hits do not
explain an important part of the molecule
"""
def __init__(self, random_seed=None, **victor_init_args):
self.random_seed = random_seed
self.victor_init_args = victor_init_args
self.placed_victors = []
def place(self, smiles: str, number_runs: int= 10,
long_name: str = 'ligand',
merging_mode='expansion',
atomnames: Optional[Dict[int, str]] = None,
custom_map: Optional[Dict[str, Dict[int, int]]] = None,
extra_ligand_constraint: Union[str] = None):
"""
Places a followup (smiles) into the protein based upon the hits. Obtains number_runs solutions.
:param smiles: smiles of followup, optionally covalent (_e.g._ ``*CC(=O)CCC``)
:param number_runs: the number of Victor objects to create and place the smiles
:param long_name: gets used for filenames so will get corrected
:param merging_mode:
:param atomnames: an optional dictionary that gets used by ``Params.from_smiles``
:param custom_map: see Monster.place
:param extra_ligand_constraint:
:return:
"""
assert number_runs >= 1, "Error, at least one placement required"
current_randomState = None
if self.random_seed:
current_randomState = random.getstate()
random.seed(self.random_seed)
rseeds = [random.randint(0, int(1e6)) for i in range(number_runs)]
if current_randomState is not None:
random.setstate(current_randomState)
i = 0
victor = Victor(monster_random_seed=rseeds[i], **self.victor_init_args)
victor.place(smiles, long_name=long_name+str(i), merging_mode= merging_mode,
custom_map=custom_map, atomnames=atomnames,
extra_ligand_constraint=extra_ligand_constraint)
victor.runNumber = i
ddG = victor.ddG
monster = victor.monster
self.placed_victors = [(ddG, victor)]
for i in range(1, number_runs):
monster.sample_new_conformation(rseeds[i])
victor = Victor(monster_random_seed=rseeds[i], **self.victor_init_args)
victor._prepare_args_for_placement(smiles=smiles, long_name = long_name+str(i), merging_mode= merging_mode,
custom_map=custom_map,
atomnames=atomnames, extra_ligand_constraint=extra_ligand_constraint)
victor.monster = monster
victor._calculate_placement_thermo()
self.placed_victors += [(victor.ddG, victor)]
self.placed_victors = sorted(self.placed_victors)
def retrieve_best_victor(self):
return self.placed_victors[0][1]
def retrieve_scores(self):
return list(zip(*self.placed_victors))[0]