Oncodrive3D 1.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oncodrive3d-1.0.4.dist-info/METADATA +333 -0
- oncodrive3d-1.0.4.dist-info/RECORD +36 -0
- oncodrive3d-1.0.4.dist-info/WHEEL +4 -0
- oncodrive3d-1.0.4.dist-info/entry_points.txt +5 -0
- oncodrive3d-1.0.4.dist-info/licenses/LICENSE +15 -0
- scripts/__init__.py +2 -0
- scripts/clustering_3d.code-workspace +7 -0
- scripts/datasets/__init__.py +0 -0
- scripts/datasets/af_merge.py +344 -0
- scripts/datasets/build_datasets.py +125 -0
- scripts/datasets/get_pae.py +78 -0
- scripts/datasets/get_structures.py +107 -0
- scripts/datasets/model_confidence.py +97 -0
- scripts/datasets/parse_pae.py +64 -0
- scripts/datasets/prob_contact_maps.py +258 -0
- scripts/datasets/seq_for_mut_prob.py +900 -0
- scripts/datasets/utils.py +394 -0
- scripts/globals.py +169 -0
- scripts/main.py +650 -0
- scripts/plotting/__init__.py +0 -0
- scripts/plotting/build_annotations.py +102 -0
- scripts/plotting/chimerax_plot.py +251 -0
- scripts/plotting/pdb_tool.py +149 -0
- scripts/plotting/pfam.py +94 -0
- scripts/plotting/plot.py +2484 -0
- scripts/plotting/stability_change.py +184 -0
- scripts/plotting/uniprot_feat.py +276 -0
- scripts/plotting/utils.py +594 -0
- scripts/run/__init__.py +0 -0
- scripts/run/clustering.py +749 -0
- scripts/run/communities.py +53 -0
- scripts/run/miss_mut_prob.py +206 -0
- scripts/run/mutability.py +289 -0
- scripts/run/pvalues.py +91 -0
- scripts/run/score_and_simulations.py +155 -0
- scripts/run/utils.py +461 -0
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
import daiquiri
|
|
5
|
+
import subprocess
|
|
6
|
+
import click
|
|
7
|
+
import sys
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import json
|
|
11
|
+
|
|
12
|
+
from scripts import __logger_name__
|
|
13
|
+
|
|
14
|
+
logger = daiquiri.getLogger(__logger_name__ + ".plotting.utils")
|
|
15
|
+
|
|
16
|
+
logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_species(species):
|
|
21
|
+
"""
|
|
22
|
+
Simply change species name to accepted format.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
if species.capitalize() == "Human" or species.capitalize() == "Homo sapiens":
|
|
26
|
+
species = "Homo sapiens"
|
|
27
|
+
elif species.capitalize() == "Mouse" or species.capitalize() == "Mus musculus":
|
|
28
|
+
species = "Mus musculus"
|
|
29
|
+
else:
|
|
30
|
+
raise RuntimeError(f"Failed to recognize '{species}' as species. Currently accepted ones are 'Homo sapiens' and 'Mus musculus'. Exiting...")
|
|
31
|
+
|
|
32
|
+
return species
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def clean_annotations_dir(path: str, loc: str) -> None:
|
|
36
|
+
"""
|
|
37
|
+
Clean the annotations directory by removing specific files
|
|
38
|
+
and subdirectories.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
path (str): Path to the directory to be cleaned.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
if loc == "d":
|
|
45
|
+
|
|
46
|
+
clean_files = f"rm -rf {os.path.join(path, '*.csv')} {os.path.join(path, '*.tsv')} {os.path.join(path, '*.json')} {os.path.join(path, '.*.txt')}"
|
|
47
|
+
clean_ddg = ["rm", "-rf", os.path.join(path, "stability_change")]
|
|
48
|
+
clean_pdbtool = ["rm", "-rf", os.path.join(path, "pdb_tool")]
|
|
49
|
+
#clean_log = ["rm", "-rf", os.path.join(path, "log")]
|
|
50
|
+
|
|
51
|
+
logger.debug(clean_files)
|
|
52
|
+
subprocess.run(clean_files, shell=True)
|
|
53
|
+
|
|
54
|
+
logger.debug(' '.join(clean_ddg))
|
|
55
|
+
subprocess.run(clean_ddg)
|
|
56
|
+
|
|
57
|
+
logger.debug(' '.join(clean_pdbtool))
|
|
58
|
+
subprocess.run(clean_pdbtool)
|
|
59
|
+
|
|
60
|
+
# logger.debug(' '.join(clean_log))
|
|
61
|
+
# subprocess.run(clean_log)
|
|
62
|
+
|
|
63
|
+
elif loc == "r":
|
|
64
|
+
# TODO: implement cleaning function for output
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def clean_annot_dir(path: str, loc: str = 'd') -> None:
|
|
69
|
+
"""
|
|
70
|
+
Clean it upon request if it already exists.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
path (str): Path to the directory to be created or cleaned.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
if os.listdir(path) != ['log']:
|
|
77
|
+
logger.warning(f"Directory {path} already exists and is not empty.")
|
|
78
|
+
|
|
79
|
+
overwrite = "y" if click.get_current_context().params['yes'] else input("Clean existing directory? (y/n): ")
|
|
80
|
+
while overwrite.lower() not in ["y", "yes", "n", "no"]:
|
|
81
|
+
print("Please choose yes or no")
|
|
82
|
+
overwrite = input("Clean existing directory? (y/n): ")
|
|
83
|
+
|
|
84
|
+
if overwrite.lower() in ["y", "yes"]:
|
|
85
|
+
clean_annotations_dir(path, loc)
|
|
86
|
+
logger.info(f"Dataset files in {path} have been removed.")
|
|
87
|
+
else:
|
|
88
|
+
logger.warning(f"Dataset files in {path} have not been removed.")
|
|
89
|
+
else:
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_broad_consequence(list_of_annotations):
|
|
94
|
+
"""
|
|
95
|
+
Group variants into broader consequence types.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
CONSEQUENCES_LIST = [
|
|
99
|
+
'transcript_ablation',
|
|
100
|
+
'splice_acceptor_variant',
|
|
101
|
+
'splice_donor_variant',
|
|
102
|
+
'stop_gained',
|
|
103
|
+
'frameshift_variant',
|
|
104
|
+
'stop_lost',
|
|
105
|
+
'start_lost',
|
|
106
|
+
'transcript_amplification',
|
|
107
|
+
'inframe_insertion',
|
|
108
|
+
'inframe_deletion',
|
|
109
|
+
'missense_variant',
|
|
110
|
+
'protein_altering_variant',
|
|
111
|
+
'splice_region_variant',
|
|
112
|
+
'splice_donor_5th_base_variant',
|
|
113
|
+
'splice_donor_region_variant',
|
|
114
|
+
'splice_polypyrimidine_tract_variant',
|
|
115
|
+
'incomplete_terminal_codon_variant',
|
|
116
|
+
'start_retained_variant',
|
|
117
|
+
'stop_retained_variant',
|
|
118
|
+
'synonymous_variant',
|
|
119
|
+
'coding_sequence_variant',
|
|
120
|
+
'mature_miRNA_variant',
|
|
121
|
+
'5_prime_UTR_variant',
|
|
122
|
+
'3_prime_UTR_variant',
|
|
123
|
+
'non_coding_transcript_exon_variant',
|
|
124
|
+
'intron_variant',
|
|
125
|
+
'NMD_transcript_variant',
|
|
126
|
+
'non_coding_transcript_variant',
|
|
127
|
+
'upstream_gene_variant',
|
|
128
|
+
'downstream_gene_variant',
|
|
129
|
+
'TFBS_ablation',
|
|
130
|
+
'TFBS_amplification',
|
|
131
|
+
'TF_binding_site_variant',
|
|
132
|
+
'regulatory_region_ablation',
|
|
133
|
+
'regulatory_region_amplification',
|
|
134
|
+
'feature_elongation',
|
|
135
|
+
'regulatory_region_variant',
|
|
136
|
+
'feature_truncation',
|
|
137
|
+
'intergenic_variant'
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
GROUPING_DICT = {
|
|
141
|
+
'transcript_ablation': 'nonsense',
|
|
142
|
+
'splice_acceptor_variant': 'nonsense',
|
|
143
|
+
'splice_donor_variant': 'nonsense',
|
|
144
|
+
'stop_gained': 'nonsense',
|
|
145
|
+
'frameshift_variant': 'nonsense',
|
|
146
|
+
'stop_lost': 'nonsense',
|
|
147
|
+
'start_lost': 'nonsense',
|
|
148
|
+
'missense_variant': 'missense',
|
|
149
|
+
'inframe_insertion': 'indel',
|
|
150
|
+
'inframe_deletion': 'indel',
|
|
151
|
+
'splice_donor_variant': 'splicing',
|
|
152
|
+
'splice_acceptor_variant': 'splicing',
|
|
153
|
+
'splice_region_variant': 'splicing',
|
|
154
|
+
'splice_donor_5th_base_variant': 'splicing',
|
|
155
|
+
'splice_donor_region_variant': 'splicing',
|
|
156
|
+
'splice_polypyrimidine_tract_variant': 'splicing',
|
|
157
|
+
'synonymous_variant': 'synonymous',
|
|
158
|
+
'incomplete_terminal_codon_variant': 'synonymous',
|
|
159
|
+
'start_retained_variant': 'synonymous',
|
|
160
|
+
'stop_retained_variant': 'synonymous',
|
|
161
|
+
'protein_altering_variant' : 'protein_altering_variant',
|
|
162
|
+
'transcript_amplification' : 'transcript_amplification',
|
|
163
|
+
'coding_sequence_variant': 'coding_sequence_variant',
|
|
164
|
+
'mature_miRNA_variant': 'non_coding_exon_region',
|
|
165
|
+
'5_prime_UTR_variant': 'non_coding_exon_region',
|
|
166
|
+
'3_prime_UTR_variant': 'non_coding_exon_region',
|
|
167
|
+
'non_coding_transcript_exon_variant': 'non_coding_exon_region',
|
|
168
|
+
'NMD_transcript_variant': 'non_coding_exon_region',
|
|
169
|
+
'intron_variant': 'intron_variant',
|
|
170
|
+
'non_coding_transcript_variant' : 'non_coding_transcript_variant',
|
|
171
|
+
'upstream_gene_variant': 'non_genic_variant',
|
|
172
|
+
'downstream_gene_variant': 'non_genic_variant',
|
|
173
|
+
'TFBS_ablation': 'non_genic_variant',
|
|
174
|
+
'TFBS_amplification': 'non_genic_variant',
|
|
175
|
+
'TF_binding_site_variant': 'non_genic_variant',
|
|
176
|
+
'regulatory_region_ablation': 'non_genic_variant',
|
|
177
|
+
'regulatory_region_amplification': 'non_genic_variant',
|
|
178
|
+
'feature_elongation': 'non_genic_variant',
|
|
179
|
+
'regulatory_region_variant': 'non_genic_variant',
|
|
180
|
+
'feature_truncation': 'non_genic_variant',
|
|
181
|
+
'intergenic_variant': 'non_genic_variant',
|
|
182
|
+
'-' : '-'
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
consequence_rank_dict = { consequence : rank for rank, consequence in enumerate(CONSEQUENCES_LIST) }
|
|
186
|
+
rank_consequence_dict = { rank : consequence for rank, consequence in enumerate(CONSEQUENCES_LIST) }
|
|
187
|
+
|
|
188
|
+
list_of_single_annotations = []
|
|
189
|
+
list_of_broad_annotations = []
|
|
190
|
+
for x in list_of_annotations:
|
|
191
|
+
all_consequences = x.split(",")
|
|
192
|
+
all_consequences_ranks = map(lambda x: consequence_rank_dict[x], all_consequences)
|
|
193
|
+
single_consequence = rank_consequence_dict[min(all_consequences_ranks)]
|
|
194
|
+
list_of_single_annotations.append(single_consequence)
|
|
195
|
+
if single_consequence in GROUPING_DICT:
|
|
196
|
+
list_of_broad_annotations.append(GROUPING_DICT[single_consequence])
|
|
197
|
+
else:
|
|
198
|
+
list_of_broad_annotations.append(single_consequence)
|
|
199
|
+
|
|
200
|
+
return list_of_broad_annotations
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def init_plot_pars(summary_fsize_x=0.4, # It will be moltiplied for the number of genes
|
|
204
|
+
summary_fsize_y=8,
|
|
205
|
+
gene_fsize_x=24,
|
|
206
|
+
gene_fsize_y=12,
|
|
207
|
+
volcano_fsize_x=15,
|
|
208
|
+
volcano_fsize_y=10,
|
|
209
|
+
volcano_subplots_fsize_x=4,
|
|
210
|
+
volcano_subplots_fsize_y=2,
|
|
211
|
+
log_odds_fsize_x=20,
|
|
212
|
+
log_odds_fsize_y=4,
|
|
213
|
+
s_lw=0.2,
|
|
214
|
+
sse_fill_width=0.43,
|
|
215
|
+
dist_thr=0.1,
|
|
216
|
+
summary_alpha=0.3,
|
|
217
|
+
lst_summary_tracks=None,
|
|
218
|
+
lst_summary_hratios=None,
|
|
219
|
+
lst_gene_annot=None,
|
|
220
|
+
lst_gene_hratios=None,
|
|
221
|
+
volcano_top_n=15):
|
|
222
|
+
"""
|
|
223
|
+
Initialize plotting parameters.
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
plot_pars = {}
|
|
227
|
+
|
|
228
|
+
plot_pars["summary_figsize"] = summary_fsize_x, summary_fsize_y
|
|
229
|
+
plot_pars["figsize"] = gene_fsize_x, gene_fsize_y
|
|
230
|
+
plot_pars["s_lw"] = s_lw
|
|
231
|
+
plot_pars["sse_fill_width"] = sse_fill_width
|
|
232
|
+
plot_pars["dist_thr"] = dist_thr
|
|
233
|
+
plot_pars["summary_alpha"] = summary_alpha
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
# Summary-plot
|
|
237
|
+
# ============
|
|
238
|
+
|
|
239
|
+
# Default values
|
|
240
|
+
plot_pars["summary_h_ratios"] = {"score" : 0.3,
|
|
241
|
+
"miss_count" : 0.2,
|
|
242
|
+
"res_count" : 0.2,
|
|
243
|
+
"res_clust_mut" : 0.2,
|
|
244
|
+
"clusters" : 0.2}
|
|
245
|
+
|
|
246
|
+
# Custom values
|
|
247
|
+
if not lst_summary_tracks:
|
|
248
|
+
lst_summary_tracks = plot_pars["summary_h_ratios"].keys()
|
|
249
|
+
if lst_summary_hratios:
|
|
250
|
+
plot_pars["summary_h_ratios"] = {lst_summary_tracks[i] : h_ratio for i, h_ratio in enumerate(lst_summary_hratios)}
|
|
251
|
+
else:
|
|
252
|
+
plot_pars["summary_h_ratios"] = {annot : plot_pars["summary_h_ratios"][annot] for annot in lst_summary_tracks}
|
|
253
|
+
plot_pars["summary_h_ratios"] = {k:v/sum(plot_pars["summary_h_ratios"].values()) for k,v in plot_pars["summary_h_ratios"].items()}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
# Gene-plots
|
|
257
|
+
# ==========
|
|
258
|
+
|
|
259
|
+
# Default values
|
|
260
|
+
plot_pars["h_ratios"] = {"nonmiss_count" : 0.13,
|
|
261
|
+
"miss_count" : 0.13,
|
|
262
|
+
"miss_prob" : 0.13,
|
|
263
|
+
"score" : 0.13,
|
|
264
|
+
"pae" : 0.1,
|
|
265
|
+
"disorder" : 0.1,
|
|
266
|
+
"pacc" : 0.1,
|
|
267
|
+
"ddg" : 0.1,
|
|
268
|
+
"ptm" : 0.022,
|
|
269
|
+
"site" : 0.022,
|
|
270
|
+
"clusters" : 0.04,
|
|
271
|
+
"sse" : 0.065,
|
|
272
|
+
"pfam" : 0.04,
|
|
273
|
+
"prosite" : 0.04,
|
|
274
|
+
"membrane" : 0.04,
|
|
275
|
+
"motif" : 0.04}
|
|
276
|
+
|
|
277
|
+
plot_pars["color_cnsq"] = {"splicing" : "C2",
|
|
278
|
+
"missense" : "C5",
|
|
279
|
+
"synonymous" : "C9",
|
|
280
|
+
"coding_sequence_variant" : "C1",
|
|
281
|
+
"nonsense" : "C6",
|
|
282
|
+
"intron_variant" : "C7",
|
|
283
|
+
"indel" : "C8",
|
|
284
|
+
"protein_altering_variant" : "C3"}
|
|
285
|
+
|
|
286
|
+
# Custom values
|
|
287
|
+
if not lst_gene_annot:
|
|
288
|
+
lst_gene_annot = plot_pars["h_ratios"].keys()
|
|
289
|
+
if lst_gene_hratios:
|
|
290
|
+
plot_pars["h_ratios"] = {lst_gene_annot[i] : h_ratio for i, h_ratio in enumerate(lst_gene_hratios)}
|
|
291
|
+
else:
|
|
292
|
+
plot_pars["h_ratios"] = {annot : plot_pars["h_ratios"][annot] for annot in lst_gene_annot}
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
# Associations-plots
|
|
296
|
+
# ==================
|
|
297
|
+
|
|
298
|
+
plot_pars["volcano_fsize_x"] = volcano_fsize_x
|
|
299
|
+
plot_pars["volcano_fsize_y"] =volcano_fsize_y
|
|
300
|
+
plot_pars["volcano_subplots_fsize_x"] = volcano_subplots_fsize_x
|
|
301
|
+
plot_pars["volcano_subplots_fsize_y"] = volcano_subplots_fsize_y
|
|
302
|
+
plot_pars["log_odds_fsize_x"] = log_odds_fsize_x
|
|
303
|
+
plot_pars["log_odds_fsize_y"] = log_odds_fsize_y
|
|
304
|
+
plot_pars["volcano_top_n"] = volcano_top_n
|
|
305
|
+
|
|
306
|
+
return plot_pars
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def init_comp_plot_pars(fsize_x=24,
|
|
310
|
+
fsize_y=12,
|
|
311
|
+
s_lw=0.2,
|
|
312
|
+
sse_fill_width=0.43,
|
|
313
|
+
dist_thr=0.1,
|
|
314
|
+
lst_tracks=None,
|
|
315
|
+
lst_hratios=None,
|
|
316
|
+
count_mirror=False,
|
|
317
|
+
score_mirror=False,
|
|
318
|
+
prob_mirror=False):
|
|
319
|
+
"""
|
|
320
|
+
Initialize plotting parameters.
|
|
321
|
+
"""
|
|
322
|
+
|
|
323
|
+
plot_pars = {}
|
|
324
|
+
|
|
325
|
+
plot_pars["figsize"] = fsize_x, fsize_y
|
|
326
|
+
plot_pars["s_lw"] = s_lw
|
|
327
|
+
plot_pars["sse_fill_width"] = sse_fill_width
|
|
328
|
+
plot_pars["dist_thr"] = dist_thr
|
|
329
|
+
plot_pars["count_mirror"] = count_mirror
|
|
330
|
+
plot_pars["score_mirror"] = score_mirror
|
|
331
|
+
plot_pars["prob_mirror"] = prob_mirror
|
|
332
|
+
|
|
333
|
+
# Default values
|
|
334
|
+
plot_pars["h_ratios"] = {"nonmiss_count" : 0.13,
|
|
335
|
+
"miss_count" : 0.13,
|
|
336
|
+
"miss_prob" : 0.13,
|
|
337
|
+
"score" : 0.13,
|
|
338
|
+
"clusters" : 0.04,
|
|
339
|
+
"pae" : 0.1,
|
|
340
|
+
"disorder" : 0.1,
|
|
341
|
+
"pacc" : 0.1,
|
|
342
|
+
"ddg" : 0.1,
|
|
343
|
+
"ptm" : 0.022,
|
|
344
|
+
"site" : 0.022,
|
|
345
|
+
"sse" : 0.065,
|
|
346
|
+
"pfam" : 0.04,
|
|
347
|
+
"prosite" : 0.04,
|
|
348
|
+
"membrane" : 0.04,
|
|
349
|
+
"motif" : 0.04}
|
|
350
|
+
|
|
351
|
+
plot_pars["color_cnsq"] = {"splicing" : "C2",
|
|
352
|
+
"missense" : "C5",
|
|
353
|
+
"synonymous" : "C9",
|
|
354
|
+
"coding_sequence_variant" : "C1",
|
|
355
|
+
"nonsense" : "C6",
|
|
356
|
+
"intron_variant" : "C7",
|
|
357
|
+
"indel" : "C8",
|
|
358
|
+
"protein_altering_variant" : "C3"}
|
|
359
|
+
|
|
360
|
+
# Custom values
|
|
361
|
+
if not lst_tracks:
|
|
362
|
+
lst_tracks = list(plot_pars["h_ratios"].keys())
|
|
363
|
+
|
|
364
|
+
if not count_mirror and "nonmiss_count" in lst_tracks:
|
|
365
|
+
ix = lst_tracks.index("nonmiss_count")
|
|
366
|
+
lst_tracks.insert(ix+1, "nonmiss_count_2")
|
|
367
|
+
plot_pars["h_ratios"]["nonmiss_count_2"] = plot_pars["h_ratios"]["nonmiss_count"]
|
|
368
|
+
|
|
369
|
+
if not count_mirror and "miss_count" in lst_tracks:
|
|
370
|
+
ix = lst_tracks.index("miss_count")
|
|
371
|
+
lst_tracks.insert(ix+1, "miss_count_2")
|
|
372
|
+
plot_pars["h_ratios"]["miss_count_2"] = plot_pars["h_ratios"]["miss_count"]
|
|
373
|
+
|
|
374
|
+
if not score_mirror and "score" in lst_tracks:
|
|
375
|
+
ix = lst_tracks.index("score")
|
|
376
|
+
lst_tracks.insert(ix+1, "score_2")
|
|
377
|
+
plot_pars["h_ratios"]["score_2"] = plot_pars["h_ratios"]["score"]
|
|
378
|
+
|
|
379
|
+
if "clusters" in lst_tracks:
|
|
380
|
+
ix = lst_tracks.index("clusters")
|
|
381
|
+
lst_tracks.insert(ix+1, "clusters_2")
|
|
382
|
+
plot_pars["h_ratios"]["clusters_2"] = plot_pars["h_ratios"]["clusters"]
|
|
383
|
+
|
|
384
|
+
if "ddg" in lst_tracks:
|
|
385
|
+
ix = lst_tracks.index("ddg")
|
|
386
|
+
lst_tracks.insert(ix+1, "ddg_2")
|
|
387
|
+
plot_pars["h_ratios"]["ddg_2"] = plot_pars["h_ratios"]["ddg"]
|
|
388
|
+
|
|
389
|
+
if lst_hratios:
|
|
390
|
+
plot_pars["h_ratios"] = {lst_tracks[i] : h_ratio for i, h_ratio in enumerate(lst_hratios)}
|
|
391
|
+
else:
|
|
392
|
+
plot_pars["h_ratios"] = {annot : plot_pars["h_ratios"][annot] for annot in lst_tracks}
|
|
393
|
+
|
|
394
|
+
plot_pars["h_ratios"] = {k:v/sum(plot_pars["h_ratios"].values()) for k,v in plot_pars["h_ratios"].items()}
|
|
395
|
+
|
|
396
|
+
return plot_pars
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def load_o3d_result(o3d_result_path, cohort):
|
|
400
|
+
"""
|
|
401
|
+
Load all files generated by 3D clustering analysis of Oncodrive3D.
|
|
402
|
+
"""
|
|
403
|
+
|
|
404
|
+
gene_result_path = f"{o3d_result_path}/{cohort}/{cohort}.3d_clustering_genes.csv"
|
|
405
|
+
pos_result_path = f"{o3d_result_path}/{cohort}/{cohort}.3d_clustering_pos.csv"
|
|
406
|
+
maf_path = f"{o3d_result_path}/{cohort}/{cohort}.mutations.processed.tsv"
|
|
407
|
+
miss_prob_dict_path = f"{o3d_result_path}/{cohort}/{cohort}.miss_prob.processed.json"
|
|
408
|
+
gene_result = pd.read_csv(gene_result_path)
|
|
409
|
+
pos_result = pd.read_csv(pos_result_path)
|
|
410
|
+
maf = pd.read_csv(maf_path, sep="\t")
|
|
411
|
+
miss_prob_dict = json.load(open(miss_prob_dict_path))
|
|
412
|
+
|
|
413
|
+
return gene_result, pos_result, maf, miss_prob_dict
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def subset_genes_and_ids(genes,
|
|
417
|
+
uni_ids,
|
|
418
|
+
seq_df,
|
|
419
|
+
disorder,
|
|
420
|
+
pdb_tool,
|
|
421
|
+
uniprot_feat):
|
|
422
|
+
"""
|
|
423
|
+
Subset each dataframe by keeping only selected genes and proteins IDs.
|
|
424
|
+
"""
|
|
425
|
+
|
|
426
|
+
seq_df = seq_df.copy()
|
|
427
|
+
disorder = disorder.copy()
|
|
428
|
+
pdb_tool = pdb_tool.copy()
|
|
429
|
+
uniprot_feat = uniprot_feat.copy()
|
|
430
|
+
# Filter genes in the other df
|
|
431
|
+
seq_df = seq_df[seq_df["Gene"].isin(genes)]
|
|
432
|
+
disorder = disorder[disorder["Uniprot_ID"].isin(uni_ids)].reset_index(drop=True)
|
|
433
|
+
pdb_tool = pdb_tool[pdb_tool["Uniprot_ID"].isin(uni_ids)].reset_index(drop=True)
|
|
434
|
+
uniprot_feat = uniprot_feat[uniprot_feat["Gene"].isin(genes)]
|
|
435
|
+
|
|
436
|
+
return seq_df, disorder, pdb_tool, uniprot_feat
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def filter_o3d_result(gene_result, pos_result, n_genes=None, lst_genes=None):
|
|
440
|
+
"""
|
|
441
|
+
Subset gene-level and position-level Oncodrive3D result.
|
|
442
|
+
"""
|
|
443
|
+
|
|
444
|
+
if isinstance(lst_genes, str):
|
|
445
|
+
lst_genes = lst_genes.replace(" ", "")
|
|
446
|
+
lst_genes = lst_genes.split(",")
|
|
447
|
+
gene_result = gene_result[gene_result["Gene"].isin(lst_genes)]
|
|
448
|
+
gene_result = gene_result[gene_result["Status"] == "Processed"]
|
|
449
|
+
if n_genes:
|
|
450
|
+
gene_result = gene_result[:n_genes]
|
|
451
|
+
uni_ids = gene_result.Uniprot_ID.values
|
|
452
|
+
genes = gene_result.Gene.values
|
|
453
|
+
pos_result = pos_result[pos_result["Gene"].isin(genes)]
|
|
454
|
+
|
|
455
|
+
return gene_result, pos_result, genes, uni_ids
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def get_enriched_result(pos_result_gene,
|
|
459
|
+
disorder_gene,
|
|
460
|
+
pdb_tool_gene,
|
|
461
|
+
seq_df):
|
|
462
|
+
"""
|
|
463
|
+
Add annotations to Oncodrive3D result to return an annotated tsv.
|
|
464
|
+
"""
|
|
465
|
+
|
|
466
|
+
pos_result_gene = pos_result_gene.copy()
|
|
467
|
+
|
|
468
|
+
# DDG
|
|
469
|
+
pos_result_gene.loc[pos_result_gene["Mut_in_res"] == 0, "DDG"] = np.nan
|
|
470
|
+
|
|
471
|
+
# Disorder
|
|
472
|
+
pos_result_gene = pos_result_gene.merge(disorder_gene, how="left", on=["Pos"])
|
|
473
|
+
pos_result_gene = pos_result_gene.rename(columns={"Confidence" : "pLDDT_res"})
|
|
474
|
+
|
|
475
|
+
# PDB_Tool
|
|
476
|
+
pos_result_gene = pos_result_gene.rename(columns={"AF_F" : "F"}).merge(
|
|
477
|
+
pdb_tool_gene.drop(columns="F"), on=["Res", "Uniprot_ID", "Pos"], how="left")
|
|
478
|
+
|
|
479
|
+
# Transcript and gene IDs
|
|
480
|
+
pos_result_gene = pos_result_gene.merge(
|
|
481
|
+
seq_df[["Gene", "Uniprot_ID", "Ens_Gene_ID", "Ens_Transcr_ID"]],
|
|
482
|
+
how="left", on=["Uniprot_ID"])
|
|
483
|
+
|
|
484
|
+
return pos_result_gene
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def reorganize_df_to_save(pos_result_df):
|
|
488
|
+
|
|
489
|
+
pos_result_df = pos_result_df.rename(columns={"Res" : "WT_res"})
|
|
490
|
+
cols = ['Gene', 'Ens_Gene_ID', 'Ens_Transcr_ID', 'Uniprot_ID', 'F', 'Pos', "WT_res",
|
|
491
|
+
'Mut_in_gene', 'Mut_in_res', 'Mut_in_vol',
|
|
492
|
+
'Score', 'Score_obs_sim', 'pval', 'C', 'C_ext', 'Cluster', 'Rank',
|
|
493
|
+
'Tot_samples', 'Samples_in_vol', 'Samples_in_cl_vol', 'Mut_in_cl_vol', 'Res_in_cl',
|
|
494
|
+
'PAE_vol', 'pLDDT_res', 'pLDDT_vol', 'pLDDT_cl_vol',
|
|
495
|
+
'Cancer', 'Cohort',
|
|
496
|
+
'SSE', 'pACC', 'DDG', "Domain", "Ptm", "Membrane", "Site"]
|
|
497
|
+
|
|
498
|
+
return pos_result_df[[col for col in cols if col in pos_result_df.columns]]
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def save_annotated_result(pos_result,
|
|
502
|
+
annot_pos_result,
|
|
503
|
+
uni_feat_processed,
|
|
504
|
+
output_dir,
|
|
505
|
+
run_name,
|
|
506
|
+
output_all_pos=False):
|
|
507
|
+
"""
|
|
508
|
+
Save the annotated pos-level result.
|
|
509
|
+
"""
|
|
510
|
+
|
|
511
|
+
# Do not include non-mutated positions (default)
|
|
512
|
+
if output_all_pos == False:
|
|
513
|
+
annot_pos_result = annot_pos_result[annot_pos_result["Mut_in_res"] > 0].reset_index(drop=True)
|
|
514
|
+
|
|
515
|
+
# Merge with 'original' one to retrieve dropped cols
|
|
516
|
+
output_pos_result = os.path.join(output_dir, f"{run_name}.3d_clustering_pos.annotated.csv")
|
|
517
|
+
output_uniprot_feat = os.path.join(output_dir, f"{run_name}.uniprot_feat.tsv")
|
|
518
|
+
cols = ["Gene", "Uniprot_ID", "F", "Ens_Gene_ID", "Ens_Transcr_ID",
|
|
519
|
+
"Pos", "Res", "pLDDT_res", "SSE", "pACC", "DDG",
|
|
520
|
+
"Domain", "Ptm", "Membrane", "Site"]
|
|
521
|
+
annot_pos_result = pos_result.drop(columns=["F", "pLDDT_res"]).merge(
|
|
522
|
+
annot_pos_result[[col for col in cols if col in annot_pos_result.columns]],
|
|
523
|
+
how="right", on=["Gene", "Uniprot_ID", "Pos"])
|
|
524
|
+
annot_pos_result = annot_pos_result.sort_values(["Gene", "Pos"])
|
|
525
|
+
|
|
526
|
+
# Fill the NA of the non-mutated positions in features
|
|
527
|
+
for col in ["Cancer", "Cohort"]:
|
|
528
|
+
if annot_pos_result[col].isnull().all():
|
|
529
|
+
annot_pos_result[col] = np.nan
|
|
530
|
+
else:
|
|
531
|
+
annot_pos_result[col] = annot_pos_result[col].dropna().unique()[0]
|
|
532
|
+
annot_pos_result["Mut_in_res"] = annot_pos_result["Mut_in_res"].fillna(0)
|
|
533
|
+
for gene in annot_pos_result.Gene.unique():
|
|
534
|
+
mut_in_gene = annot_pos_result.loc[annot_pos_result["Gene"] == gene, "Mut_in_gene"].dropna().unique()[0]
|
|
535
|
+
annot_pos_result.loc[annot_pos_result["Gene"] == gene, "Mut_in_gene"] = mut_in_gene
|
|
536
|
+
if "Tot_samples" in annot_pos_result.columns:
|
|
537
|
+
tot_samples = annot_pos_result.loc[annot_pos_result["Gene"] == gene, "Tot_samples"].dropna().unique()
|
|
538
|
+
if tot_samples:
|
|
539
|
+
tot_samples = tot_samples[0]
|
|
540
|
+
else:
|
|
541
|
+
tot_samples = np.nan
|
|
542
|
+
annot_pos_result.loc[annot_pos_result["Gene"] == gene, "Tot_samples"] = tot_samples
|
|
543
|
+
|
|
544
|
+
# Save
|
|
545
|
+
annot_pos_result = reorganize_df_to_save(annot_pos_result)
|
|
546
|
+
annot_pos_result.to_csv(output_pos_result, index=False)
|
|
547
|
+
logger.info(f"Saved annotated position-level result to {output_pos_result}")
|
|
548
|
+
uni_feat_processed.to_csv(output_uniprot_feat, sep="\t", index=False)
|
|
549
|
+
logger.info(f"Saved Uniprot features annotations to {output_uniprot_feat}")
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
def parse_lst_tracks(lst, plot_type):
|
|
553
|
+
"""
|
|
554
|
+
Parse the list of tracks from click arg.
|
|
555
|
+
"""
|
|
556
|
+
|
|
557
|
+
summary_tracks = ["score",
|
|
558
|
+
"miss_count",
|
|
559
|
+
"res_count",
|
|
560
|
+
"res_clust_mut",
|
|
561
|
+
"clusters"]
|
|
562
|
+
|
|
563
|
+
gene_tracks = ["nonmiss_count",
|
|
564
|
+
"miss_count",
|
|
565
|
+
"miss_prob",
|
|
566
|
+
"score",
|
|
567
|
+
"pae",
|
|
568
|
+
"disorder",
|
|
569
|
+
"pacc",
|
|
570
|
+
"ddg",
|
|
571
|
+
"ptm",
|
|
572
|
+
"site",
|
|
573
|
+
"clusters",
|
|
574
|
+
"sse",
|
|
575
|
+
"pfam",
|
|
576
|
+
"prosite",
|
|
577
|
+
"membrane",
|
|
578
|
+
"motif"]
|
|
579
|
+
|
|
580
|
+
if plot_type == "summary":
|
|
581
|
+
available_tracks = summary_tracks
|
|
582
|
+
elif plot_type == "gene":
|
|
583
|
+
available_tracks = gene_tracks
|
|
584
|
+
lst = lst.split(",")
|
|
585
|
+
|
|
586
|
+
is_valid = np.array([track not in available_tracks for track in lst])
|
|
587
|
+
if is_valid.any():
|
|
588
|
+
invalid_tracks = list(np.array(lst)[np.where(is_valid)])
|
|
589
|
+
logger.error(f"One or more track names for {plot_type} plot are not accepted: {invalid_tracks}")
|
|
590
|
+
logger.error(f"Available track names are: {available_tracks}")
|
|
591
|
+
logger.error(f"Exiting..")
|
|
592
|
+
sys.exit(1)
|
|
593
|
+
|
|
594
|
+
return lst
|
scripts/run/__init__.py
ADDED
|
File without changes
|