Skip to content

Commit f0feecc

Browse files
committed
Fix # 14
1 parent 4a6cfe6 commit f0feecc

4 files changed

Lines changed: 162 additions & 138 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ vina
3434
streamlit/test/moldrug-dashboard.py
3535

3636
Contrib/MP
37+
*.jlib
3738

3839
.venv
3940
vina*_linux_x86_64

Contrib/MolSkill/fitness_molskill.py

Lines changed: 47 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,23 @@
1212

1313

1414
def Cost(
15-
Individual:utils.Individual,
16-
wd:str = '.vina_jobs',
17-
vina_executable:str = 'vina',
18-
receptor_pdbqt_path:str = None,
19-
boxcenter:List[float] = None,
20-
boxsize:List[float] = None,
21-
exhaustiveness:int = 8,
22-
ad4map:str = None,
23-
ncores:int = 1,
24-
num_modes:int = 1,
25-
constraint:bool = False,
26-
constraint_type:str = 'score_only', # score_only, local_only
27-
constraint_ref:Chem.rdchem.Mol = None,
28-
constraint_receptor_pdb_path:str = None,
29-
constraint_num_conf:int = 100,
30-
constraint_minimum_conf_rms:int = 0.01,
31-
desirability:Dict = None,
15+
Individual: utils.Individual,
16+
wd: str = '.vina_jobs',
17+
vina_executable: str = 'vina',
18+
receptor_pdbqt_path: str = None,
19+
boxcenter: List[float] = None,
20+
boxsize: List[float] = None,
21+
exhaustiveness: int = 8,
22+
ad4map: str = None,
23+
ncores: int = 1,
24+
num_modes: int = 1,
25+
constraint: bool = False,
26+
constraint_type: str = 'score_only', # score_only, local_only
27+
constraint_ref: Chem.rdchem.Mol = None,
28+
constraint_receptor_pdb_path: str = None,
29+
constraint_num_conf: int = 100,
30+
constraint_minimum_conf_rms: int = 0.01,
31+
desirability: Dict = None,
3232
):
3333
"""
3434
This is the main Cost function of the module. It use the concept of desirability functions. The response variables are:
@@ -95,28 +95,26 @@ def Cost(
9595
-------
9696
utils.Individual
9797
A new instance of the original Individual with the the new attributes:
98-
pdbqt, qed, vina_score, sa_score and cost.
98+
pdbqt, molskill_score, vina_score, sa_score and cost.
9999
cost attribute will be a number between 0 and 1, been 0 the optimal value.
100100
Example
101101
-------
102102
.. ipython:: python
103103
104-
from moldrug import utils, fitness
104+
from moldrug import utils
105+
import fitness_molskill as fitness
105106
from rdkit import Chem
106107
import tempfile, os
107-
from moldrug.data import ligands, boxes, receptor_pdbqt
108+
from moldrug.data import get_data
108109
tmp_path = tempfile.TemporaryDirectory()
109-
ligand_mol = Chem.MolFromSmiles(ligands.r_x0161)
110+
data_x0161 = get_data('x0161')
111+
ligand_mol = Chem.MolFromSmiles(data_x0161['smiles'])
110112
I = utils.Individual(ligand_mol)
111-
receptor_path = os.path.join(tmp_path.name,'receptor.pdbqt')
112-
with open(receptor_path, 'w') as r: r.write(receptor_pdbqt.r_x0161)
113-
box = boxes.r_x0161['A']
113+
box = data_x0161['box']
114114
# Using the default desirability
115-
NewI = fitness.Cost(
116-
Individual = I,wd = tmp_path.name,
117-
receptor_pdbqt_path = receptor_path,boxcenter = box['boxcenter'],
118-
boxsize = box['boxsize'],exhaustiveness = 4,ncores = 4)
119-
print(NewI.cost, NewI.vina_score, NewI.qed, NewI.sa_score)
115+
NewI = fitness.Cost(Individual=I, wd=tmp_path.name, receptor_pdbqt_path=data_x0161['protein']['pdbqt'], \
116+
boxcenter=box['boxcenter'], boxsize=box['boxsize'], exhaustiveness=4, ncores=4)
117+
print(NewI.cost, NewI.vina_score, NewI.molskill_score, NewI.sa_score)
120118
"""
121119
if not desirability:
122120
desirability = {
@@ -146,7 +144,6 @@ def Cost(
146144
}
147145
}
148146

149-
150147
# Multicriteria optimization,Optimization of Several Response Variables
151148
# Estimation of SkillScorer
152149
molskill_scorer = MolSkillScorer()
@@ -158,22 +155,22 @@ def Cost(
158155

159156
# Getting vina_score and update pdbqt
160157
Individual.vina_score, Individual.pdbqt = _vinadock(
161-
Individual = Individual,
162-
wd = wd,
163-
vina_executable = vina_executable,
164-
receptor_pdbqt_path = receptor_pdbqt_path,
165-
boxcenter = boxcenter,
166-
boxsize = boxsize,
167-
exhaustiveness = exhaustiveness,
168-
ad4map = ad4map,
169-
ncores = ncores,
170-
num_modes = num_modes,
171-
constraint = constraint,
172-
constraint_type = constraint_type,
173-
constraint_ref = constraint_ref,
174-
constraint_receptor_pdb_path = constraint_receptor_pdb_path,
175-
constraint_num_conf = constraint_num_conf,
176-
constraint_minimum_conf_rms = constraint_minimum_conf_rms,
158+
Individual=Individual,
159+
wd=wd,
160+
vina_executable=vina_executable,
161+
receptor_pdbqt_path=receptor_pdbqt_path,
162+
boxcenter=boxcenter,
163+
boxsize=boxsize,
164+
exhaustiveness=exhaustiveness,
165+
ad4map=ad4map,
166+
ncores=ncores,
167+
num_modes=num_modes,
168+
constraint=constraint,
169+
constraint_type=constraint_type,
170+
constraint_ref=constraint_ref,
171+
constraint_receptor_pdb_path=constraint_receptor_pdb_path,
172+
constraint_num_conf=constraint_num_conf,
173+
constraint_minimum_conf_rms=constraint_minimum_conf_rms,
177174
)
178175
# Adding the cost using all the information of qed, sas and vina_cost
179176
# Construct the desirability
@@ -188,12 +185,12 @@ def Cost(
188185
elif key in utils.DerringerSuichDesirability():
189186
d = utils.DerringerSuichDesirability()[key](getattr(Individual, variable), **desirability[variable][key])
190187
else:
191-
raise RuntimeError(f"Inside the desirability dictionary you provided for the variable = {variable} "\
192-
f"a non implemented key = {key}. Only are possible: 'w' (standing for weight) and any "\
193-
f"possible Derringer-Suich desirability function: {utils.DerringerSuichDesirability().keys()}")
188+
raise RuntimeError(f"Inside the desirability dictionary you provided for the variable = {variable} "
189+
f"a non implemented key = {key}. Only are possible: 'w' (standing for weight) and any "
190+
f"possible Derringer-Suich desirability function: {utils.DerringerSuichDesirability().keys()}")
194191
base *= d**w
195192
exponent += w
196193

197194
# We are using a geometric mean. And because we are minimizing we have to return
198195
Individual.cost = 1 - base**(1/exponent)
199-
return Individual
196+
return Individual

Contrib/using_models/fitness_plus_models.py

Lines changed: 91 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import joblib
77
import numpy as np
88
from rdkit import Chem, RDLogger
9-
from rdkit.Chem import AllChem, Descriptors
9+
from rdkit.Chem import QED, AllChem, Descriptors
1010

1111
from moldrug import utils
1212
from moldrug.fitness import _vinadock
@@ -15,7 +15,7 @@
1515

1616

1717
class 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+
121122
def 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

Comments
 (0)