66import joblib
77import numpy as np
88from rdkit import Chem , RDLogger
9- from rdkit .Chem import AllChem , Descriptors
9+ from rdkit .Chem import QED , AllChem , Descriptors
1010
1111from moldrug import utils
1212from moldrug .fitness import _vinadock
1515
1616
1717class Featurizer :
18- def __init__ (self , fpb = 2048 , calc_descriptors = True , scale = False ):
18+ def __init__ (self , fpb = 2048 , calc_descriptors = True , scale = False ):
1919 """
2020 :param fpb: number of Morgan bits
2121 :param descriptors: boolean - calculate descriptors.
@@ -118,25 +118,26 @@ def predict(self, molecule):
118118
119119 return to_return
120120
121+
121122def Cost (
122- Individual :utils .Individual ,
123- wd :str = '.vina_jobs' ,
124- vina_executable :str = 'vina' ,
125- receptor_pdbqt_path :str = None ,
126- boxcenter :List [float ] = None ,
127- boxsize :List [float ] = None ,
128- exhaustiveness :int = 8 ,
129- ad4map :str = None ,
130- ncores :int = 1 ,
131- num_modes :int = 1 ,
132- constraint :bool = False ,
133- constraint_type = 'score_only' , # score_only, local_only
134- constraint_ref :Chem .rdchem .Mol = None ,
135- constraint_receptor_pdb_path :str = None ,
136- constraint_num_conf :int = 100 ,
137- constraint_minimum_conf_rms :int = 0.01 ,
138- models :Dict = None ,
139- desirability :Dict = None ,
123+ Individual : utils .Individual ,
124+ wd : str = '.vina_jobs' ,
125+ vina_executable : str = 'vina' ,
126+ receptor_pdbqt_path : str = None ,
127+ boxcenter : List [float ] = None ,
128+ boxsize : List [float ] = None ,
129+ exhaustiveness : int = 8 ,
130+ ad4map : str = None ,
131+ ncores : int = 1 ,
132+ num_modes : int = 1 ,
133+ constraint : bool = False ,
134+ constraint_type : str = 'score_only' , # score_only, local_only
135+ constraint_ref : Chem .rdchem .Mol = None ,
136+ constraint_receptor_pdb_path : str = None ,
137+ constraint_num_conf : int = 100 ,
138+ constraint_minimum_conf_rms : int = 0.01 ,
139+ models : Dict = None ,
140+ desirability : Dict = None
140141 ):
141142 """
142143 This is the main Cost function of the module. It use the concept of desirability functions. The response variables are:
@@ -197,7 +198,7 @@ def Cost(
197198 must be the same as in desirability. In case that provided more models than hppb and clearance
198199 the same must be done in desirability.
199200 desirability : dict, optional
200- The definition of the desirability to use for each used variable = [qed, sa_score, vina_score].
201+ The definition of the desirability to use for each used variable = [hppb, clearance, qed, sa_score, vina_score].
201202 Each variable only will accept the keys [w, and the name of the desirability function of :meth:`moldrug.utils.DerringerSuichDesirability`],
202203 by default None which means that it will be used:
203204 desirability = {
@@ -218,18 +219,13 @@ def Cost(
218219 pdbqt, qed, vina_score, sa_score and cost.
219220 cost attribute will be a number between 0 and 1, been 0 the optimal value.
220221 """
221- if not models :
222- models = {
223- 'hppb' : 'hppb.jlib' ,
224- 'clearance' : 'clearance.jlib' ,
225- }
226- if not desirability :
227- desirability = {
222+
223+ internal_default_desirability = {
228224 'hppb' : {
229225 'w' : 1 ,
230226 'LargerTheBest' : {
231227 'LowerLimit' : 25 ,
232- 'Target' :75 ,
228+ 'Target' : 75 ,
233229 'r' : 1
234230 }
235231 },
@@ -241,60 +237,89 @@ def Cost(
241237 'r' : 1
242238 }
243239 },
240+ # Definitions of extra properties
241+ # Those that are not jlib models
244242 'vina_score' : {
245243 'w' : 1 ,
246244 'SmallerTheBest' : {
247245 'Target' : - 12 ,
248246 'UpperLimit' : - 6 ,
249247 'r' : 1
250248 }
251- }
249+ },
250+ 'qed' : {
251+ 'w' : 1 ,
252+ 'LargerTheBest' : {
253+ 'LowerLimit' : 0.1 ,
254+ 'Target' : 0.75 ,
255+ 'r' : 1
256+ }
257+ },
258+ 'sa_score' : {
259+ 'w' : 1 ,
260+ 'SmallerTheBest' : {
261+ 'Target' : 3 ,
262+ 'UpperLimit' : 7 ,
263+ 'r' : 1
264+ }
265+ },
252266 }
253- # Check that everything is ok with naming in models and desirability
254- diff = list (set (desirability ) - set (models ))
255- if len (diff ) == 0 :
256- # vina_score was not defined. the default values will be used.
257- desirability ['vina_score' ] = {
258- 'w' : 1 ,
259- 'SmallerTheBest' : {
260- 'Target' : - 12 ,
261- 'UpperLimit' : - 6 ,
262- 'r' : 1
263- }
267+
268+ internal_default_models = {
269+ 'hppb' : 'hppb.jlib' ,
270+ 'clearance' : 'clearance.jlib' ,
264271 }
272+
273+ if desirability is None :
274+ desirability = internal_default_desirability
265275 else :
266- if len (diff ) != 1 :
267- raise Exception (f"You provided models = { models .keys ()} and desirability = { desirability .keys ()} . " \
268- "However, desirability must have the same keywords as models and optionally the keyword vina_score" )
269- elif diff [0 ] != 'vina_score' :
270- raise Exception (f"desirability has the keyword: '{ diff [0 ]} ' which is not defined in models = { models .keys ()} and is not vina_score" )
276+ desirability = utils .deep_update (
277+ target_dict = internal_default_desirability ,
278+ update_dict = desirability
279+ )
280+
281+ if models is None :
282+ models = internal_default_models
283+
284+ for model in models .keys ():
285+ if model not in desirability .keys ():
286+ raise ValueError (f"Model { model } was not defined in the desirability" )
271287
272288 # Getting and setting properties on the Individual
289+
290+ # ### JLIB modelss # ###
273291 predictor = Predictors (featurizer = Featurizer (), models = models .values ())
274292
275293 # MUST be a copy of Individual.mol becasue if not creazy stuffs will happen!!
276294 predictions = predictor .predict (deepcopy (Individual .mol ))
277295 _ = [setattr (Individual , name , value ) for name , value in zip (models , predictions )]
278296
297+ # ### Non-JLIB properties # ###
298+ sascorer = utils .import_sascorer ()
299+ # Getting estimate of drug-likness
300+ Individual .qed = QED .weights_mean (Chem .RemoveHs (Individual .mol ))
301+
302+ # Getting synthetic accessibility score
303+ Individual .sa_score = sascorer .calculateScore (Chem .RemoveHs (Individual .mol ))
279304
280305 # Getting vina_score and update pdbqt
281306 Individual .vina_score , Individual .pdbqt = _vinadock (
282- Individual = Individual ,
283- wd = wd ,
284- vina_executable = vina_executable ,
285- receptor_pdbqt_path = receptor_pdbqt_path ,
286- boxcenter = boxcenter ,
287- boxsize = boxsize ,
288- exhaustiveness = exhaustiveness ,
289- ad4map = ad4map ,
290- ncores = ncores ,
291- num_modes = num_modes ,
292- constraint = constraint ,
293- constraint_type = constraint_type ,
294- constraint_ref = constraint_ref ,
295- constraint_receptor_pdb_path = constraint_receptor_pdb_path ,
296- constraint_num_conf = constraint_num_conf ,
297- constraint_minimum_conf_rms = constraint_minimum_conf_rms ,
307+ Individual = Individual ,
308+ wd = wd ,
309+ vina_executable = vina_executable ,
310+ receptor_pdbqt_path = receptor_pdbqt_path ,
311+ boxcenter = boxcenter ,
312+ boxsize = boxsize ,
313+ exhaustiveness = exhaustiveness ,
314+ ad4map = ad4map ,
315+ ncores = ncores ,
316+ num_modes = num_modes ,
317+ constraint = constraint ,
318+ constraint_type = constraint_type ,
319+ constraint_ref = constraint_ref ,
320+ constraint_receptor_pdb_path = constraint_receptor_pdb_path ,
321+ constraint_num_conf = constraint_num_conf ,
322+ constraint_minimum_conf_rms = constraint_minimum_conf_rms ,
298323 )
299324 # Adding the cost using all the information of qed, sas and vina_cost
300325 # Construct the desirability
@@ -309,12 +334,12 @@ def Cost(
309334 elif key in utils .DerringerSuichDesirability ():
310335 d = utils .DerringerSuichDesirability ()[key ](getattr (Individual , variable ), ** desirability [variable ][key ])
311336 else :
312- raise RuntimeError (f"Inside the desirability dictionary you provided for the variable = { variable } " \
313- f"a non implemented key = { key } . Only are possible: 'w' (standing for weight) and any " \
314- f"possible Derringer-Suich desirability function: { utils .DerringerSuichDesirability ().keys ()} " )
337+ raise RuntimeError (f"Inside the desirability dictionary you provided for the variable = { variable } "
338+ f"a non implemented key = { key } . Only are possible: 'w' (standing for weight) and any "
339+ f"possible Derringer-Suich desirability function: { utils .DerringerSuichDesirability ().keys ()} " )
315340 base *= d ** w
316341 exponent += w
317342
318343 # We are using a geometric mean. And because we are minimizing we have to return
319344 Individual .cost = 1 - base ** (1 / exponent )
320- return Individual
345+ return Individual
0 commit comments