mrna-bench 1.0.0__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.
Files changed (44) hide show
  1. mrna_bench-1.0.0/LICENSE +21 -0
  2. mrna_bench-1.0.0/PKG-INFO +160 -0
  3. mrna_bench-1.0.0/README.md +108 -0
  4. mrna_bench-1.0.0/mrna_bench/__init__.py +9 -0
  5. mrna_bench-1.0.0/mrna_bench/data_splitter/__init__.py +0 -0
  6. mrna_bench-1.0.0/mrna_bench/data_splitter/data_splitter.py +53 -0
  7. mrna_bench-1.0.0/mrna_bench/data_splitter/homology_split.py +200 -0
  8. mrna_bench-1.0.0/mrna_bench/data_splitter/sklearn_split.py +31 -0
  9. mrna_bench-1.0.0/mrna_bench/data_splitter/split_catalog.py +11 -0
  10. mrna_bench-1.0.0/mrna_bench/datasets/__init__.py +7 -0
  11. mrna_bench-1.0.0/mrna_bench/datasets/benchmark_dataset.py +134 -0
  12. mrna_bench-1.0.0/mrna_bench/datasets/dataset_catalog.py +20 -0
  13. mrna_bench-1.0.0/mrna_bench/datasets/dataset_utils.py +46 -0
  14. mrna_bench-1.0.0/mrna_bench/datasets/go_mol_func.py +51 -0
  15. mrna_bench-1.0.0/mrna_bench/datasets/lncrna_essentiality.py +25 -0
  16. mrna_bench-1.0.0/mrna_bench/datasets/mrl_sugimoto.py +51 -0
  17. mrna_bench-1.0.0/mrna_bench/datasets/pcg_essentiality.py +25 -0
  18. mrna_bench-1.0.0/mrna_bench/datasets/prot_loc.py +54 -0
  19. mrna_bench-1.0.0/mrna_bench/datasets/rna_hl_human.py +51 -0
  20. mrna_bench-1.0.0/mrna_bench/datasets/rna_hl_mouse.py +51 -0
  21. mrna_bench-1.0.0/mrna_bench/embedder/__init__.py +7 -0
  22. mrna_bench-1.0.0/mrna_bench/embedder/dataset_embedder.py +173 -0
  23. mrna_bench-1.0.0/mrna_bench/embedder/embedder_utils.py +31 -0
  24. mrna_bench-1.0.0/mrna_bench/linear_probe/__init__.py +5 -0
  25. mrna_bench-1.0.0/mrna_bench/linear_probe/linear_probe.py +438 -0
  26. mrna_bench-1.0.0/mrna_bench/loader/__init__.py +0 -0
  27. mrna_bench-1.0.0/mrna_bench/loader/loader.py +48 -0
  28. mrna_bench-1.0.0/mrna_bench/models/__init__.py +7 -0
  29. mrna_bench-1.0.0/mrna_bench/models/aido.py +90 -0
  30. mrna_bench-1.0.0/mrna_bench/models/dnabert.py +76 -0
  31. mrna_bench-1.0.0/mrna_bench/models/embedding_model.py +138 -0
  32. mrna_bench-1.0.0/mrna_bench/models/hyenadna.py +86 -0
  33. mrna_bench-1.0.0/mrna_bench/models/model_catalog.py +20 -0
  34. mrna_bench-1.0.0/mrna_bench/models/nucleotide_transformer.py +104 -0
  35. mrna_bench-1.0.0/mrna_bench/models/orthrus.py +135 -0
  36. mrna_bench-1.0.0/mrna_bench/models/rnafm.py +160 -0
  37. mrna_bench-1.0.0/mrna_bench/utils.py +104 -0
  38. mrna_bench-1.0.0/mrna_bench.egg-info/PKG-INFO +160 -0
  39. mrna_bench-1.0.0/mrna_bench.egg-info/SOURCES.txt +42 -0
  40. mrna_bench-1.0.0/mrna_bench.egg-info/dependency_links.txt +1 -0
  41. mrna_bench-1.0.0/mrna_bench.egg-info/requires.txt +18 -0
  42. mrna_bench-1.0.0/mrna_bench.egg-info/top_level.txt +1 -0
  43. mrna_bench-1.0.0/pyproject.toml +51 -0
  44. mrna_bench-1.0.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Ian Shi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,160 @@
1
+ Metadata-Version: 2.2
2
+ Name: mrna-bench
3
+ Version: 1.0.0
4
+ Summary: Benchmarking suite for mRNA property prediction.
5
+ Author-email: "Ruian (Ian) Shi" <ian.shi@mail.utoronto.ca>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 Ian Shi
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Repository, https://github.com/IanShi1996/mRNABench
29
+ Keywords: mrna,genomic foundation model,benchmark
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Operating System :: Unix
33
+ Requires-Python: >=3.10
34
+ Description-Content-Type: text/markdown
35
+ License-File: LICENSE
36
+ Requires-Dist: tqdm
37
+ Requires-Dist: PyYAML
38
+ Requires-Dist: scikit-learn
39
+ Requires-Dist: numpy<2
40
+ Requires-Dist: pandas<=2.2.2
41
+ Requires-Dist: requests
42
+ Provides-Extra: base-models
43
+ Requires-Dist: torch==2.2.2; extra == "base-models"
44
+ Requires-Dist: transformers==4.29.1; extra == "base-models"
45
+ Requires-Dist: mamba-ssm==1.2.0.post1; extra == "base-models"
46
+ Requires-Dist: rna-fm==0.2.2; extra == "base-models"
47
+ Requires-Dist: accelerate; extra == "base-models"
48
+ Provides-Extra: dev
49
+ Requires-Dist: mypy; extra == "dev"
50
+ Requires-Dist: flake8; extra == "dev"
51
+ Requires-Dist: flake8-docstrings; extra == "dev"
52
+
53
+ # mRNABench
54
+ This repository contains a workflow to benchmark the embedding quality of genomic foundation models on (m)RNA specific tasks. The mRNABench contains a catalogue of datasets and training split logic which can be used to evaluate the embedding quality of several catalogued models.
55
+
56
+ **Jump to:** [Model Catalog](#model-catalog) [Dataset Catalog](#dataset-catalog)
57
+
58
+ ## Setup
59
+ Several configurations of the mRNABench are available.
60
+
61
+ ### Datasets Only
62
+ If you are interested in the benchmark datasets **only**, you can run:
63
+
64
+ ```bash
65
+ pip install mrna-bench
66
+ ```
67
+
68
+ ### Full Version
69
+ The inference-capable version of mRNABench that can generate embeddings using
70
+ Orthrus, DNA-BERT2, NucleotideTransformer, RNA-FM, and HyenaDNA can be
71
+ installed as shown below. Note that this requires PyTorch version 2.2.2 with
72
+ CUDA 12.1 and Triton uninstalled (due to a DNA-BERT2 issue).
73
+ ```bash
74
+ conda create --name mrna_bench python=3.10
75
+ conda activate mrna_bench
76
+
77
+ pip install torch==2.2.2 --index-url https://download.pytorch.org/whl/cu121
78
+ pip install mrna-bench[base_models]
79
+ pip uninstall triton
80
+ ```
81
+ Inference with other models will require the installation of the model's
82
+ dependencies first, which are usually listed on the model's GitHub page (see below).
83
+
84
+ ### Post-install
85
+ After installation, please run the following in Python to set where data associated with the benchmarks will be stored.
86
+ ```python
87
+ import mrna_bench as mb
88
+
89
+ path_to_dir_to_store_data = "DESIRED_PATH"
90
+ mb.update_data_path(path_to_dir_to_store_data)
91
+ ```
92
+
93
+ ## Usage
94
+ Datasets can be retrieved using:
95
+
96
+ ```python
97
+ import mrna_bench as mb
98
+
99
+ dataset = mb.load_dataset("go-mf")
100
+ data_df = dataset.data_df
101
+ ```
102
+
103
+ The mRNABench can also be used to test out common genomic foundation models:
104
+ ```python
105
+ import torch
106
+
107
+ import mrna_bench as mb
108
+ from mrna_bench.embedder import DatasetEmbedder
109
+ from mrna_bench.linear_probe import LinearProbe
110
+
111
+ device = torch.device("cuda")
112
+
113
+ dataset = mb.load_dataset("go-mf")
114
+ model = mb.load_model("Orthrus", "orthrus-large-6-track", device)
115
+
116
+ embedder = DatasetEmbedder(model, dataset)
117
+ embeddings = embedder.embed_dataset()
118
+ embeddings = embeddings.detach().cpu().numpy()
119
+
120
+ prober = LinearProbe(
121
+ dataset=dataset,
122
+ embeddings=embeddings,
123
+ task="multilabel",
124
+ target_col="target",
125
+ split_type="homology"
126
+ )
127
+
128
+ metrics = prober.run_linear_probe()
129
+ print(metrics)
130
+ ```
131
+ Also see the `scripts/` folder for example scripts that uses slurm to embed dataset chunks in parallel for reduce runtime, as well as an example of multi-seed linear probing.
132
+
133
+ ## Model Catalog
134
+ The current models catalogued are:
135
+
136
+ | Model Name | Model Versions | Description | Citation | Supported<br>by<br>`base_models` |
137
+ | :--------: | ---------------------- | ------------- | :------: | :------------------------: |
138
+ | `Orthrus` | `orthrus_large_6_track`<br> `orthrus_base_4_track` | Mamba-based RNA FM pre-trained using contrastive learning. | [code](https://github.com/bowang-lab/Orthrus) [paper](https://www.biorxiv.org/content/10.1101/2024.10.10.617658v2)| ✅ |
139
+ | `AIDO.RNA` | `aido_rna_650m` <br> `aido_rna_650m_cds` <br> `aido_rna_1b600m` <br> `aido_rna_1b600m_cds` | Encoder Transformer-based RNA FM pre-trained using MLM on 42M ncRNA sequences. Version that is domain adapted to CDS is available. | [paper](https://www.biorxiv.org/content/10.1101/2024.11.28.625345v1) | |
140
+ | `RNA-FM` | `rna-fm` <br> `mrna-fm` | Transformer-based RNA FM pre-trained using MLM on 23M ncRNA sequences. mRNA-FM trained on CDS using codon tokenizer. | [github](https://github.com/ml4bio/RNA-FM) | ✅ |
141
+ | `DNABERT2` | `dnabert2` | Transformer-based DNA FM pre-trained using MLM on multispecies genomic dataset. Uses BPE and other modern architectural improvements for efficiency. | [github](https://github.com/MAGICS-LAB/DNABERT_2) | ✅ |
142
+ | `NucleotideTransformer` | `2.5b-multi-species` <br> `2.5b-1000g` <br> `500m-human-ref` <br> `500m-1000g` <br> `v2-50m-multi-species` <br> `v2-100m-multi-species` <br> `v2-250m-multi-species` <br> `v2-500m-multi-species` | Transformer-based DNA FM pre-trained using MLM on a variety of possible datasets at various model sizes. Sequence is tokenized using 6-mers. | [github](https://github.com/instadeepai/nucleotide-transformer) | ✅ |
143
+ | `HyenaDNA` | `hyenadna-large-1m-seqlen-hf` <br> `hyenadna-medium-450k-seqlen-hf` <br> `hyenadna-medium-160k-seqlen-hf` <br> `hyenadna-small-32k-seqlen-hf` <br> `hyenadna-tiny-16k-seqlen-d128-hf` | Hyena-based DNA FM pre-trained using NTP on the human reference genome. Available at various model sizes and pretraining sequence contexts. | [github](https://github.com/HazyResearch/hyena-dna) | ✅ |
144
+
145
+ ### Adding a new model
146
+ All models should inherit from the template `EmbeddingModel`. Each model file should lazily load dependencies within its `__init__` methods so each model can be used individually without install all other models. Models must implement `get_model_short_name(model_version)` which fetches the internal name for the model. This must be unique for every model version and must not contain underscores. Models should implement either `embed_sequence` or `embed_sequence_sixtrack` (see code for method signature). New models should be added to `MODEL_CATALOG`.
147
+
148
+ ## Dataset Catalog
149
+ The current datasets catalogued are:
150
+ | Dataset Name | Catalogue Identifier | Description | Tasks | Citation |
151
+ |---|---|---|---|---|
152
+ | GO Molecular Function | <code>go-mf</code> | Classification of the molecular function of a transcript's product as defined by the GO Resource. | `multilabel` | [website](https://geneontology.org/) |
153
+ | Mean Ribosome Load (Sugimoto) | <code>mrl&#8209;sugimoto</code> | Mean Ribosome Load per transcript isoform as measured in Sugimoto et al. 2022. | `regression` | [paper](https://www.nature.com/articles/s41594-022-00819-2) |
154
+ | RNA Half-life (Human) | <code>rnahl&#8209;human</code> | RNA half-life of human transcripts collected by Agarwal et al. 2022. | `regression` | [paper](https://genomebiology.biomedcentral.com/articles/10.1186/s13059-022-02811-x) |
155
+ | RNA Half-life (Mouse) | <code>rnahl&#8209;mouse</code> | RNA half-life of mouse transcripts collected by Agarwal et al. 2022. | `regression` | [paper](https://genomebiology.biomedcentral.com/articles/10.1186/s13059-022-02811-x) |
156
+ | Protein Subcellular Localization | <code>prot&#8209;loc</code> | Subcellular localization of transcript protein product defined in Protein Atlas. | `multilabel` | [website](https://www.proteinatlas.org/) |
157
+ | Protein Coding Gene Essentiality | <code>pcg&#8209;ess</code> | Essentiality of PCGs as measured by CRISPR knockdown. Log-fold expression and binary essentiality available on several cell lines. | `regression` `classification`| [paper](https://www.cell.com/cell/fulltext/S0092-8674(24)01203-0)|
158
+
159
+ ### Adding a new dataset
160
+ New datasets should inherit from `BenchmarkDataset`. Dataset names cannot contain underscores. Each new dataset should download raw data and process it into a dataframe by overriding `process_raw_data`. This dataframe should store transcript as rows, using string encoding in the `sequence` column. If homology splitting is required, a column `gene` containing gene names is required. Six track embedding also requires columns `cds` and `splice`. The target column can have any name, as it is specified at time of probing. New datasets should be added to `DATASET_CATALOG`.
@@ -0,0 +1,108 @@
1
+ # mRNABench
2
+ This repository contains a workflow to benchmark the embedding quality of genomic foundation models on (m)RNA specific tasks. The mRNABench contains a catalogue of datasets and training split logic which can be used to evaluate the embedding quality of several catalogued models.
3
+
4
+ **Jump to:** [Model Catalog](#model-catalog) [Dataset Catalog](#dataset-catalog)
5
+
6
+ ## Setup
7
+ Several configurations of the mRNABench are available.
8
+
9
+ ### Datasets Only
10
+ If you are interested in the benchmark datasets **only**, you can run:
11
+
12
+ ```bash
13
+ pip install mrna-bench
14
+ ```
15
+
16
+ ### Full Version
17
+ The inference-capable version of mRNABench that can generate embeddings using
18
+ Orthrus, DNA-BERT2, NucleotideTransformer, RNA-FM, and HyenaDNA can be
19
+ installed as shown below. Note that this requires PyTorch version 2.2.2 with
20
+ CUDA 12.1 and Triton uninstalled (due to a DNA-BERT2 issue).
21
+ ```bash
22
+ conda create --name mrna_bench python=3.10
23
+ conda activate mrna_bench
24
+
25
+ pip install torch==2.2.2 --index-url https://download.pytorch.org/whl/cu121
26
+ pip install mrna-bench[base_models]
27
+ pip uninstall triton
28
+ ```
29
+ Inference with other models will require the installation of the model's
30
+ dependencies first, which are usually listed on the model's GitHub page (see below).
31
+
32
+ ### Post-install
33
+ After installation, please run the following in Python to set where data associated with the benchmarks will be stored.
34
+ ```python
35
+ import mrna_bench as mb
36
+
37
+ path_to_dir_to_store_data = "DESIRED_PATH"
38
+ mb.update_data_path(path_to_dir_to_store_data)
39
+ ```
40
+
41
+ ## Usage
42
+ Datasets can be retrieved using:
43
+
44
+ ```python
45
+ import mrna_bench as mb
46
+
47
+ dataset = mb.load_dataset("go-mf")
48
+ data_df = dataset.data_df
49
+ ```
50
+
51
+ The mRNABench can also be used to test out common genomic foundation models:
52
+ ```python
53
+ import torch
54
+
55
+ import mrna_bench as mb
56
+ from mrna_bench.embedder import DatasetEmbedder
57
+ from mrna_bench.linear_probe import LinearProbe
58
+
59
+ device = torch.device("cuda")
60
+
61
+ dataset = mb.load_dataset("go-mf")
62
+ model = mb.load_model("Orthrus", "orthrus-large-6-track", device)
63
+
64
+ embedder = DatasetEmbedder(model, dataset)
65
+ embeddings = embedder.embed_dataset()
66
+ embeddings = embeddings.detach().cpu().numpy()
67
+
68
+ prober = LinearProbe(
69
+ dataset=dataset,
70
+ embeddings=embeddings,
71
+ task="multilabel",
72
+ target_col="target",
73
+ split_type="homology"
74
+ )
75
+
76
+ metrics = prober.run_linear_probe()
77
+ print(metrics)
78
+ ```
79
+ Also see the `scripts/` folder for example scripts that uses slurm to embed dataset chunks in parallel for reduce runtime, as well as an example of multi-seed linear probing.
80
+
81
+ ## Model Catalog
82
+ The current models catalogued are:
83
+
84
+ | Model Name | Model Versions | Description | Citation | Supported<br>by<br>`base_models` |
85
+ | :--------: | ---------------------- | ------------- | :------: | :------------------------: |
86
+ | `Orthrus` | `orthrus_large_6_track`<br> `orthrus_base_4_track` | Mamba-based RNA FM pre-trained using contrastive learning. | [code](https://github.com/bowang-lab/Orthrus) [paper](https://www.biorxiv.org/content/10.1101/2024.10.10.617658v2)| ✅ |
87
+ | `AIDO.RNA` | `aido_rna_650m` <br> `aido_rna_650m_cds` <br> `aido_rna_1b600m` <br> `aido_rna_1b600m_cds` | Encoder Transformer-based RNA FM pre-trained using MLM on 42M ncRNA sequences. Version that is domain adapted to CDS is available. | [paper](https://www.biorxiv.org/content/10.1101/2024.11.28.625345v1) | |
88
+ | `RNA-FM` | `rna-fm` <br> `mrna-fm` | Transformer-based RNA FM pre-trained using MLM on 23M ncRNA sequences. mRNA-FM trained on CDS using codon tokenizer. | [github](https://github.com/ml4bio/RNA-FM) | ✅ |
89
+ | `DNABERT2` | `dnabert2` | Transformer-based DNA FM pre-trained using MLM on multispecies genomic dataset. Uses BPE and other modern architectural improvements for efficiency. | [github](https://github.com/MAGICS-LAB/DNABERT_2) | ✅ |
90
+ | `NucleotideTransformer` | `2.5b-multi-species` <br> `2.5b-1000g` <br> `500m-human-ref` <br> `500m-1000g` <br> `v2-50m-multi-species` <br> `v2-100m-multi-species` <br> `v2-250m-multi-species` <br> `v2-500m-multi-species` | Transformer-based DNA FM pre-trained using MLM on a variety of possible datasets at various model sizes. Sequence is tokenized using 6-mers. | [github](https://github.com/instadeepai/nucleotide-transformer) | ✅ |
91
+ | `HyenaDNA` | `hyenadna-large-1m-seqlen-hf` <br> `hyenadna-medium-450k-seqlen-hf` <br> `hyenadna-medium-160k-seqlen-hf` <br> `hyenadna-small-32k-seqlen-hf` <br> `hyenadna-tiny-16k-seqlen-d128-hf` | Hyena-based DNA FM pre-trained using NTP on the human reference genome. Available at various model sizes and pretraining sequence contexts. | [github](https://github.com/HazyResearch/hyena-dna) | ✅ |
92
+
93
+ ### Adding a new model
94
+ All models should inherit from the template `EmbeddingModel`. Each model file should lazily load dependencies within its `__init__` methods so each model can be used individually without install all other models. Models must implement `get_model_short_name(model_version)` which fetches the internal name for the model. This must be unique for every model version and must not contain underscores. Models should implement either `embed_sequence` or `embed_sequence_sixtrack` (see code for method signature). New models should be added to `MODEL_CATALOG`.
95
+
96
+ ## Dataset Catalog
97
+ The current datasets catalogued are:
98
+ | Dataset Name | Catalogue Identifier | Description | Tasks | Citation |
99
+ |---|---|---|---|---|
100
+ | GO Molecular Function | <code>go-mf</code> | Classification of the molecular function of a transcript's product as defined by the GO Resource. | `multilabel` | [website](https://geneontology.org/) |
101
+ | Mean Ribosome Load (Sugimoto) | <code>mrl&#8209;sugimoto</code> | Mean Ribosome Load per transcript isoform as measured in Sugimoto et al. 2022. | `regression` | [paper](https://www.nature.com/articles/s41594-022-00819-2) |
102
+ | RNA Half-life (Human) | <code>rnahl&#8209;human</code> | RNA half-life of human transcripts collected by Agarwal et al. 2022. | `regression` | [paper](https://genomebiology.biomedcentral.com/articles/10.1186/s13059-022-02811-x) |
103
+ | RNA Half-life (Mouse) | <code>rnahl&#8209;mouse</code> | RNA half-life of mouse transcripts collected by Agarwal et al. 2022. | `regression` | [paper](https://genomebiology.biomedcentral.com/articles/10.1186/s13059-022-02811-x) |
104
+ | Protein Subcellular Localization | <code>prot&#8209;loc</code> | Subcellular localization of transcript protein product defined in Protein Atlas. | `multilabel` | [website](https://www.proteinatlas.org/) |
105
+ | Protein Coding Gene Essentiality | <code>pcg&#8209;ess</code> | Essentiality of PCGs as measured by CRISPR knockdown. Log-fold expression and binary essentiality available on several cell lines. | `regression` `classification`| [paper](https://www.cell.com/cell/fulltext/S0092-8674(24)01203-0)|
106
+
107
+ ### Adding a new dataset
108
+ New datasets should inherit from `BenchmarkDataset`. Dataset names cannot contain underscores. Each new dataset should download raw data and process it into a dataframe by overriding `process_raw_data`. This dataframe should store transcript as rows, using string encoding in the `sequence` column. If homology splitting is required, a column `gene` containing gene names is required. Six track embedding also requires columns `cds` and `splice`. The target column can have any name, as it is specified at time of probing. New datasets should be added to `DATASET_CATALOG`.
@@ -0,0 +1,9 @@
1
+ from mrna_bench.loader.loader import load_model, load_dataset
2
+ from mrna_bench.utils import update_data_path, get_data_path
3
+
4
+ __all__ = [
5
+ "load_model",
6
+ "load_dataset",
7
+ "update_data_path",
8
+ "get_data_path"
9
+ ]
File without changes
@@ -0,0 +1,53 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ import pandas as pd
4
+
5
+
6
+ class DataSplitter(ABC):
7
+ """Generates reproducible train test splits."""
8
+
9
+ @abstractmethod
10
+ def split_df(
11
+ self,
12
+ df: pd.DataFrame,
13
+ test_size: float,
14
+ random_seed: int
15
+ ) -> tuple[pd.DataFrame, pd.DataFrame]:
16
+ """Split dataframe into train and test dataframes.
17
+
18
+ Args:
19
+ df: Dataframe to split.
20
+ test_size: Fraction of dataset to assign to test split.
21
+ random_seed: Random seed used during split sampling.
22
+
23
+ Returns:
24
+ Train and test dataframes.
25
+ """
26
+ pass
27
+
28
+ def get_all_splits_df(
29
+ self,
30
+ df: pd.DataFrame,
31
+ split_ratios: tuple[float, float, float],
32
+ random_seed: int,
33
+ ) -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
34
+ """Get train, validation, test splits.
35
+
36
+ Args:
37
+ df: Dataframe to split.
38
+ split_ratios: Ratio of training, validation, test split size.
39
+ random_seed: Random seed used to generate splits.
40
+
41
+ Returns:
42
+ Dataframe containing training, validation, test splits.
43
+ """
44
+ if sum(split_ratios) != 1:
45
+ raise ValueError("Split ratios must sum to 1.")
46
+
47
+ tv_split_size = split_ratios[1] + split_ratios[2]
48
+ test_split_size = split_ratios[2] / tv_split_size
49
+
50
+ train_df, tv_df = self.split_df(df, tv_split_size, random_seed)
51
+ val_df, test_df = self.split_df(tv_df, test_split_size, random_seed)
52
+
53
+ return train_df, val_df, test_df
@@ -0,0 +1,200 @@
1
+ from pathlib import Path
2
+ import shutil
3
+ import zipfile
4
+
5
+ import pandas as pd
6
+ import numpy as np
7
+
8
+ from mrna_bench import get_data_path
9
+ from mrna_bench.data_splitter.data_splitter import DataSplitter
10
+ from mrna_bench.utils import download_file
11
+
12
+
13
+ def train_test_split_homologous(
14
+ genes: list[str],
15
+ homology_df: pd.DataFrame,
16
+ test_size: float = 0.3,
17
+ random_state: int | None = None
18
+ ) -> tuple[list[int], list[int]]:
19
+ """Split genes into two sets with homologous genes in the same set.
20
+
21
+ Args:
22
+ genes: List of gene names.
23
+ homology_df: DataFrame with columns "gene_name" and "gene_group".
24
+ test_size: Fraction of data allocated to test split.
25
+ random_state: Defaults to None.
26
+
27
+ Returns:
28
+ Dictionary with keys "train_indices" and "test_indices" containing the
29
+ indices of the genes in the train and test sets respectively.
30
+ """
31
+ # Map genes to their respective homology groups
32
+ homo_group_map = homology_df.set_index("gene_name")["gene_group"].to_dict()
33
+
34
+ gene_groups = np.array([homo_group_map.get(gene, None) for gene in genes])
35
+
36
+ group_to_index: dict[int, list[int]] = {}
37
+
38
+ # Populate the group_to_index dictionary
39
+ for i, group in enumerate(gene_groups):
40
+ if group is not None:
41
+ group_to_index.setdefault(group, []).append(i)
42
+
43
+ gene_index = np.arange(len(genes))
44
+
45
+ np.random.seed(random_state)
46
+ np.random.shuffle(gene_index)
47
+
48
+ len_of_train = int(len(gene_index) * (1 - test_size))
49
+
50
+ train_indices: list[int] = []
51
+ test_indices: list[int] = []
52
+
53
+ seen_groups = set()
54
+
55
+ for index in gene_index:
56
+ group = gene_groups[index]
57
+ if group is not None and group in seen_groups:
58
+ continue
59
+
60
+ seen_groups.add(group)
61
+
62
+ if len(train_indices) < len_of_train:
63
+ train_indices.extend(group_to_index.get(group, [index]))
64
+ else:
65
+ test_indices.extend(group_to_index.get(group, [index]))
66
+
67
+ train_indices = [int(ind) for ind in train_indices]
68
+ test_indices = [int(ind) for ind in test_indices]
69
+
70
+ return train_indices, test_indices
71
+
72
+
73
+ class HomologySplitter(DataSplitter):
74
+ """Homology-based data splitter.
75
+
76
+ Uses an external homology mapping file to construct train / test splits.
77
+ Genes which are homologous are kept within the same 'side' of the data
78
+ split to reduce data leakage.
79
+ """
80
+
81
+ HOMO_URL = (
82
+ "https://zenodo.org/records/13910050/files/"
83
+ "homology_maps_homologene.zip"
84
+ )
85
+
86
+ def __init__(
87
+ self,
88
+ species: list[str],
89
+ homology_map_path: str | None = None,
90
+ force_redownload: bool = False
91
+ ):
92
+ """Initialize HomologySplitter.
93
+
94
+ Homology splitting requires a dataframe mapping genes to a group
95
+ of homologous genes. This dataframe must have columns "gene_name" and
96
+ "gene_group". If homology_map_path is not specified, relationships
97
+ processed from homologene will be downloaded.
98
+
99
+ Homology map files should be named as: {species}_homology_map.csv
100
+
101
+ Args:
102
+ species: List of species that genes are from.
103
+ homology_map_path: Path to homology maps.
104
+ force_redownload: Forces redownload of homology maps.
105
+ """
106
+ super().__init__()
107
+
108
+ if homology_map_path is None:
109
+ data_storage_path = get_data_path()
110
+ self.homology_map_path = data_storage_path + "/homology_maps"
111
+
112
+ if not Path(self.homology_map_path).exists():
113
+ Path(self.homology_map_path).mkdir(exist_ok=True)
114
+ force_redownload = True
115
+ else:
116
+ self.homology_map_path = homology_map_path
117
+
118
+ if force_redownload:
119
+ out = download_file(self.HOMO_URL, self.homology_map_path, True)[0]
120
+
121
+ with zipfile.ZipFile(out, "r") as zip_ref:
122
+ for file in zip_ref.namelist():
123
+ if not file.endswith("/"):
124
+ source = zip_ref.open(file)
125
+ path = Path(self.homology_map_path) / Path(file).name
126
+
127
+ with open(path, "wb") as target:
128
+ shutil.copyfileobj(source, target)
129
+
130
+ Path(out).unlink()
131
+
132
+ self.species = species
133
+ self.homology_df = self.get_homology_df()
134
+
135
+ def get_homology_df(self) -> pd.DataFrame:
136
+ """Get homology dataframe for specified species.
137
+
138
+ If multiple species exists, naively merges dataframes, merging homology
139
+ groups if gene name overlap exists.
140
+
141
+ Returns:
142
+ Dataframe with gene names mapped to homology groups.
143
+ """
144
+ species_maps = []
145
+ for s in self.species:
146
+ homology_dir = Path(self.homology_map_path)
147
+ homology_map = homology_dir / "{}_homology_map.csv".format(s)
148
+ if not homology_map.exists():
149
+ print("Homology map for species {} is missing.".format(s))
150
+ else:
151
+ species_maps.append(pd.read_csv(homology_map))
152
+
153
+ max_groups = [max(s_df["gene_group"]) for s_df in species_maps]
154
+ cusum_max_groups = np.cumsum(max_groups)
155
+
156
+ for i, s_df in enumerate(species_maps[1:]):
157
+ s_df["gene_group"] += cusum_max_groups[i]
158
+
159
+ out_df = pd.concat(species_maps, axis=0, ignore_index=True)
160
+
161
+ # Merge identical gene names
162
+ out_df.groupby("gene_name", as_index=False).min()
163
+ out_df.reset_index(drop=True, inplace=True)
164
+
165
+ return out_df
166
+
167
+ def split_df(
168
+ self,
169
+ df: pd.DataFrame,
170
+ test_size: float,
171
+ random_seed: int
172
+ ) -> tuple[pd.DataFrame, pd.DataFrame]:
173
+ """Split dataframe rows into train and test df using homology split.
174
+
175
+ Args:
176
+ df: Dataframe to split.
177
+ test_size: Fraction of dataset to assign to test split.
178
+ random_seed: Random seed used for sampling rows during splitting.
179
+
180
+ Returns:
181
+ Dataframe containing train data and test data.
182
+ """
183
+ if "gene" not in df.columns:
184
+ raise ValueError("Gene must be column for homology split.")
185
+
186
+ genes = df["gene"]
187
+
188
+ train_indices, test_indices = train_test_split_homologous(
189
+ genes,
190
+ self.homology_df,
191
+ test_size,
192
+ random_seed
193
+ )
194
+
195
+ assert len(set(train_indices).intersection(set(test_indices))) == 0
196
+
197
+ train_df = df.iloc[train_indices]
198
+ test_df = df.iloc[test_indices]
199
+
200
+ return train_df, test_df
@@ -0,0 +1,31 @@
1
+ from sklearn.model_selection import train_test_split
2
+
3
+ import pandas as pd
4
+
5
+ from mrna_bench.data_splitter.data_splitter import DataSplitter
6
+
7
+
8
+ class SklearnSplitter(DataSplitter):
9
+ """Wrapper for sklearn train_test_split."""
10
+
11
+ def split_df(
12
+ self,
13
+ df: pd.DataFrame,
14
+ test_size: float,
15
+ random_seed: int
16
+ ) -> tuple[pd.DataFrame, pd.DataFrame]:
17
+ """Split dataframe into train and test split using sklearn.
18
+
19
+ Args:
20
+ df: Dataframe to split.
21
+ test_size: Fraction of dataset to place in test set.
22
+ random_seed: Random seed used during sampling.
23
+
24
+ Return:
25
+ Train and test dataframes.
26
+ """
27
+ return train_test_split(
28
+ df,
29
+ test_size=test_size,
30
+ random_state=random_seed
31
+ )
@@ -0,0 +1,11 @@
1
+ from collections.abc import Callable
2
+
3
+ from mrna_bench.data_splitter.data_splitter import DataSplitter
4
+ from mrna_bench.data_splitter.homology_split import HomologySplitter
5
+ from mrna_bench.data_splitter.sklearn_split import SklearnSplitter
6
+
7
+
8
+ SPLIT_CATALOG: dict[str, Callable[..., DataSplitter]] = {
9
+ "default": SklearnSplitter,
10
+ "homology": HomologySplitter
11
+ }
@@ -0,0 +1,7 @@
1
+ from mrna_bench.datasets.benchmark_dataset import BenchmarkDataset
2
+ from mrna_bench.datasets.dataset_catalog import DATASET_CATALOG
3
+
4
+ __all__ = [
5
+ "BenchmarkDataset",
6
+ "DATASET_CATALOG"
7
+ ]