libokj commited on
Commit
69bec57
·
1 Parent(s): 38eb1d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +281 -2
app.py CHANGED
@@ -1,5 +1,284 @@
 
 
 
 
 
 
1
  import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- demo = gr.load("Helsinki-NLP/opus-mt-en-es", src="models")
4
 
5
- demo.launch()
 
 
1
+ import hydra
2
+ import os
3
+ import pathlib
4
+ from pathlib import Path
5
+ import sys
6
+
7
  import gradio as gr
8
+ import pandas as pd
9
+ from rdkit import Chem
10
+ from rdkit.Chem import RDConfig, Descriptors, Lipinski, Crippen
11
+
12
+ from deepscreen.predict import predict
13
+
14
+ sys.path.append(os.path.join(RDConfig.RDContribDir, 'SA_Score'))
15
+ import sascorer
16
+
17
+ pathlib.PosixPath = pathlib.WindowsPath
18
+ ROOT = Path.cwd()
19
+
20
+ # TODO refactor caching with LRU
21
+ # MOL_MAP = {}
22
+ # def cached_mol(smiles):
23
+ # if smiles not in MOL_MAP:
24
+ # MOL_MAP.update({smiles: Chem.MolFromSmiles(smiles)})
25
+ # return MOL_MAP.get(smiles)
26
+
27
+
28
+ def sa_score(row):
29
+ return sascorer.calculateScore(Chem.MolFromSmiles(row['X1']))
30
+
31
+ def mw(row):
32
+ return Chem.Descriptors.MolWt(Chem.MolFromSmiles(row['X1']))
33
+
34
+ def hbd(row):
35
+ return Lipinski.NumHDonors(Chem.MolFromSmiles(row['X1']))
36
+
37
+ def hba(row):
38
+ return Lipinski.NumHAcceptors(Chem.MolFromSmiles(row['X1']))
39
+
40
+ def logp(row):
41
+ return Crippen.MolLogP(Chem.MolFromSmiles(row['X1']))
42
+
43
+ SCORE_MAP = {
44
+ 'SAscore': sa_score,
45
+ 'RAscore': None, # https://github.com/reymond-group/RAscore
46
+ 'SCScore': None, # https://pubs.acs.org/doi/10.1021/acs.jcim.7b00622
47
+ 'LogP': logp, # https://www.rdkit.org/docs/source/rdkit.Chem.Crippen.html
48
+ 'MW': mw, # https://www.rdkit.org/docs/source/rdkit.Chem.Descriptors.html
49
+ 'HBD': hbd, # https://www.rdkit.org/docs/source/rdkit.Chem.Lipinski.html
50
+ 'HBA': hba, # https://www.rdkit.org/docs/source/rdkit.Chem.Lipinski.html
51
+ 'TopoPSA': None, # http://mordred-descriptor.github.io/documentation/master/api/mordred.TopoPSA.html
52
+ }
53
+
54
+ FILTER_MAP = {
55
+ 'PAINS filter': None,
56
+ "Lipinski's rule of five": None, # https://gist.github.com/strets123/fdc4db6d450b66345f46
57
+ 'ADMET filter': None,
58
+ 'TCL filter': None
59
+ }
60
+
61
+ TASK_MAP = {
62
+ 'Drug-target interaction': 'binary',
63
+ 'Drug-target binding affinity': 'regression',
64
+ }
65
+
66
+ PRESET_MAP = {
67
+ 'DeepDTA': 'deep_dta',
68
+ 'GraphDTA': 'graph_dta'
69
+ }
70
+
71
+ TARGET_FAMILY_MAP = {
72
+ 'Auto-detect': 'detect',
73
+ 'Manually-labelled': 'labelled',
74
+ 'Library-labelled': 'labelled',
75
+ 'Kinases': 'kinases',
76
+ 'Non-kinase enzymes': 'non-kinase_enzymes',
77
+ 'Membrane receptors': 'membrane_receptors',
78
+ 'Nuclear receptors': 'nuclear_receptors',
79
+ 'Ion channels': 'ion_channels',
80
+ 'Other protein targets': 'other_protein_targets',
81
+ 'Kinases (auto-detected)': 'kinases',
82
+ 'Non-kinase enzymes (auto-detected)': 'non-kinase_enzymes',
83
+ 'Membrane receptors (auto-detected)': 'membrane_receptors',
84
+ 'Nuclear receptors (auto-detected)': 'nuclear_receptors',
85
+ 'Ion channels (auto-detected)': 'ion_channels',
86
+ 'Other protein targets (auto-detected)': 'other_protein_targets',
87
+ 'Indiscriminate': 'indiscriminate'
88
+ }
89
+
90
+ TARGET_LIBRARY_MAP = {
91
+ 'STITCH': 'stitch.csv',
92
+ 'Drug Repurposing Hub': 'drug_repurposing_hub.csv',
93
+ }
94
+
95
+ DRUG_LIBRARY_MAP = {
96
+ 'ChEMBL': 'chembl.csv',
97
+ 'DrugBank': 'drug_bank.csv',
98
+ }
99
+
100
+ MODE_LIST = [
101
+ 'Drug screening',
102
+ 'Drug repurposing',
103
+ 'Drug-target pair'
104
+ ]
105
+
106
+ def predictions_to_df(predictions):
107
+ predictions = [pd.DataFrame(prediction) for prediction in predictions]
108
+ prediction_df = pd.concat(predictions, ignore_index=True)
109
+ return prediction_df
110
+
111
+
112
+ def submit_predict(predict_data, task, preset, target_family):
113
+ task = TASK_MAP[task]
114
+ preset = PRESET_MAP[preset]
115
+ target_family = TARGET_FAMILY_MAP[target_family]
116
+
117
+ match target_family:
118
+ case 'labelled':
119
+ pass # target_family_list = ...
120
+ case 'detect':
121
+ pass # target_family_list = ...
122
+ case _:
123
+ target_family_list = [target_family]
124
+
125
+ prediction_df = pd.DataFrame()
126
+ for target_family in target_family_list:
127
+ with hydra.initialize(version_base="1.3", config_path="configs", job_name="webserver_inference"):
128
+ cfg = hydra.compose(
129
+ config_name="webserver_inference",
130
+ overrides=[
131
+ f"task={task}",
132
+ f"preset={preset}",
133
+ f"ckpt_path=resources/checkpoints/{preset}-{task}-{target_family}.ckpt",
134
+ f"data.data_file='{str(predict_data)}'",
135
+ ]
136
+ )
137
+
138
+ predictions, _ = predict(cfg)
139
+ prediction_df = pd.concat([prediction_df, predictions_to_df(predictions)])
140
+
141
+ return [gr.DataFrame(value=prediction_df, visible=True), gr.Tabs(selected=1)]
142
+
143
+
144
+ # Define a function that takes a CSV output and a list of analytical utility functions as inputs
145
+ def submit_report(df, score_list, filter_list):
146
+ # Loop through the list of functions and apply them to the dataframe
147
+ for filter_name in filter_list:
148
+ gr.Info(f'Applying {filter_name}...')
149
+
150
+ for score_name in score_list:
151
+ gr.Info(f'Calculating {score_name}...')
152
+ # Apply the function to the dataframe and assign the result to a new column
153
+ df[score_name] = df.apply(SCORE_MAP[score_name], axis=1)
154
+ # Return the dataframe as a table
155
+ return [gr.DataFrame(visible=False), gr.DataFrame(value=df, visible=True)]
156
+
157
+
158
+ def change_layout(mode):
159
+ match mode:
160
+ case "Drug screening":
161
+ return [
162
+ gr.Row(visible=True),
163
+ gr.Row(visible=False),
164
+ gr.Row(visible=False),
165
+ gr.Dropdown(choices=[
166
+ 'Auto-detect',
167
+ 'Kinases',
168
+ 'Non-kinase enzymes',
169
+ 'Membrane receptors',
170
+ 'Nuclear receptors',
171
+ 'Ion channels',
172
+ 'Other protein targets',
173
+ 'Indiscriminate'
174
+ ])
175
+ ]
176
+ case "Drug repurposing":
177
+ return [
178
+ gr.Row(visible=False),
179
+ gr.Row(visible=True),
180
+ gr.Row(visible=False),
181
+ gr.Dropdown(choices=[
182
+ 'Library-labelled',
183
+ 'Indiscriminate'
184
+ ])
185
+ ]
186
+ case "Drug-target pair":
187
+ return [
188
+ gr.Row(visible=False),
189
+ gr.Row(visible=False),
190
+ gr.Row(visible=True),
191
+ gr.Dropdown(choices=[
192
+ 'Auto-detect',
193
+ 'Manually-labelled',
194
+ 'Indiscriminate'
195
+ ])
196
+ ]
197
+
198
+
199
+
200
+ with gr.Blocks(theme=gr.themes.Soft(spacing_size="sm", text_size='md'), title='DeepScreen') as demo:
201
+ with gr.Tabs() as tabs:
202
+ with gr.TabItem(label='Inference', id=0) as inference:
203
+ gr.Markdown('''
204
+ # <center>DeepScreen Inference Service</center>
205
+
206
+ DeepScreen for predicting drug-target interaction/binding affinity.
207
+ ''')
208
+
209
+ mode = gr.Radio(label='Mode', choices=MODE_LIST, value='Drug screening')
210
+
211
+ with gr.Row(visible=True) as drug_screening:
212
+ with gr.Column():
213
+ target = gr.Textbox(label='Target FASTA sequence')
214
+ drug_library = gr.Dropdown(label='Drug library', choices=DRUG_LIBRARY_MAP.keys())
215
+
216
+ # Modify the pd df directly with df['X2'] = target
217
+
218
+ with gr.Row(visible=False) as drug_repurposing:
219
+ with gr.Column():
220
+ drug = gr.Textbox(label='Drug SMILES sequence')
221
+ target_library = gr.Dropdown(label='Target library', choices=TARGET_LIBRARY_MAP.keys())
222
+
223
+ # Modify the pd df directly with df['X1'] = drug
224
+
225
+
226
+ with gr.Row(visible=False) as drug_target_pair:
227
+ predict_data = gr.File(label='Prediction dataset file', file_count="single", type='filepath', height=50)
228
+
229
+ with gr.Row(visible=True):
230
+ task = gr.Dropdown(list(TASK_MAP.keys()), label='Task')
231
+ preset = gr.Dropdown(list(PRESET_MAP.keys()), label='Preset')
232
+ target_family = gr.Dropdown(choices=[
233
+ 'Auto-detect',
234
+ 'Kinases',
235
+ 'Non-kinase enzymes',
236
+ 'Membrane receptors',
237
+ 'Nuclear receptors',
238
+ 'Ion channels',
239
+ 'Other protein targets',
240
+ 'Indiscriminate'
241
+ ], label='Target family')
242
+
243
+ with gr.Row(visible=True):
244
+ predict_btn = gr.Button("Predict", variant="primary")
245
+
246
+ with gr.TabItem(label='Report', id=1) as report:
247
+ gr.Markdown('''
248
+ # <center>DeepScreen Virtual Screening Report</center>
249
+
250
+ Analytic report for virtual screening predictions.
251
+ ''')
252
+ with gr.Row():
253
+ scores = gr.CheckboxGroup(SCORE_MAP.keys(), label='Scores')
254
+ filters = gr.CheckboxGroup(FILTER_MAP.keys(), label='Filters')
255
+
256
+ with gr.Row():
257
+ df_original = gr.Dataframe(type="pandas", interactive=False, height=500, visible=False)
258
+ df_report = gr.Dataframe(type="pandas", interactive=False, height=500, visible=False)
259
+ with gr.Row():
260
+ clear_btn = gr.ClearButton()
261
+ analyze_btn = gr.Button("Report", variant="primary")
262
+
263
+ mode.change(change_layout, mode, [drug_screening, drug_repurposing, drug_target_pair, target_family], show_progress=False)
264
+ predict_btn.click(fn=submit_predict, inputs=[predict_data, task, preset, target_family], outputs=[df_original, tabs])
265
+ analyze_btn.click(fn=submit_report, inputs=[df_original, scores, filters], outputs=[df_original, df_report])
266
+
267
+
268
+ # js = """function () {
269
+ # gradioURL = window.location.href
270
+ # if (!gradioURL.endsWith('?__theme=light')) {
271
+ # window.location.replace(gradioURL + '?__theme=light');
272
+ # }
273
+ # }"""
274
+ js="""
275
+ () => {
276
+ document.body.classList.remove('dark');
277
+ document.querySelector('gradio-app').style.backgroundColor = 'var(--color-background-primary)'
278
+ }
279
+ """
280
+ demo.load(None, None, None, js=js)
281
 
 
282
 
283
+ demo.close()
284
+ demo.launch(debug=True)