Oncodrive3D 1.0.5__tar.gz → 1.0.7__tar.gz
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.5 → oncodrive3d-1.0.7}/.gitignore +1 -3
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/Dockerfile +2 -2
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/PKG-INFO +31 -4
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/README.md +30 -3
- oncodrive3d-1.0.7/docs/build_output.md +19 -0
- oncodrive3d-1.0.7/docs/images/graphical_abstract.png +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/docs/run_input_output.md +3 -3
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/oncodrive3d_pipeline/README.md +1 -1
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/__init__.py +1 -1
- oncodrive3d-1.0.7/scripts/datasets/build_datasets.py +173 -0
- oncodrive3d-1.0.7/scripts/datasets/custom_pdb.py +144 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/datasets/get_pae.py +28 -6
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/datasets/get_structures.py +5 -3
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/datasets/prob_contact_maps.py +10 -4
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/datasets/seq_for_mut_prob.py +236 -111
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/datasets/utils.py +2 -1
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/main.py +36 -12
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/plotting/chimerax_plot.py +9 -5
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/run/utils.py +0 -1
- oncodrive3d-1.0.7/tools/preprocessing/prepare_samplesheet.py +252 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/uv.lock +888 -887
- oncodrive3d-1.0.5/docs/build_output.md +0 -13
- oncodrive3d-1.0.5/scripts/datasets/build_datasets.py +0 -126
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/.python-version +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/LICENSE +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/oncodrive3d_pipeline/conf/base.config +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/oncodrive3d_pipeline/conf/test.config +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/oncodrive3d_pipeline/main.nf +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/oncodrive3d_pipeline/modules/o3d_chimerax_plot.nf +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/oncodrive3d_pipeline/modules/o3d_plot.nf +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/oncodrive3d_pipeline/modules/o3d_run.nf +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/oncodrive3d_pipeline/nextflow.config +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/oncodrive3d_pipeline/validation.nf +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/oncodrive3d_pipeline/workflows/oncodrive3d.nf +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/pyproject.toml +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/clustering_3d.code-workspace +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/datasets/__init__.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/datasets/af_merge.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/datasets/model_confidence.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/datasets/parse_pae.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/globals.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/plotting/__init__.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/plotting/build_annotations.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/plotting/pdb_tool.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/plotting/pfam.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/plotting/plot.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/plotting/stability_change.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/plotting/uniprot_feat.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/plotting/utils.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/run/__init__.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/run/clustering.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/run/communities.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/run/miss_mut_prob.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/run/mutability.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/run/pvalues.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/scripts/run/score_and_simulations.py +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/test/input/maf/TCGA_WXS_ACC.in.maf +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/test/input/maf/TCGA_WXS_PAAD.in.maf +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/test/input/mut_profile/TCGA_WXS_ACC.sig.json +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/test/input/mut_profile/TCGA_WXS_PAAD.sig.json +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/test/input/vep/TCGA_WXS_ACC.vep.tsv.gz +0 -0
- {oncodrive3d-1.0.5 → oncodrive3d-1.0.7}/test/input/vep/TCGA_WXS_PAAD.vep.tsv.gz +0 -0
|
@@ -19,7 +19,7 @@ RUN mkdir -p /root/.cache/uv \
|
|
|
19
19
|
&& uv build
|
|
20
20
|
|
|
21
21
|
# Second stage: Runtime image
|
|
22
|
-
FROM python:3.10-
|
|
22
|
+
FROM python:3.10.18-bookworm AS runtime-stage
|
|
23
23
|
|
|
24
24
|
# Set environment variables
|
|
25
25
|
ENV BGDATA_LOCAL="/bgdatacache" \
|
|
@@ -30,7 +30,7 @@ COPY --from=build-stage /oncodrive3d/dist /oncodrive3d/dist
|
|
|
30
30
|
WORKDIR /oncodrive3d
|
|
31
31
|
|
|
32
32
|
# Install oncodrive3d
|
|
33
|
-
RUN pip install
|
|
33
|
+
RUN pip install dist/*.tar.gz
|
|
34
34
|
|
|
35
35
|
# Create required directories
|
|
36
36
|
RUN install -d -m 0755 "$BGDATA_LOCAL" "$BBGLAB_HOME"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Oncodrive3D
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.7
|
|
4
4
|
Summary: Oncodrive3D is a method designed to analyse patterns of somatic mutations across tumors to identify three-dimensional (3D) clusters of missense mutations and detect genes that are under positive selection.
|
|
5
5
|
Project-URL: Homepage, https://github.com/bbglab/clustering_3d
|
|
6
6
|
Project-URL: Repository, https://github.com/bbglab/clustering_3d
|
|
@@ -37,14 +37,15 @@ Description-Content-Type: text/markdown
|
|
|
37
37
|
|
|
38
38
|
**Oncodrive3D** is a fast and accurate computational method designed to analyze patterns of somatic mutation across tumors, with the goal of identifying **three-dimensional (3D) clusters** of missense mutations and detecting genes under **positive selection**.
|
|
39
39
|
|
|
40
|
-
The method leverages **AlphaFold 2-predicted protein structures** and Predicted Aligned Error (PAE) to define residue contacts within the protein's 3D space. When available, it integrates **mutational profiles** to build an accurate background model of neutral mutagenesis. By applying a novel **rank-based statistical approach**, Oncodrive3D scores potential 3D clusters and computes empirical p-values.
|
|
40
|
+
The method leverages **AlphaFold 2-predicted protein structures** and Predicted Aligned Error (PAE) to define residue contacts within the protein's 3D space. When available, it integrates **mutational profiles** to build an accurate background model of neutral mutagenesis. By applying a novel **rank-based statistical approach**, Oncodrive3D scores potential 3D clusters and computes empirical p-values.
|
|
41
41
|
|
|
42
42
|
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
43
43
|
[](https://hub.docker.com/r/bbglab/oncodrive3d)
|
|
44
44
|
[](https://pypi.org/project/Oncodrive3D/)
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+

|
|
47
47
|
|
|
48
|
+
---
|
|
48
49
|
|
|
49
50
|
## Requirements
|
|
50
51
|
|
|
@@ -118,6 +119,13 @@ Options:
|
|
|
118
119
|
Default: human
|
|
119
120
|
-m, --mane Use structures predicted from MANE Select transcripts
|
|
120
121
|
(applicable to Homo sapiens only).
|
|
122
|
+
-M, --mane_only Use only structures predicted from MANE Select transcripts
|
|
123
|
+
(applicable to Homo sapiens only).
|
|
124
|
+
-C, --custom_mane_pdb_dir Path to directory containing custom MANE PDB structures.
|
|
125
|
+
Default: None
|
|
126
|
+
-f, --custom_mane_metadata_path Path to a dataframe (typically a samplesheet.csv) including
|
|
127
|
+
Ensembl IDs and sequences of the custom pdbs.
|
|
128
|
+
Default: None
|
|
121
129
|
-d, --distance_threshold INT Distance threshold (Å) for defining residues contacts.
|
|
122
130
|
Default: 10
|
|
123
131
|
-c, --cores INT Number of CPU cores for computation.
|
|
@@ -128,6 +136,25 @@ Options:
|
|
|
128
136
|
|
|
129
137
|
For more information on the output of this step, please refer to the [Building Datasets Output Documentation](https://github.com/bbglab/oncodrive3d/tree/master/docs/build_output.md).
|
|
130
138
|
|
|
139
|
+
> [!TIP]
|
|
140
|
+
> ### Increasing MANE Structural Coverage
|
|
141
|
+
> To maximize structural coverage of **MANE Select transcripts**, you can predict missing structures locally and integrate them into Oncodrive3D using:
|
|
142
|
+
>
|
|
143
|
+
> - `tools/preprocessing/prepare_samplesheet.py`: a standalone utility that:
|
|
144
|
+
> - Retrieve the full MANE entries from NCBI.
|
|
145
|
+
> - Identifies proteins missing from the AlphaFold MANE dataset.
|
|
146
|
+
> - Generates:
|
|
147
|
+
> - A `samplesheet.csv` with Ensembl protein IDs, FASTA paths, and optional sequences.
|
|
148
|
+
> - Individual FASTA files for each missing protein.
|
|
149
|
+
>
|
|
150
|
+
> - `--custom_mane_pdb_dir`: use this to provide your own predicted PDB structures (e.g., from [nf-core/proteinfold](https://nf-co.re/proteinfold/1.1.1/)).
|
|
151
|
+
>
|
|
152
|
+
> - `--custom_mane_metadata_path`: path to the corresponding `samplesheet.csv`, which must include:
|
|
153
|
+
> - `sequence`: Ensembl protein ID (required)
|
|
154
|
+
> - `refseq`: amino acid sequence (used to inject sequence into PDB if missing)
|
|
155
|
+
>
|
|
156
|
+
|
|
157
|
+
|
|
131
158
|
|
|
132
159
|
## Running 3D clustering Analysis
|
|
133
160
|
|
|
@@ -305,4 +332,4 @@ Oncodrive3D is available to the general public subject to certain conditions des
|
|
|
305
332
|
|
|
306
333
|
|
|
307
334
|
## Citation
|
|
308
|
-
If you use Oncodrive3D in your research, please cite the original paper: [Oncodrive3D:
|
|
335
|
+
If you use Oncodrive3D in your research, please cite the original paper: [Oncodrive3D: fast and accurate detection of structural clusters of somatic mutations under positive selection](https://academic.oup.com/nar/article/53/15/gkaf776/8234003).
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
**Oncodrive3D** is a fast and accurate computational method designed to analyze patterns of somatic mutation across tumors, with the goal of identifying **three-dimensional (3D) clusters** of missense mutations and detecting genes under **positive selection**.
|
|
4
4
|
|
|
5
|
-
The method leverages **AlphaFold 2-predicted protein structures** and Predicted Aligned Error (PAE) to define residue contacts within the protein's 3D space. When available, it integrates **mutational profiles** to build an accurate background model of neutral mutagenesis. By applying a novel **rank-based statistical approach**, Oncodrive3D scores potential 3D clusters and computes empirical p-values.
|
|
5
|
+
The method leverages **AlphaFold 2-predicted protein structures** and Predicted Aligned Error (PAE) to define residue contacts within the protein's 3D space. When available, it integrates **mutational profiles** to build an accurate background model of neutral mutagenesis. By applying a novel **rank-based statistical approach**, Oncodrive3D scores potential 3D clusters and computes empirical p-values.
|
|
6
6
|
|
|
7
7
|
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
8
8
|
[](https://hub.docker.com/r/bbglab/oncodrive3d)
|
|
9
9
|
[](https://pypi.org/project/Oncodrive3D/)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+

|
|
12
12
|
|
|
13
|
+
---
|
|
13
14
|
|
|
14
15
|
## Requirements
|
|
15
16
|
|
|
@@ -83,6 +84,13 @@ Options:
|
|
|
83
84
|
Default: human
|
|
84
85
|
-m, --mane Use structures predicted from MANE Select transcripts
|
|
85
86
|
(applicable to Homo sapiens only).
|
|
87
|
+
-M, --mane_only Use only structures predicted from MANE Select transcripts
|
|
88
|
+
(applicable to Homo sapiens only).
|
|
89
|
+
-C, --custom_mane_pdb_dir Path to directory containing custom MANE PDB structures.
|
|
90
|
+
Default: None
|
|
91
|
+
-f, --custom_mane_metadata_path Path to a dataframe (typically a samplesheet.csv) including
|
|
92
|
+
Ensembl IDs and sequences of the custom pdbs.
|
|
93
|
+
Default: None
|
|
86
94
|
-d, --distance_threshold INT Distance threshold (Å) for defining residues contacts.
|
|
87
95
|
Default: 10
|
|
88
96
|
-c, --cores INT Number of CPU cores for computation.
|
|
@@ -93,6 +101,25 @@ Options:
|
|
|
93
101
|
|
|
94
102
|
For more information on the output of this step, please refer to the [Building Datasets Output Documentation](https://github.com/bbglab/oncodrive3d/tree/master/docs/build_output.md).
|
|
95
103
|
|
|
104
|
+
> [!TIP]
|
|
105
|
+
> ### Increasing MANE Structural Coverage
|
|
106
|
+
> To maximize structural coverage of **MANE Select transcripts**, you can predict missing structures locally and integrate them into Oncodrive3D using:
|
|
107
|
+
>
|
|
108
|
+
> - `tools/preprocessing/prepare_samplesheet.py`: a standalone utility that:
|
|
109
|
+
> - Retrieve the full MANE entries from NCBI.
|
|
110
|
+
> - Identifies proteins missing from the AlphaFold MANE dataset.
|
|
111
|
+
> - Generates:
|
|
112
|
+
> - A `samplesheet.csv` with Ensembl protein IDs, FASTA paths, and optional sequences.
|
|
113
|
+
> - Individual FASTA files for each missing protein.
|
|
114
|
+
>
|
|
115
|
+
> - `--custom_mane_pdb_dir`: use this to provide your own predicted PDB structures (e.g., from [nf-core/proteinfold](https://nf-co.re/proteinfold/1.1.1/)).
|
|
116
|
+
>
|
|
117
|
+
> - `--custom_mane_metadata_path`: path to the corresponding `samplesheet.csv`, which must include:
|
|
118
|
+
> - `sequence`: Ensembl protein ID (required)
|
|
119
|
+
> - `refseq`: amino acid sequence (used to inject sequence into PDB if missing)
|
|
120
|
+
>
|
|
121
|
+
|
|
122
|
+
|
|
96
123
|
|
|
97
124
|
## Running 3D clustering Analysis
|
|
98
125
|
|
|
@@ -270,4 +297,4 @@ Oncodrive3D is available to the general public subject to certain conditions des
|
|
|
270
297
|
|
|
271
298
|
|
|
272
299
|
## Citation
|
|
273
|
-
If you use Oncodrive3D in your research, please cite the original paper: [Oncodrive3D:
|
|
300
|
+
If you use Oncodrive3D in your research, please cite the original paper: [Oncodrive3D: fast and accurate detection of structural clusters of somatic mutations under positive selection](https://academic.oup.com/nar/article/53/15/gkaf776/8234003).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Output
|
|
2
|
+
|
|
3
|
+
After successfully completing this step, the build folder must include the following files and directories:
|
|
4
|
+
|
|
5
|
+
- **pae/**: Directory including the AlphaFold predicted aligned error (PAE) for any protein of the proteome with a length lower than 2700 amino acids
|
|
6
|
+
|
|
7
|
+
- **prob_cmaps/**: Directory including the contact probability map (pCMAPs) for any protein of the proteome
|
|
8
|
+
|
|
9
|
+
- **confidence.csv**: CSV file including per-residue predicted local distance difference test (pLDDT) score for any protein of the proteome
|
|
10
|
+
|
|
11
|
+
- **seq_for_mut_prob.csv**: CSV file including HUGO symbol, Uniprot ID, DNA and protein sequences for any proteine of the proteome
|
|
12
|
+
|
|
13
|
+
- **pdb_structures/**: Directory containing all PDB structure files—both those downloaded from the AlphaFold database and any custom in-house predicted structures (if provided).
|
|
14
|
+
|
|
15
|
+
- **log/**: Directory containing log files produced during the build-datasets execution.
|
|
16
|
+
|
|
17
|
+
- **biomart_metadata.csv**: Metadata file from Ensembl BioMart used to prioritize canonical transcripts when multiple transcripts map to the same protein structure.
|
|
18
|
+
|
|
19
|
+
...
|
|
Binary file
|
|
@@ -176,7 +176,7 @@ It includes the following fields:
|
|
|
176
176
|
- **C_pos**: List of protein positions of the gene clusters.
|
|
177
177
|
- **C_label**: List of labels indicating the clump to which each cluster is grouped.
|
|
178
178
|
- **Pos_top_vol**: Position of the most significant cluster.
|
|
179
|
-
- **Score_obs_sim_top_vol**: 3D clustering score of the gene (
|
|
179
|
+
- **Score_obs_sim_top_vol**: 3D clustering score of the gene (rescaled 3D clustering score of the residue with the lowest p-value; if multiple residues have the same lowest p-value, the maximum rescaled 3D clustering score among those residues is used).
|
|
180
180
|
- **Mut_in_gene**: Number of missense mutations in the gene.
|
|
181
181
|
- **Clust_mut**: Number of missense mutations in significant clusters.
|
|
182
182
|
- **Clust_res**: Number of residues detected as significant clusters.
|
|
@@ -227,12 +227,12 @@ It includes the following fields:
|
|
|
227
227
|
- **Mut_in_res**: Number of missense mutations in the residue.
|
|
228
228
|
- **Mut_in_vol**: Number of missense mutations in the volume of the residue.
|
|
229
229
|
- **Score**: 3D clustering score for the residue.
|
|
230
|
-
- **Score_obs_sim**:
|
|
230
|
+
- **Score_obs_sim**: Rescaled 3D clustering score for the residue.
|
|
231
231
|
- **pval**: The p-value of the residue in the 3D clustering analysis.
|
|
232
232
|
- **C**: Binary label indicating whether the cluster at that residue is significant (1) or not (0). A cluster is marked as significant either because it meets the significance criteria directly or because it has been rescued by contributing mutations to another significant cluster.
|
|
233
233
|
- **C_ext**: Binary label indicating whether the cluster has been rescued by contributing mutations to another significant cluster (1) or if it was significant on its own (0).
|
|
234
234
|
- **Clump**: Identifier for the clump to which the cluster at that residue has been assigned.
|
|
235
|
-
- **Rank**: Rank used to perform the calculation of the
|
|
235
|
+
- **Rank**: Rank used to perform the calculation of the 3D clustering score and p-values.
|
|
236
236
|
- **Mut_in_cl_vol**: Number of missense mutations in the clusters of the clump to which the cluster has been assigned.
|
|
237
237
|
- **Res_in_cl**: Positions of the clusters of the clump to which the cluster has been assigned.
|
|
238
238
|
- **PAE_vol**: Weighted average predicted aligned error (PAE) of the residues in the volume of the cluster.
|
|
@@ -29,7 +29,7 @@ Run a test to ensure that everything is set up correctly and functioning as expe
|
|
|
29
29
|
nextflow run main.nf -profile test,container --data_dir <build_folder>
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
Replace `<build_folder>` with the path to the Oncodrive3D datasets built in the [building datasets](#building-datasets) step.
|
|
32
|
+
Replace `<build_folder>` with the path to the Oncodrive3D datasets built in the [building datasets](../README.md#building-datasets) step.
|
|
33
33
|
If you prefer to use Conda, replace `container` in the `-profile` argument with `conda`.
|
|
34
34
|
|
|
35
35
|
## Usage
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__logger_name__ = 'oncodrive3d'
|
|
2
|
-
__version__ = "1.0.
|
|
2
|
+
__version__ = "1.0.7"
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module to generate datasets necessary to run Oncodrive3D.
|
|
3
|
+
|
|
4
|
+
The build is a pipeline that perform the following tasks:
|
|
5
|
+
- Download the PDB structures of the selected proteome
|
|
6
|
+
predicted by AlphaFold 2 from AlphaFold DB.
|
|
7
|
+
- Merge the overlapping structures processed as fragments.
|
|
8
|
+
- Optionally download the PDB structures corresponding to
|
|
9
|
+
the MANE Select transcripts.
|
|
10
|
+
- Optionally copy and parse custom PDB structures.
|
|
11
|
+
- Generate a dataframe including Uniprot_ID, HUGO Symbol,
|
|
12
|
+
protein, DNA sequence, and other gene's information.
|
|
13
|
+
- Extract AlphaFold model confidence (pLDDT).
|
|
14
|
+
- Download AlphaFold predicted aligned error (PAE) from
|
|
15
|
+
AlphaFold DB and convert the files into npy format.
|
|
16
|
+
- Use the PDB structure and PAE to create maps of
|
|
17
|
+
probability of contacts (pCMAPs) for any protein of the
|
|
18
|
+
downloaded proteome with available PAE.
|
|
19
|
+
- Remove unnecessary temp files.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
import os
|
|
24
|
+
import daiquiri
|
|
25
|
+
|
|
26
|
+
from scripts import __logger_name__
|
|
27
|
+
from scripts.datasets.af_merge import merge_af_fragments
|
|
28
|
+
from scripts.datasets.get_pae import get_pae
|
|
29
|
+
from scripts.datasets.get_structures import get_structures, mv_mane_pdb
|
|
30
|
+
from scripts.datasets.model_confidence import get_confidence
|
|
31
|
+
from scripts.datasets.parse_pae import parse_pae
|
|
32
|
+
from scripts.datasets.prob_contact_maps import get_prob_cmaps_mp
|
|
33
|
+
from scripts.datasets.seq_for_mut_prob import get_seq_df
|
|
34
|
+
from scripts.datasets.custom_pdb import copy_and_parse_custom_pdbs
|
|
35
|
+
from scripts.datasets.utils import get_species
|
|
36
|
+
from scripts.globals import clean_dir, clean_temp_files
|
|
37
|
+
|
|
38
|
+
logger = daiquiri.getLogger(__logger_name__ + ".build")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def build(output_datasets,
|
|
42
|
+
organism,
|
|
43
|
+
mane,
|
|
44
|
+
mane_only,
|
|
45
|
+
custom_pdb_dir,
|
|
46
|
+
custom_mane_metadata_path,
|
|
47
|
+
distance_threshold,
|
|
48
|
+
num_cores,
|
|
49
|
+
af_version,
|
|
50
|
+
mane_version):
|
|
51
|
+
"""
|
|
52
|
+
Build datasets necessary to run Oncodrive3D.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
# Empty directory
|
|
56
|
+
clean_dir(output_datasets, 'd', txt_file=True)
|
|
57
|
+
|
|
58
|
+
# Download PDB structures
|
|
59
|
+
species = get_species(organism)
|
|
60
|
+
if not mane_only:
|
|
61
|
+
logger.info("Downloading AlphaFold (AF) predicted structures...")
|
|
62
|
+
get_structures(
|
|
63
|
+
path=os.path.join(output_datasets,"pdb_structures"),
|
|
64
|
+
species=species,
|
|
65
|
+
af_version=str(af_version),
|
|
66
|
+
threads=num_cores
|
|
67
|
+
)
|
|
68
|
+
logger.info("Download of structures completed!")
|
|
69
|
+
|
|
70
|
+
# Merge fragmented structures
|
|
71
|
+
logger.info("Merging fragmented structures...")
|
|
72
|
+
merge_af_fragments(input_dir=os.path.join(output_datasets,"pdb_structures"), gzip=True)
|
|
73
|
+
|
|
74
|
+
# Download PDB MANE structures
|
|
75
|
+
if species == "Homo sapiens" and mane:
|
|
76
|
+
logger.info("Downloading AlphaFold (AF) predicted structures overlap with MANE...")
|
|
77
|
+
get_structures(
|
|
78
|
+
path=os.path.join(output_datasets,"pdb_structures_mane"),
|
|
79
|
+
species=species,
|
|
80
|
+
mane=True,
|
|
81
|
+
threads=num_cores
|
|
82
|
+
)
|
|
83
|
+
mv_mane_pdb(output_datasets, "pdb_structures", "pdb_structures_mane")
|
|
84
|
+
logger.info("Download of MANE structures completed!")
|
|
85
|
+
|
|
86
|
+
# Copy custom PDB structures and optinally add SEQRES
|
|
87
|
+
if custom_pdb_dir is not None:
|
|
88
|
+
if custom_mane_metadata_path is None:
|
|
89
|
+
logger.error(
|
|
90
|
+
"custom_mane_metadata_path must be provided when custom_pdb_dir is specified"
|
|
91
|
+
)
|
|
92
|
+
raise ValueError(
|
|
93
|
+
"Both custom_pdb_dir and custom_mane_metadata_path must be provided together"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
logger.info("Copying custom PDB structures...")
|
|
97
|
+
if os.path.exists(custom_pdb_dir):
|
|
98
|
+
copy_and_parse_custom_pdbs(
|
|
99
|
+
src_dir=custom_pdb_dir,
|
|
100
|
+
dst_dir=os.path.join(output_datasets,"pdb_structures"),
|
|
101
|
+
af_version=int(af_version),
|
|
102
|
+
custom_mane_metadata_path=custom_mane_metadata_path
|
|
103
|
+
)
|
|
104
|
+
else:
|
|
105
|
+
logger.error(f"Custom PDB directory does not exist: {custom_pdb_dir}")
|
|
106
|
+
raise FileNotFoundError(f"Custom PDB directory not found: {custom_pdb_dir}")
|
|
107
|
+
|
|
108
|
+
# Create df including genes and proteins sequences & Hugo to Uniprot_ID mapping
|
|
109
|
+
logger.info("Generating dataframe for genes and proteins sequences...")
|
|
110
|
+
seq_df = get_seq_df(
|
|
111
|
+
datasets_dir=output_datasets,
|
|
112
|
+
output_seq_df=os.path.join(output_datasets, "seq_for_mut_prob.tsv"),
|
|
113
|
+
organism=species,
|
|
114
|
+
mane=mane,
|
|
115
|
+
num_cores=num_cores,
|
|
116
|
+
mane_version=mane_version,
|
|
117
|
+
custom_mane_metadata_path=custom_mane_metadata_path
|
|
118
|
+
)
|
|
119
|
+
logger.info("Generation of sequences dataframe completed!")
|
|
120
|
+
|
|
121
|
+
# Get model confidence
|
|
122
|
+
logger.info("Extracting AF model confidence...")
|
|
123
|
+
get_confidence(
|
|
124
|
+
input=os.path.join(output_datasets, "pdb_structures"),
|
|
125
|
+
output_dir=os.path.join(output_datasets),
|
|
126
|
+
seq_df=seq_df
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Get PAE
|
|
130
|
+
logger.info("Downloading AF predicted aligned error (PAE)...")
|
|
131
|
+
get_pae(
|
|
132
|
+
input_dir=os.path.join(output_datasets,"pdb_structures"),
|
|
133
|
+
output_dir=os.path.join(output_datasets,"pae"),
|
|
134
|
+
num_cores=num_cores,
|
|
135
|
+
af_version=str(af_version),
|
|
136
|
+
custom_pdb_dir=custom_pdb_dir
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# Parse PAE
|
|
140
|
+
logger.info("Parsing PAE...")
|
|
141
|
+
parse_pae(input=os.path.join(output_datasets, 'pae'))
|
|
142
|
+
logger.info("Parsing PAE completed!")
|
|
143
|
+
|
|
144
|
+
# Get pCAMPs
|
|
145
|
+
logger.info("Generating contact probability maps (pCMAPs)..")
|
|
146
|
+
get_prob_cmaps_mp(
|
|
147
|
+
input_pdb=os.path.join(output_datasets, "pdb_structures"),
|
|
148
|
+
input_pae=os.path.join(output_datasets, "pae"),
|
|
149
|
+
output=os.path.join(output_datasets,"prob_cmaps"),
|
|
150
|
+
distance=distance_threshold,
|
|
151
|
+
num_cores=num_cores
|
|
152
|
+
)
|
|
153
|
+
logger.info("Generation pCMAPs completed!")
|
|
154
|
+
|
|
155
|
+
# Clean datasets
|
|
156
|
+
logger.info("Cleaning datasets...")
|
|
157
|
+
clean_temp_files(path=output_datasets)
|
|
158
|
+
logger.info("Datasets cleaning completed!")
|
|
159
|
+
logger.info("Datasets have been successfully built and are ready for analysis!")
|
|
160
|
+
|
|
161
|
+
if __name__ == "__main__":
|
|
162
|
+
build(
|
|
163
|
+
output_datasets="/data/bbg/nobackup/scratch/oncodrive3d/mane_missing/oncodrive3d/datasets/datasets-mane_only-mane_custom-250729",
|
|
164
|
+
organism="Homo sapiens",
|
|
165
|
+
mane=False,
|
|
166
|
+
mane_only=True,
|
|
167
|
+
custom_pdb_dir="/data/bbg/nobackup/scratch/oncodrive3d/mane_missing/data/250724-no_fragments/all_pdbs-pred_and_retrieved/pdbs",
|
|
168
|
+
custom_mane_metadata_path="/data/bbg/nobackup/scratch/oncodrive3d/mane_missing/data/250724-no_fragments/all_pdbs-pred_and_retrieved/samplesheet.csv",
|
|
169
|
+
distance_threshold=10,
|
|
170
|
+
num_cores=8,
|
|
171
|
+
af_version=4,
|
|
172
|
+
mane_version=1.4
|
|
173
|
+
)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import gzip
|
|
3
|
+
import shutil
|
|
4
|
+
import daiquiri
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from scripts.datasets.utils import get_seq_from_pdb
|
|
7
|
+
|
|
8
|
+
from scripts import __logger_name__
|
|
9
|
+
|
|
10
|
+
logger = daiquiri.getLogger(__logger_name__ + ".build.custom_PDB")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Mapping single-letter to three-letter codes
|
|
14
|
+
one_to_three_res_map = {
|
|
15
|
+
'A':'ALA','C':'CYS','D':'ASP','E':'GLU','F':'PHE','G':'GLY',
|
|
16
|
+
'H':'HIS','I':'ILE','K':'LYS','L':'LEU','M':'MET','N':'ASN',
|
|
17
|
+
'P':'PRO','Q':'GLN','R':'ARG','S':'SER','T':'THR','V':'VAL',
|
|
18
|
+
'W':'TRP','Y':'TYR'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_pdb_seqres_records(lst_res):
|
|
23
|
+
"""
|
|
24
|
+
Given a list of three-letter residue names, construct SEQRES records.
|
|
25
|
+
|
|
26
|
+
:param lst_res: List of residue names (e.g. ['MET','ALA',...])
|
|
27
|
+
:return: List of formatted SEQRES lines ending with '\n'
|
|
28
|
+
"""
|
|
29
|
+
records = []
|
|
30
|
+
num_res = len(lst_res)
|
|
31
|
+
for i in range(0, num_res, 13):
|
|
32
|
+
block = lst_res[i:i+13]
|
|
33
|
+
rec_num = len(records) + 1
|
|
34
|
+
# Atom name block: up to 13 residues separated by spaces, padded to 51 chars
|
|
35
|
+
residues_str = ' '.join(block)
|
|
36
|
+
records.append(
|
|
37
|
+
f"SEQRES {rec_num:>3} A {num_res:>4} {residues_str:<51}\n"
|
|
38
|
+
)
|
|
39
|
+
return records
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def add_seqres_to_pdb(path_pdb: str, residues: list) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Insert SEQRES records at the very top of a PDB file (supports gzipped and plain).
|
|
45
|
+
|
|
46
|
+
:param path_pdb: Path to the PDB file to modify in-place (can be .pdb or .pdb.gz)
|
|
47
|
+
:param residues: List of three-letter residue codes for the sequence
|
|
48
|
+
"""
|
|
49
|
+
# Choose appropriate open functions
|
|
50
|
+
open_in = gzip.open if path_pdb.endswith('.gz') else open
|
|
51
|
+
mode_in = 'rt' if path_pdb.endswith('.gz') else 'r'
|
|
52
|
+
open_out = gzip.open if path_pdb.endswith('.gz') else open
|
|
53
|
+
mode_out = 'wt' if path_pdb.endswith('.gz') else 'w'
|
|
54
|
+
|
|
55
|
+
# Read original lines
|
|
56
|
+
with open_in(path_pdb, mode_in) as fh:
|
|
57
|
+
lines = fh.readlines()
|
|
58
|
+
|
|
59
|
+
# Generate SEQRES lines
|
|
60
|
+
seqres = get_pdb_seqres_records(residues)
|
|
61
|
+
|
|
62
|
+
# Insert at top
|
|
63
|
+
new_lines = seqres + lines
|
|
64
|
+
|
|
65
|
+
# Write back
|
|
66
|
+
with open_out(path_pdb, mode_out) as fh:
|
|
67
|
+
fh.writelines(new_lines)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def copy_and_parse_custom_pdbs(
|
|
71
|
+
src_dir: str,
|
|
72
|
+
dst_dir: str,
|
|
73
|
+
af_version: int = 4,
|
|
74
|
+
custom_mane_metadata_path: str = None
|
|
75
|
+
) -> None:
|
|
76
|
+
"""
|
|
77
|
+
Copy all .pdb files from src_dir to dst_dir, renaming and gzipping them.
|
|
78
|
+
Optionally add residues information (SEQRES) from samplesheet.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
# Ensure destination directory exists
|
|
82
|
+
os.makedirs(dst_dir, exist_ok=True)
|
|
83
|
+
|
|
84
|
+
# Handle metadata
|
|
85
|
+
if custom_mane_metadata_path and os.path.isfile(custom_mane_metadata_path):
|
|
86
|
+
samplesheet_df = pd.read_csv(custom_mane_metadata_path)
|
|
87
|
+
else:
|
|
88
|
+
if not custom_mane_metadata_path:
|
|
89
|
+
logger.warning(
|
|
90
|
+
"No samplesheet path provided; skipping SEQRES insertion for accession %s",
|
|
91
|
+
accession
|
|
92
|
+
)
|
|
93
|
+
else:
|
|
94
|
+
logger.warning(
|
|
95
|
+
"samplesheet not found at '%s'; skipping SEQRES insertion for accession %s",
|
|
96
|
+
custom_mane_metadata_path,
|
|
97
|
+
accession
|
|
98
|
+
)
|
|
99
|
+
samplesheet_df = None
|
|
100
|
+
|
|
101
|
+
# Copy and gzip pdb and optionally add REFSEQ
|
|
102
|
+
for fname in os.listdir(src_dir):
|
|
103
|
+
if not fname.endswith('.pdb'):
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
parts = fname.split('.') # e.g. [ACCESSION, fragment_code, 'alphafold', 'pdb']
|
|
107
|
+
if len(parts) < 4:
|
|
108
|
+
logger.warning(f"Skipping unexpected filename format: {fname}")
|
|
109
|
+
continue
|
|
110
|
+
|
|
111
|
+
accession = parts[0]
|
|
112
|
+
fragment = parts[1]
|
|
113
|
+
|
|
114
|
+
new_name = f'AF-{accession}-F{fragment}-model_v{af_version}.pdb.gz'
|
|
115
|
+
|
|
116
|
+
src_path = os.path.join(src_dir, fname)
|
|
117
|
+
dst_path = os.path.join(dst_dir, new_name)
|
|
118
|
+
|
|
119
|
+
with open(src_path, 'rb') as fin, gzip.open(dst_path, 'wb') as fout:
|
|
120
|
+
shutil.copyfileobj(fin, fout)
|
|
121
|
+
|
|
122
|
+
logger.debug(f'Copied and gzipped: {fname} -> {new_name}')
|
|
123
|
+
|
|
124
|
+
# Optionally add SEQRES records
|
|
125
|
+
if samplesheet_df is not None:
|
|
126
|
+
if accession not in samplesheet_df["sequence"].values:
|
|
127
|
+
logger.warning("Accession %s not in samplesheet %s", accession, custom_mane_metadata_path)
|
|
128
|
+
continue
|
|
129
|
+
seq = samplesheet_df[samplesheet_df["sequence"] == accession].refseq.values[0]
|
|
130
|
+
|
|
131
|
+
if not pd.isna(seq):
|
|
132
|
+
seq = [one_to_three_res_map[aa] for aa in seq]
|
|
133
|
+
add_seqres_to_pdb(path_pdb=dst_path, residues=seq)
|
|
134
|
+
logger.debug(f"Inserted SEQRES records into: {new_name}")
|
|
135
|
+
else:
|
|
136
|
+
try:
|
|
137
|
+
seq = "".join(list(get_seq_from_pdb(dst_path)))
|
|
138
|
+
if not pd.isna(seq):
|
|
139
|
+
logger.debug(f"SEQRES record already present in the structure: {new_name}")
|
|
140
|
+
else:
|
|
141
|
+
logger.warning(f"SEQRES not found in samplesheet and its extraction from structure failed: {new_name}")
|
|
142
|
+
except Exception as e:
|
|
143
|
+
logger.warning(f"SEQRES not found in samplesheet and its extraction from structure failed: {new_name}")
|
|
144
|
+
logger.warning(f"Exception captured: {e}")
|
|
@@ -3,6 +3,7 @@ import os
|
|
|
3
3
|
import daiquiri
|
|
4
4
|
import requests
|
|
5
5
|
import time
|
|
6
|
+
from typing import Optional
|
|
6
7
|
import concurrent.futures
|
|
7
8
|
from tqdm import tqdm
|
|
8
9
|
|
|
@@ -11,14 +12,20 @@ from scripts import __logger_name__
|
|
|
11
12
|
logger = daiquiri.getLogger(__logger_name__ + ".build.PAE")
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
def download_pae(
|
|
15
|
+
def download_pae(
|
|
16
|
+
uniprot_id: str,
|
|
17
|
+
af_version: int,
|
|
18
|
+
output_dir: str,
|
|
19
|
+
max_retries: int = 100
|
|
20
|
+
) -> None:
|
|
15
21
|
"""
|
|
16
22
|
Download Predicted Aligned Error (PAE) file from AlphaFold DB.
|
|
17
23
|
|
|
18
24
|
Args:
|
|
19
|
-
uniprot_id
|
|
20
|
-
af_version
|
|
21
|
-
output_dir
|
|
25
|
+
uniprot_id: Uniprot ID of the structure.
|
|
26
|
+
af_version: AlphaFold 2 version.
|
|
27
|
+
output_dir: Output directory where to download the PAE files.
|
|
28
|
+
max_retries: Break the loop if the download fails too many times.
|
|
22
29
|
"""
|
|
23
30
|
|
|
24
31
|
file_path = os.path.join(output_dir, f"{uniprot_id}-F1-predicted_aligned_error.json")
|
|
@@ -28,6 +35,9 @@ def download_pae(uniprot_id: str, af_version: int, output_dir: str) -> None:
|
|
|
28
35
|
status = "INIT"
|
|
29
36
|
while status != "FINISHED":
|
|
30
37
|
i += 1
|
|
38
|
+
if i > max_retries:
|
|
39
|
+
logger.warning(f"Reached {max_retries} attempts; proceeding without download.")
|
|
40
|
+
break
|
|
31
41
|
if status != "INIT":
|
|
32
42
|
time.sleep(30)
|
|
33
43
|
try:
|
|
@@ -43,7 +53,13 @@ def download_pae(uniprot_id: str, af_version: int, output_dir: str) -> None:
|
|
|
43
53
|
logger.debug(f"Request failed {e}: Retrying")
|
|
44
54
|
|
|
45
55
|
|
|
46
|
-
def get_pae(
|
|
56
|
+
def get_pae(
|
|
57
|
+
input_dir: str,
|
|
58
|
+
output_dir: str,
|
|
59
|
+
num_cores: int,
|
|
60
|
+
af_version: int = 4,
|
|
61
|
+
custom_pdb_dir: Optional[str] = None
|
|
62
|
+
) -> None:
|
|
47
63
|
"""
|
|
48
64
|
Download Predicted Aligned Error (PAE) files for all non-fragmented PDB
|
|
49
65
|
structures in the input directory.
|
|
@@ -53,6 +69,7 @@ def get_pae(input_dir: str, output_dir: str, num_cores: int, af_version: int = 4
|
|
|
53
69
|
output_dir (str): Output directory where to download the PAE files.
|
|
54
70
|
num_cores (int): Number of cores for multithreading download.
|
|
55
71
|
af_version (int): AlphaFold 2 version (default is 4).
|
|
72
|
+
custom_pdb_dir (str | None): Directory including provided custom PDB structures.
|
|
56
73
|
"""
|
|
57
74
|
|
|
58
75
|
if not os.path.exists(output_dir):
|
|
@@ -62,9 +79,14 @@ def get_pae(input_dir: str, output_dir: str, num_cores: int, af_version: int = 4
|
|
|
62
79
|
if os.path.exists(checkpoint):
|
|
63
80
|
logger.debug("PAE already downloaded: Skipping...")
|
|
64
81
|
return
|
|
65
|
-
|
|
82
|
+
|
|
66
83
|
pdb_files = [file for file in os.listdir(input_dir) if file.startswith("AF-") and file.endswith(f"-model_v{af_version}.pdb.gz")]
|
|
67
84
|
uniprot_ids = [pdb_file.split("-")[1] for pdb_file in pdb_files]
|
|
85
|
+
|
|
86
|
+
# Do not download PAE for custom provided structures
|
|
87
|
+
if custom_pdb_dir is not None:
|
|
88
|
+
custom_uniprot_ids = [fname.split('.')[0] for fname in os.listdir(custom_pdb_dir) if fname.endswith('.pdb')]
|
|
89
|
+
uniprot_ids = [uni_id for uni_id in uniprot_ids if uni_id not in custom_uniprot_ids]
|
|
68
90
|
|
|
69
91
|
with concurrent.futures.ThreadPoolExecutor(max_workers=num_cores) as executor:
|
|
70
92
|
tasks = [executor.submit(download_pae, uniprot_id, af_version, output_dir) for uniprot_id in uniprot_ids]
|
|
@@ -22,8 +22,8 @@ def mv_mane_pdb(path_datasets, pdb_dir, mane_pdb_dir) -> None:
|
|
|
22
22
|
|
|
23
23
|
path_pdb = os.path.join(path_datasets, pdb_dir)
|
|
24
24
|
path_mane_pdb = os.path.join(path_datasets, mane_pdb_dir)
|
|
25
|
-
|
|
26
|
-
os.makedirs(
|
|
25
|
+
for path in (path_pdb, path_mane_pdb):
|
|
26
|
+
os.makedirs(path, exist_ok=True)
|
|
27
27
|
|
|
28
28
|
# Move MANE structures
|
|
29
29
|
for filename in [file for file in os.listdir(path_mane_pdb) if file.endswith(".pdb.gz") or file.endswith(".pdb")]:
|
|
@@ -66,6 +66,8 @@ def get_structures(path: str,
|
|
|
66
66
|
# Select proteome
|
|
67
67
|
if mane:
|
|
68
68
|
if species == "Homo sapiens":
|
|
69
|
+
if str(af_version) not in {"3", "4"}:
|
|
70
|
+
raise RuntimeError("AlphaFold MANE overlaps are available only for versions 3 or 4. When using --mane or --mane_only, please set --af_version to 3 or 4.")
|
|
69
71
|
proteome = f"mane_overlap_v{af_version}"
|
|
70
72
|
else:
|
|
71
73
|
raise RuntimeError("Structures with MANE transcripts overlap are available only for 'Homo sapiens'. Exiting...")
|
|
@@ -78,7 +80,7 @@ def get_structures(path: str,
|
|
|
78
80
|
raise RuntimeError(f"Failed to recognize '{species}' as organism. Currently accepted ones are 'Homo sapiens' and 'Mus musculus'. Exiting...")
|
|
79
81
|
|
|
80
82
|
logger.debug(f"Proteome to download: {proteome}")
|
|
81
|
-
af_url = f"https://ftp.ebi.ac.uk/pub/databases/alphafold/
|
|
83
|
+
af_url = f"https://ftp.ebi.ac.uk/pub/databases/alphafold/v{af_version}/{proteome}.tar"
|
|
82
84
|
file_path = os.path.join(path, f"{proteome}.tar")
|
|
83
85
|
|
|
84
86
|
try:
|