cellarr 0.4.1.dev1__tar.gz → 0.4.1.dev2__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.
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/PKG-INFO +43 -2
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/README.md +42 -1
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/setup.cfg +2 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/buildutils_tiledb_frame.py +1 -1
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/slurm/README.md +11 -4
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/slurm/build_cellarr_steps.py +65 -33
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/slurm/final_assembly.py +9 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/slurm/finalize_matrix.py +2 -2
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/slurm/process_gene_annotation.py +15 -3
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/slurm/process_matrix.py +11 -3
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/slurm/process_sample_metadata.py +2 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr.egg-info/PKG-INFO +43 -2
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr.egg-info/SOURCES.txt +1 -1
- cellarr-0.4.1.dev2/src/cellarr.egg-info/entry_points.txt +2 -0
- cellarr-0.4.1.dev1/src/cellarr/slurm/build_cellarr_steps_bkp.py +0 -185
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/.coveragerc +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/.github/workflows/pypi-publish.yml +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/.github/workflows/pypi-test.yml +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/.gitignore +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/.pre-commit-config.yaml +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/.readthedocs.yml +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/AUTHORS.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/CHANGELOG.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/CONTRIBUTING.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/LICENSE.txt +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/assets/cellarr.jpg +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/assets/cellarr.png +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/assets/cellarr.svg +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/Makefile +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/_static/.gitignore +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/authors.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/changelog.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/conf.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/contributing.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/index.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/license.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/notes.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/readme.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/requirements.txt +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/docs/tutorial.md +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/pyproject.toml +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/setup.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/CellArrDataset.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/CellArrDatasetSlice.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/__init__.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/autoencoder.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/build_cellarrdataset.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/build_options.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/buildutils_tiledb_array.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/dataloader.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/queryutils_tiledb_frame.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/slurm/__init__.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/slurm/process_cell_metadata.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/slurm/process_matrix_all.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr/utils_anndata.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr.egg-info/dependency_links.txt +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr.egg-info/not-zip-safe +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr.egg-info/requires.txt +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/src/cellarr.egg-info/top_level.txt +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/tests/conftest.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/tests/data/adata.h5ad +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/tests/test_anndata_utils.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/tests/test_build.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/tests/test_custom_config.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/tests/test_dataloader.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/tests/test_query.py +0 -0
- {cellarr-0.4.1.dev1 → cellarr-0.4.1.dev2}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cellarr
|
|
3
|
-
Version: 0.4.1.
|
|
3
|
+
Version: 0.4.1.dev2
|
|
4
4
|
Summary: TileDB-based array storage for genomics data collections.
|
|
5
5
|
Home-page: https://github.com/BiocPy/cellarr
|
|
6
6
|
Author: Jayaram Kancherla
|
|
@@ -45,7 +45,7 @@ datasets but can be generalized to store any 2-dimensional experimental data.
|
|
|
45
45
|
|
|
46
46
|
To get started, install the package from [PyPI](https://pypi.org/project/cellarr/)
|
|
47
47
|
|
|
48
|
-
```
|
|
48
|
+
```sh
|
|
49
49
|
pip install cellarr
|
|
50
50
|
|
|
51
51
|
## to include optional dependencies
|
|
@@ -156,6 +156,47 @@ print(dataset)
|
|
|
156
156
|
|
|
157
157
|
Check out the [documentation](https://biocpy.github.io/cellarr/tutorial.html) for more details.
|
|
158
158
|
|
|
159
|
+
### Building on HPC environments with `slurm`
|
|
160
|
+
|
|
161
|
+
To simplify building TileDB files on HPC environments that use `slurm`, there are a few steps you need to follow.
|
|
162
|
+
|
|
163
|
+
- Step 1: Construct a manifest file
|
|
164
|
+
A minimal manifest file (json) must contain the following fields
|
|
165
|
+
- `"files"`: A list of file path to the input `h5ad` objects.
|
|
166
|
+
- `"python_env"`: A set of commands to activate the Python environment containing this package and its dependencies.
|
|
167
|
+
|
|
168
|
+
Here’s an example of the manifest file:
|
|
169
|
+
```json
|
|
170
|
+
manifest = {
|
|
171
|
+
"files": your/list/of/files,
|
|
172
|
+
"python_env": """
|
|
173
|
+
ml Miniforge3
|
|
174
|
+
conda activate cellarr
|
|
175
|
+
|
|
176
|
+
python --version
|
|
177
|
+
which python
|
|
178
|
+
""",
|
|
179
|
+
"matrix_options": [
|
|
180
|
+
{
|
|
181
|
+
"matrix_name": "non_zero_cells",
|
|
182
|
+
"dtype": "uint32"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"matrix_name": "pseudo_bulk_log_normed",
|
|
186
|
+
"dtype": "float32"
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
For more options, check out the [README](./src/cellarr/slurm/README.md).
|
|
192
|
+
|
|
193
|
+
- Step 2: Submit the job
|
|
194
|
+
Once your manifest file is ready, you can submit the necessary jobs using the `cellarr_build` CLI. Run the following command:
|
|
195
|
+
|
|
196
|
+
```sh
|
|
197
|
+
cellarr_build --input-manifest your/path/to/test_manifest.json --output-dir your/path/to/output --memory-per-job 8 --cpus-per-task 2
|
|
198
|
+
```
|
|
199
|
+
|
|
159
200
|
### Query a `CellArrDataset`
|
|
160
201
|
|
|
161
202
|
Users have the option to reuse the `dataset` object returned when building the dataset or by creating a `CellArrDataset` object by initializing it to the path where the files were created.
|
|
@@ -12,7 +12,7 @@ datasets but can be generalized to store any 2-dimensional experimental data.
|
|
|
12
12
|
|
|
13
13
|
To get started, install the package from [PyPI](https://pypi.org/project/cellarr/)
|
|
14
14
|
|
|
15
|
-
```
|
|
15
|
+
```sh
|
|
16
16
|
pip install cellarr
|
|
17
17
|
|
|
18
18
|
## to include optional dependencies
|
|
@@ -123,6 +123,47 @@ print(dataset)
|
|
|
123
123
|
|
|
124
124
|
Check out the [documentation](https://biocpy.github.io/cellarr/tutorial.html) for more details.
|
|
125
125
|
|
|
126
|
+
### Building on HPC environments with `slurm`
|
|
127
|
+
|
|
128
|
+
To simplify building TileDB files on HPC environments that use `slurm`, there are a few steps you need to follow.
|
|
129
|
+
|
|
130
|
+
- Step 1: Construct a manifest file
|
|
131
|
+
A minimal manifest file (json) must contain the following fields
|
|
132
|
+
- `"files"`: A list of file path to the input `h5ad` objects.
|
|
133
|
+
- `"python_env"`: A set of commands to activate the Python environment containing this package and its dependencies.
|
|
134
|
+
|
|
135
|
+
Here’s an example of the manifest file:
|
|
136
|
+
```json
|
|
137
|
+
manifest = {
|
|
138
|
+
"files": your/list/of/files,
|
|
139
|
+
"python_env": """
|
|
140
|
+
ml Miniforge3
|
|
141
|
+
conda activate cellarr
|
|
142
|
+
|
|
143
|
+
python --version
|
|
144
|
+
which python
|
|
145
|
+
""",
|
|
146
|
+
"matrix_options": [
|
|
147
|
+
{
|
|
148
|
+
"matrix_name": "non_zero_cells",
|
|
149
|
+
"dtype": "uint32"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"matrix_name": "pseudo_bulk_log_normed",
|
|
153
|
+
"dtype": "float32"
|
|
154
|
+
}
|
|
155
|
+
],
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
For more options, check out the [README](./src/cellarr/slurm/README.md).
|
|
159
|
+
|
|
160
|
+
- Step 2: Submit the job
|
|
161
|
+
Once your manifest file is ready, you can submit the necessary jobs using the `cellarr_build` CLI. Run the following command:
|
|
162
|
+
|
|
163
|
+
```sh
|
|
164
|
+
cellarr_build --input-manifest your/path/to/test_manifest.json --output-dir your/path/to/output --memory-per-job 8 --cpus-per-task 2
|
|
165
|
+
```
|
|
166
|
+
|
|
126
167
|
### Query a `CellArrDataset`
|
|
127
168
|
|
|
128
169
|
Users have the option to reuse the `dataset` object returned when building the dataset or by creating a `CellArrDataset` object by initializing it to the path where the files were created.
|
|
@@ -76,7 +76,7 @@ def create_tiledb_frame_from_column_names(
|
|
|
76
76
|
)
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
def create_tiledb_frame_from_dataframe(tiledb_uri_path: str, frame: List[str], column_types=
|
|
79
|
+
def create_tiledb_frame_from_dataframe(tiledb_uri_path: str, frame: List[str], column_types: dict = None):
|
|
80
80
|
"""Create a TileDB file with the provided attributes to persistent storage.
|
|
81
81
|
|
|
82
82
|
This will materialize the array directory and all
|
|
@@ -37,10 +37,17 @@
|
|
|
37
37
|
"cell_type": "ascii",
|
|
38
38
|
"quality_score": "float32"
|
|
39
39
|
},
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
},
|
|
41
|
+
"python_env": """
|
|
42
|
+
. /system/gredit/clientos/etc/profile
|
|
43
|
+
|
|
44
|
+
ml Miniforge3
|
|
45
|
+
conda activate biocpy_miniforge
|
|
46
|
+
|
|
47
|
+
~/.conda/envs/biocpy_miniforge/bin/python --version
|
|
48
|
+
which python
|
|
49
|
+
python --version
|
|
50
|
+
""",
|
|
44
51
|
}
|
|
45
52
|
```
|
|
46
53
|
|
|
@@ -4,7 +4,6 @@ import subprocess
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import Dict, List, Optional, Tuple
|
|
6
6
|
|
|
7
|
-
import anndata
|
|
8
7
|
import numpy as np
|
|
9
8
|
|
|
10
9
|
from cellarr.buildutils_tiledb_array import create_tiledb_array
|
|
@@ -55,7 +54,12 @@ class SlurmBuilder:
|
|
|
55
54
|
self.cpus_per_task = cpus_per_task
|
|
56
55
|
|
|
57
56
|
def create_slurm_script(
|
|
58
|
-
self,
|
|
57
|
+
self,
|
|
58
|
+
job_name: str,
|
|
59
|
+
python_script: str,
|
|
60
|
+
args: Dict,
|
|
61
|
+
dependencies: Optional[str] = None,
|
|
62
|
+
python_env: str = "",
|
|
59
63
|
) -> str:
|
|
60
64
|
"""Create a SLURM job submission script."""
|
|
61
65
|
script = f"""#!/bin/bash
|
|
@@ -70,8 +74,7 @@ class SlurmBuilder:
|
|
|
70
74
|
script += f"#SBATCH --dependency={dependencies}\n"
|
|
71
75
|
|
|
72
76
|
script += f"""
|
|
73
|
-
|
|
74
|
-
conda activate cellarr_env # MODIFY AS NEEDED
|
|
77
|
+
{python_env}
|
|
75
78
|
|
|
76
79
|
python {python_script} '{json.dumps(args)}'
|
|
77
80
|
"""
|
|
@@ -81,7 +84,13 @@ python {python_script} '{json.dumps(args)}'
|
|
|
81
84
|
return script_path
|
|
82
85
|
|
|
83
86
|
def create_array_script(
|
|
84
|
-
self,
|
|
87
|
+
self,
|
|
88
|
+
job_name: str,
|
|
89
|
+
python_script: str,
|
|
90
|
+
args: Dict,
|
|
91
|
+
n_tasks: int,
|
|
92
|
+
dependencies: Optional[str] = None,
|
|
93
|
+
python_env: str = "",
|
|
85
94
|
) -> str:
|
|
86
95
|
"""Create a SLURM array job submission script."""
|
|
87
96
|
script = f"""#!/bin/bash
|
|
@@ -97,8 +106,7 @@ python {python_script} '{json.dumps(args)}'
|
|
|
97
106
|
script += f"#SBATCH --dependency={dependencies}\n"
|
|
98
107
|
|
|
99
108
|
script += f"""
|
|
100
|
-
|
|
101
|
-
conda activate cellarr_env # MODIFY AS NEEDED
|
|
109
|
+
{python_env}
|
|
102
110
|
|
|
103
111
|
python {python_script} '{json.dumps(args)}'
|
|
104
112
|
"""
|
|
@@ -112,7 +120,7 @@ python {python_script} '{json.dumps(args)}'
|
|
|
112
120
|
result = subprocess.run(["sbatch", script_path], capture_output=True, text=True)
|
|
113
121
|
return result.stdout.strip().split()[-1]
|
|
114
122
|
|
|
115
|
-
def submit_gene_annotation_job(self, files: List[str], gene_options: Dict) -> str:
|
|
123
|
+
def submit_gene_annotation_job(self, files: List[str], gene_options: Dict, python_env: str) -> str:
|
|
116
124
|
"""Submit gene annotation processing job."""
|
|
117
125
|
args = {
|
|
118
126
|
"files": files,
|
|
@@ -121,12 +129,19 @@ python {python_script} '{json.dumps(args)}'
|
|
|
121
129
|
"temp_dir": str(self.temp_dir / "gene_annotation"),
|
|
122
130
|
}
|
|
123
131
|
|
|
132
|
+
parent_dir = str(Path(__file__).parent)
|
|
133
|
+
|
|
124
134
|
script_path = self.create_slurm_script(
|
|
125
|
-
job_name="cellarr_gene_annot",
|
|
135
|
+
job_name="cellarr_gene_annot",
|
|
136
|
+
python_script=f"{parent_dir}/process_gene_annotation.py",
|
|
137
|
+
args=args,
|
|
138
|
+
python_env=python_env,
|
|
126
139
|
)
|
|
127
140
|
return self.submit_job(script_path)
|
|
128
141
|
|
|
129
|
-
def submit_sample_metadata_job(
|
|
142
|
+
def submit_sample_metadata_job(
|
|
143
|
+
self, files: List[str], sample_options: Dict, dependency: str, python_env: str
|
|
144
|
+
) -> str:
|
|
130
145
|
"""Submit sample metadata processing job."""
|
|
131
146
|
args = {
|
|
132
147
|
"files": files,
|
|
@@ -135,15 +150,18 @@ python {python_script} '{json.dumps(args)}'
|
|
|
135
150
|
"temp_dir": str(self.temp_dir / "sample_metadata"),
|
|
136
151
|
}
|
|
137
152
|
|
|
153
|
+
parent_dir = str(Path(__file__).parent)
|
|
154
|
+
|
|
138
155
|
script_path = self.create_slurm_script(
|
|
139
156
|
job_name="cellarr_sample_meta",
|
|
140
|
-
python_script="process_sample_metadata.py",
|
|
157
|
+
python_script=f"{parent_dir}/process_sample_metadata.py",
|
|
141
158
|
args=args,
|
|
159
|
+
python_env=python_env,
|
|
142
160
|
# dependencies=f"afterok:{dependency}",
|
|
143
161
|
)
|
|
144
162
|
return self.submit_job(script_path)
|
|
145
163
|
|
|
146
|
-
def submit_cell_metadata_job(self, files: List[str], cell_options: Dict, dependency: str) -> str:
|
|
164
|
+
def submit_cell_metadata_job(self, files: List[str], cell_options: Dict, dependency: str, python_env: str) -> str:
|
|
147
165
|
"""Submit cell metadata processing job."""
|
|
148
166
|
args = {
|
|
149
167
|
"files": files,
|
|
@@ -152,23 +170,21 @@ python {python_script} '{json.dumps(args)}'
|
|
|
152
170
|
"temp_dir": str(self.temp_dir / "cell_metadata"),
|
|
153
171
|
}
|
|
154
172
|
|
|
173
|
+
parent_dir = str(Path(__file__).parent)
|
|
174
|
+
|
|
155
175
|
script_path = self.create_slurm_script(
|
|
156
176
|
job_name="cellarr_cell_meta",
|
|
157
|
-
python_script="process_cell_metadata.py",
|
|
177
|
+
python_script=f"{parent_dir}/process_cell_metadata.py",
|
|
158
178
|
args=args,
|
|
179
|
+
python_env=python_env,
|
|
159
180
|
# dependencies=f"afterok:{dependency}",
|
|
160
181
|
)
|
|
161
182
|
return self.submit_job(script_path)
|
|
162
183
|
|
|
163
|
-
def submit_matrix_processing(
|
|
184
|
+
def submit_matrix_processing(
|
|
185
|
+
self, files: List[str], matrix_options: Dict, dependency: str, python_env: str
|
|
186
|
+
) -> Tuple[str, str]:
|
|
164
187
|
"""Submit matrix processing as SLURM array job."""
|
|
165
|
-
# Calculate cell offsets for each file
|
|
166
|
-
offset = 0
|
|
167
|
-
file_infos = []
|
|
168
|
-
for file in files:
|
|
169
|
-
file_infos.append({"file": file, "offset": offset})
|
|
170
|
-
adata = anndata.read_h5ad(file, backed="r")
|
|
171
|
-
offset += adata.n_obs
|
|
172
188
|
|
|
173
189
|
# Create matrix TileDB array
|
|
174
190
|
matrix_uri = str(self.output_dir / "assays" / matrix_options["matrix_name"])
|
|
@@ -184,16 +200,19 @@ python {python_script} '{json.dumps(args)}'
|
|
|
184
200
|
"temp_dir": str(self.temp_dir / f"matrix_{matrix_options['matrix_name']}"),
|
|
185
201
|
"matrix_options": matrix_options,
|
|
186
202
|
"gene_annotation_file": str(self.temp_dir / "gene_annotation/gene_set.json"),
|
|
187
|
-
"
|
|
203
|
+
"files": files,
|
|
188
204
|
}
|
|
189
205
|
|
|
206
|
+
parent_dir = str(Path(__file__).parent)
|
|
207
|
+
|
|
190
208
|
# Submit array job
|
|
191
209
|
array_script = self.create_array_script(
|
|
192
210
|
job_name=f"matrix_{matrix_options['matrix_name']}",
|
|
193
|
-
python_script="process_matrix.py",
|
|
211
|
+
python_script=f"{parent_dir}/process_matrix.py",
|
|
194
212
|
args=array_args,
|
|
195
213
|
n_tasks=len(files),
|
|
196
214
|
dependencies=f"afterok:{dependency}",
|
|
215
|
+
python_env=python_env,
|
|
197
216
|
)
|
|
198
217
|
array_job_id = self.submit_job(array_script)
|
|
199
218
|
|
|
@@ -202,28 +221,32 @@ python {python_script} '{json.dumps(args)}'
|
|
|
202
221
|
"output_dir": str(self.output_dir),
|
|
203
222
|
"temp_dir": str(self.temp_dir / f"matrix_{matrix_options['matrix_name']}"),
|
|
204
223
|
"matrix_options": matrix_options,
|
|
205
|
-
"
|
|
224
|
+
"files": files,
|
|
206
225
|
}
|
|
207
226
|
|
|
208
227
|
final_script = self.create_slurm_script(
|
|
209
228
|
job_name=f"finalize_matrix_{matrix_options['matrix_name']}",
|
|
210
|
-
python_script="finalize_matrix.py",
|
|
229
|
+
python_script=f"{parent_dir}/finalize_matrix.py",
|
|
211
230
|
args=final_args,
|
|
212
231
|
dependencies=f"afterok:{array_job_id}",
|
|
232
|
+
python_env=python_env,
|
|
213
233
|
)
|
|
214
234
|
final_job_id = self.submit_job(final_script)
|
|
215
235
|
|
|
216
236
|
return array_job_id, final_job_id
|
|
217
237
|
|
|
218
|
-
def submit_final_assembly(self, matrix_names: List[str], dependencies: List[str]) -> str:
|
|
238
|
+
def submit_final_assembly(self, matrix_names: List[str], dependencies: List[str], python_env: str) -> str:
|
|
219
239
|
"""Submit final assembly job."""
|
|
220
240
|
args = {"input_dir": str(self.output_dir), "output_dir": str(self.output_dir), "matrix_names": matrix_names}
|
|
221
241
|
|
|
242
|
+
parent_dir = str(Path(__file__).parent)
|
|
243
|
+
|
|
222
244
|
script_path = self.create_slurm_script(
|
|
223
245
|
job_name="cellarr_final_assembly",
|
|
224
|
-
python_script="final_assembly.py",
|
|
246
|
+
python_script=f"{parent_dir}/final_assembly.py",
|
|
225
247
|
args=args,
|
|
226
248
|
dependencies=f"afterok:{','.join(dependencies)}",
|
|
249
|
+
python_env=python_env,
|
|
227
250
|
)
|
|
228
251
|
return self.submit_job(script_path)
|
|
229
252
|
|
|
@@ -242,8 +265,9 @@ def main():
|
|
|
242
265
|
log_dir = base_dir / "logs"
|
|
243
266
|
temp_dir = base_dir / "temp"
|
|
244
267
|
final_dir = base_dir / "final"
|
|
268
|
+
assays_dir = base_dir / "final/assays"
|
|
245
269
|
|
|
246
|
-
for d in [log_dir, temp_dir, final_dir]:
|
|
270
|
+
for d in [log_dir, temp_dir, final_dir, assays_dir]:
|
|
247
271
|
d.mkdir(parents=True, exist_ok=True)
|
|
248
272
|
|
|
249
273
|
# Read manifest
|
|
@@ -261,13 +285,17 @@ def main():
|
|
|
261
285
|
)
|
|
262
286
|
|
|
263
287
|
# Submit jobs
|
|
264
|
-
gene_job_id = builder.submit_gene_annotation_job(
|
|
288
|
+
gene_job_id = builder.submit_gene_annotation_job(
|
|
289
|
+
manifest["files"], manifest.get("gene_options", {}), manifest["python_env"]
|
|
290
|
+
)
|
|
265
291
|
|
|
266
292
|
sample_job_id = builder.submit_sample_metadata_job(
|
|
267
|
-
manifest["files"], manifest.get("sample_options", {}), gene_job_id
|
|
293
|
+
manifest["files"], manifest.get("sample_options", {}), gene_job_id, manifest["python_env"]
|
|
268
294
|
)
|
|
269
295
|
|
|
270
|
-
cell_job_id = builder.submit_cell_metadata_job(
|
|
296
|
+
cell_job_id = builder.submit_cell_metadata_job(
|
|
297
|
+
manifest["files"], manifest.get("cell_options", {}), sample_job_id, manifest["python_env"]
|
|
298
|
+
)
|
|
271
299
|
|
|
272
300
|
# Process matrices
|
|
273
301
|
matrix_options = manifest.get("matrix_options", [{"matrix_name": "counts"}])
|
|
@@ -276,11 +304,15 @@ def main():
|
|
|
276
304
|
|
|
277
305
|
matrix_job_ids = []
|
|
278
306
|
for matrix_opt in matrix_options:
|
|
279
|
-
_, final_id = builder.submit_matrix_processing(
|
|
307
|
+
_, final_id = builder.submit_matrix_processing(
|
|
308
|
+
manifest["files"], matrix_opt, f"{cell_job_id},{gene_job_id}", manifest["python_env"]
|
|
309
|
+
)
|
|
280
310
|
matrix_job_ids.append(final_id)
|
|
281
311
|
|
|
282
312
|
# Submit final assembly
|
|
283
|
-
builder.submit_final_assembly(
|
|
313
|
+
builder.submit_final_assembly(
|
|
314
|
+
[opt["matrix_name"] for opt in matrix_options], matrix_job_ids, manifest["python_env"]
|
|
315
|
+
)
|
|
284
316
|
|
|
285
317
|
|
|
286
318
|
if __name__ == "__main__":
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import sys
|
|
2
3
|
|
|
3
4
|
from cellarr import CellArrDataset
|
|
4
5
|
|
|
@@ -18,3 +19,11 @@ def final_assembly(args_json: str):
|
|
|
18
19
|
|
|
19
20
|
with open(f"{args['output_dir']}/metadata.json", "w") as f:
|
|
20
21
|
json.dump(metadata, f)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if __name__ == "__main__":
|
|
25
|
+
if len(sys.argv) != 2:
|
|
26
|
+
print("Usage: python final_assembly.py '<json_args>'")
|
|
27
|
+
sys.exit(1)
|
|
28
|
+
|
|
29
|
+
final_assembly(sys.argv[1])
|
|
@@ -15,7 +15,7 @@ def finalize_matrix(args_json: str):
|
|
|
15
15
|
|
|
16
16
|
# Verify all tasks completed
|
|
17
17
|
completed_dir = Path(args["temp_dir"]) / "completed"
|
|
18
|
-
expected_tasks = len(args["
|
|
18
|
+
expected_tasks = len(args["files"])
|
|
19
19
|
completed_tasks = len(list(completed_dir.glob("task_*.json")))
|
|
20
20
|
|
|
21
21
|
if completed_tasks != expected_tasks:
|
|
@@ -30,7 +30,7 @@ def finalize_matrix(args_json: str):
|
|
|
30
30
|
json.dump(
|
|
31
31
|
{
|
|
32
32
|
"matrix_name": args["matrix_options"]["matrix_name"],
|
|
33
|
-
"files_processed": len(args["
|
|
33
|
+
"files_processed": len(args["files"]),
|
|
34
34
|
"uri": matrix_uri,
|
|
35
35
|
},
|
|
36
36
|
f,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import sys
|
|
3
|
+
from pathlib import Path
|
|
2
4
|
|
|
3
5
|
import pandas as pd
|
|
4
6
|
|
|
@@ -15,7 +17,7 @@ def process_gene_annotation(args_json: str):
|
|
|
15
17
|
|
|
16
18
|
# Extract gene information from all files
|
|
17
19
|
files_cache = uad.extract_anndata_info(
|
|
18
|
-
args["files"], var_feature_column=args
|
|
20
|
+
args["files"], var_feature_column=args.get("gene_options", {}).get("feature_column", "index")
|
|
19
21
|
)
|
|
20
22
|
|
|
21
23
|
# Scan for features
|
|
@@ -24,10 +26,20 @@ def process_gene_annotation(args_json: str):
|
|
|
24
26
|
|
|
25
27
|
# Create gene annotation dataframe
|
|
26
28
|
gene_annotation = pd.DataFrame({"cellarr_gene_index": gene_set}, index=gene_set)
|
|
29
|
+
gene_annotation.reset_index(drop=True, inplace=True)
|
|
30
|
+
|
|
31
|
+
# Create TileDB store
|
|
32
|
+
create_tiledb_frame_from_dataframe(f"{args['output_dir']}/gene_annotation", gene_annotation)
|
|
27
33
|
|
|
28
34
|
# Save gene set for later use
|
|
35
|
+
Path(args["temp_dir"]).mkdir(parents=True, exist_ok=True)
|
|
29
36
|
with open(f"{args['temp_dir']}/gene_set.json", "w") as f:
|
|
30
37
|
json.dump(gene_set, f)
|
|
31
38
|
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
if len(sys.argv) != 2:
|
|
42
|
+
print("Usage: python process_gene_annotation.py '<json_args>'")
|
|
43
|
+
sys.exit(1)
|
|
44
|
+
|
|
45
|
+
process_gene_annotation(sys.argv[1])
|
|
@@ -3,6 +3,8 @@ import os
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
+
import tiledb
|
|
7
|
+
|
|
6
8
|
from cellarr import utils_anndata as uad
|
|
7
9
|
from cellarr.buildutils_tiledb_array import write_csr_matrix_to_tiledb
|
|
8
10
|
|
|
@@ -24,9 +26,13 @@ def process_matrix_file(args_json: str):
|
|
|
24
26
|
gene_map = {gene: idx for idx, gene in enumerate(gene_set)}
|
|
25
27
|
|
|
26
28
|
# Get file and offset for this task
|
|
27
|
-
file_info = args["
|
|
28
|
-
input_file = file_info
|
|
29
|
-
|
|
29
|
+
file_info = args["files"][task_id]
|
|
30
|
+
input_file = file_info
|
|
31
|
+
|
|
32
|
+
# get sample offset
|
|
33
|
+
sample_uri = tiledb.open(f"{args['output_dir']}/sample_metadata", "r")
|
|
34
|
+
sample_row = sample_uri.df[task_id]
|
|
35
|
+
row_offset = sample_row["cellarr_sample_start_index"]
|
|
30
36
|
|
|
31
37
|
# Process the file
|
|
32
38
|
matrix = uad.remap_anndata(input_file, gene_map, layer_matrix_name=args["matrix_options"]["matrix_name"])
|
|
@@ -36,6 +42,8 @@ def process_matrix_file(args_json: str):
|
|
|
36
42
|
write_csr_matrix_to_tiledb(matrix_uri, matrix[args["matrix_options"]["matrix_name"]], row_offset=row_offset)
|
|
37
43
|
|
|
38
44
|
# Save task completion marker
|
|
45
|
+
Path(args["temp_dir"]).mkdir(parents=True, exist_ok=True)
|
|
46
|
+
Path(args["temp_dir"] + "/completed").mkdir(parents=True, exist_ok=True)
|
|
39
47
|
task_marker = Path(args["temp_dir"]) / "completed" / f"task_{task_id}.json"
|
|
40
48
|
task_marker.parent.mkdir(exist_ok=True)
|
|
41
49
|
with open(task_marker, "w") as f:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import sys
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
|
|
4
5
|
import pandas as pd
|
|
5
6
|
|
|
@@ -64,6 +65,7 @@ def process_sample_metadata(args_json: str):
|
|
|
64
65
|
# Save metadata for subsequent steps
|
|
65
66
|
metadata = {"num_samples": len(sample_names), "total_cells": int(sample_metadata["cellarr_cell_counts"].sum())}
|
|
66
67
|
|
|
68
|
+
Path(args["temp_dir"]).mkdir(parents=True, exist_ok=True)
|
|
67
69
|
with open(f"{args['temp_dir']}/sample_metadata.json", "w") as f:
|
|
68
70
|
json.dump(metadata, f)
|
|
69
71
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cellarr
|
|
3
|
-
Version: 0.4.1.
|
|
3
|
+
Version: 0.4.1.dev2
|
|
4
4
|
Summary: TileDB-based array storage for genomics data collections.
|
|
5
5
|
Home-page: https://github.com/BiocPy/cellarr
|
|
6
6
|
Author: Jayaram Kancherla
|
|
@@ -45,7 +45,7 @@ datasets but can be generalized to store any 2-dimensional experimental data.
|
|
|
45
45
|
|
|
46
46
|
To get started, install the package from [PyPI](https://pypi.org/project/cellarr/)
|
|
47
47
|
|
|
48
|
-
```
|
|
48
|
+
```sh
|
|
49
49
|
pip install cellarr
|
|
50
50
|
|
|
51
51
|
## to include optional dependencies
|
|
@@ -156,6 +156,47 @@ print(dataset)
|
|
|
156
156
|
|
|
157
157
|
Check out the [documentation](https://biocpy.github.io/cellarr/tutorial.html) for more details.
|
|
158
158
|
|
|
159
|
+
### Building on HPC environments with `slurm`
|
|
160
|
+
|
|
161
|
+
To simplify building TileDB files on HPC environments that use `slurm`, there are a few steps you need to follow.
|
|
162
|
+
|
|
163
|
+
- Step 1: Construct a manifest file
|
|
164
|
+
A minimal manifest file (json) must contain the following fields
|
|
165
|
+
- `"files"`: A list of file path to the input `h5ad` objects.
|
|
166
|
+
- `"python_env"`: A set of commands to activate the Python environment containing this package and its dependencies.
|
|
167
|
+
|
|
168
|
+
Here’s an example of the manifest file:
|
|
169
|
+
```json
|
|
170
|
+
manifest = {
|
|
171
|
+
"files": your/list/of/files,
|
|
172
|
+
"python_env": """
|
|
173
|
+
ml Miniforge3
|
|
174
|
+
conda activate cellarr
|
|
175
|
+
|
|
176
|
+
python --version
|
|
177
|
+
which python
|
|
178
|
+
""",
|
|
179
|
+
"matrix_options": [
|
|
180
|
+
{
|
|
181
|
+
"matrix_name": "non_zero_cells",
|
|
182
|
+
"dtype": "uint32"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"matrix_name": "pseudo_bulk_log_normed",
|
|
186
|
+
"dtype": "float32"
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
For more options, check out the [README](./src/cellarr/slurm/README.md).
|
|
192
|
+
|
|
193
|
+
- Step 2: Submit the job
|
|
194
|
+
Once your manifest file is ready, you can submit the necessary jobs using the `cellarr_build` CLI. Run the following command:
|
|
195
|
+
|
|
196
|
+
```sh
|
|
197
|
+
cellarr_build --input-manifest your/path/to/test_manifest.json --output-dir your/path/to/output --memory-per-job 8 --cpus-per-task 2
|
|
198
|
+
```
|
|
199
|
+
|
|
159
200
|
### Query a `CellArrDataset`
|
|
160
201
|
|
|
161
202
|
Users have the option to reuse the `dataset` object returned when building the dataset or by creating a `CellArrDataset` object by initializing it to the path where the files were created.
|
|
@@ -42,13 +42,13 @@ src/cellarr/utils_anndata.py
|
|
|
42
42
|
src/cellarr.egg-info/PKG-INFO
|
|
43
43
|
src/cellarr.egg-info/SOURCES.txt
|
|
44
44
|
src/cellarr.egg-info/dependency_links.txt
|
|
45
|
+
src/cellarr.egg-info/entry_points.txt
|
|
45
46
|
src/cellarr.egg-info/not-zip-safe
|
|
46
47
|
src/cellarr.egg-info/requires.txt
|
|
47
48
|
src/cellarr.egg-info/top_level.txt
|
|
48
49
|
src/cellarr/slurm/README.md
|
|
49
50
|
src/cellarr/slurm/__init__.py
|
|
50
51
|
src/cellarr/slurm/build_cellarr_steps.py
|
|
51
|
-
src/cellarr/slurm/build_cellarr_steps_bkp.py
|
|
52
52
|
src/cellarr/slurm/final_assembly.py
|
|
53
53
|
src/cellarr/slurm/finalize_matrix.py
|
|
54
54
|
src/cellarr/slurm/process_cell_metadata.py
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import json
|
|
3
|
-
import os
|
|
4
|
-
import subprocess
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from typing import Dict, Optional
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
__author__ = "Jayaram Kancherla"
|
|
10
|
-
__copyright__ = "Jayaram Kancherla"
|
|
11
|
-
__license__ = "MIT"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def create_slurm_script(
|
|
15
|
-
job_name: str,
|
|
16
|
-
log_dir: str,
|
|
17
|
-
python_script: str,
|
|
18
|
-
args: Dict,
|
|
19
|
-
memory_gb: int = 64,
|
|
20
|
-
time_hours: int = 24,
|
|
21
|
-
cpus_per_task: int = 4,
|
|
22
|
-
dependencies: Optional[str] = None,
|
|
23
|
-
) -> str:
|
|
24
|
-
"""Create SLURM job submission script."""
|
|
25
|
-
script = f"""#!/bin/bash
|
|
26
|
-
#SBATCH --job-name={job_name}
|
|
27
|
-
#SBATCH --output={log_dir}/{job_name}_%j.out
|
|
28
|
-
#SBATCH --error={log_dir}/{job_name}_%j.err
|
|
29
|
-
#SBATCH --time={time_hours}:00:00
|
|
30
|
-
#SBATCH --mem={memory_gb}G
|
|
31
|
-
#SBATCH --cpus-per-task={cpus_per_task}
|
|
32
|
-
"""
|
|
33
|
-
if dependencies:
|
|
34
|
-
script += f"#SBATCH --dependency={dependencies}\n"
|
|
35
|
-
|
|
36
|
-
script += """
|
|
37
|
-
source ~/.bashrc
|
|
38
|
-
conda activate cellarr_env # Modify as needed for your environment
|
|
39
|
-
|
|
40
|
-
python {python_script} '{json.dumps(args)}'
|
|
41
|
-
"""
|
|
42
|
-
script_path = os.path.join(log_dir, f"{job_name}_submit.sh")
|
|
43
|
-
with open(script_path, "w") as f:
|
|
44
|
-
f.write(script)
|
|
45
|
-
return script_path
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def submit_slurm_job(script_path: str, dependency: Optional[str] = None) -> str:
|
|
49
|
-
"""Submit SLURM job and return job ID."""
|
|
50
|
-
cmd = ["sbatch"]
|
|
51
|
-
if dependency:
|
|
52
|
-
cmd.extend(["--dependency", dependency])
|
|
53
|
-
cmd.append(script_path)
|
|
54
|
-
|
|
55
|
-
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
56
|
-
job_id = result.stdout.strip().split()[-1]
|
|
57
|
-
return job_id
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def main():
|
|
61
|
-
parser = argparse.ArgumentParser(description="Build CellArrDataset using SLURM steps")
|
|
62
|
-
parser.add_argument("--input-manifest", required=True, help="Path to JSON manifest file")
|
|
63
|
-
parser.add_argument("--output-dir", required=True, help="Base output directory")
|
|
64
|
-
parser.add_argument("--memory-per-job", type=int, default=64, help="Memory in GB per job")
|
|
65
|
-
parser.add_argument("--time-per-job", type=int, default=24, help="Time in hours per job")
|
|
66
|
-
parser.add_argument("--cpus-per-task", type=int, default=4, help="CPUs per task")
|
|
67
|
-
args = parser.parse_args()
|
|
68
|
-
|
|
69
|
-
# Create output directories
|
|
70
|
-
base_dir = Path(args.output_dir)
|
|
71
|
-
log_dir = base_dir / "logs"
|
|
72
|
-
temp_dir = base_dir / "temp"
|
|
73
|
-
final_dir = base_dir / "final"
|
|
74
|
-
|
|
75
|
-
for d in [log_dir, temp_dir, final_dir]:
|
|
76
|
-
d.mkdir(parents=True, exist_ok=True)
|
|
77
|
-
|
|
78
|
-
# Read manifest file
|
|
79
|
-
with open(args.input_manifest) as f:
|
|
80
|
-
manifest = json.load(f)
|
|
81
|
-
|
|
82
|
-
# Step 1: Gene Annotation Job
|
|
83
|
-
gene_args = {
|
|
84
|
-
"files": manifest["files"],
|
|
85
|
-
"output_dir": str(final_dir),
|
|
86
|
-
"gene_options": manifest.get("gene_options", {}),
|
|
87
|
-
"temp_dir": str(temp_dir / "gene_annotation"),
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
gene_script = create_slurm_script(
|
|
91
|
-
job_name="cellarr_gene_annot",
|
|
92
|
-
log_dir=str(log_dir),
|
|
93
|
-
python_script="process_gene_annotation.py",
|
|
94
|
-
args=gene_args,
|
|
95
|
-
memory_gb=args.memory_per_job,
|
|
96
|
-
cpus_per_task=args.cpus_per_task,
|
|
97
|
-
)
|
|
98
|
-
gene_job_id = submit_slurm_job(gene_script)
|
|
99
|
-
|
|
100
|
-
# Step 2: Sample Metadata Job
|
|
101
|
-
sample_args = {
|
|
102
|
-
"files": manifest["files"],
|
|
103
|
-
"output_dir": str(final_dir),
|
|
104
|
-
"sample_options": manifest.get("sample_options", {}),
|
|
105
|
-
"temp_dir": str(temp_dir / "sample_metadata"),
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
sample_script = create_slurm_script(
|
|
109
|
-
job_name="cellarr_sample_meta",
|
|
110
|
-
log_dir=str(log_dir),
|
|
111
|
-
python_script="process_sample_metadata.py",
|
|
112
|
-
args=sample_args,
|
|
113
|
-
memory_gb=args.memory_per_job,
|
|
114
|
-
cpus_per_task=args.cpus_per_task,
|
|
115
|
-
# dependencies=f"afterok:{gene_job_id}",
|
|
116
|
-
)
|
|
117
|
-
sample_job_id = submit_slurm_job(sample_script)
|
|
118
|
-
|
|
119
|
-
# Step 3: Cell Metadata Job
|
|
120
|
-
cell_args = {
|
|
121
|
-
"files": manifest["files"],
|
|
122
|
-
"output_dir": str(final_dir),
|
|
123
|
-
"cell_options": manifest.get("cell_options", {}),
|
|
124
|
-
"temp_dir": str(temp_dir / "cell_metadata"),
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
cell_script = create_slurm_script(
|
|
128
|
-
job_name="cellarr_cell_meta",
|
|
129
|
-
log_dir=str(log_dir),
|
|
130
|
-
python_script="process_cell_metadata.py",
|
|
131
|
-
args=cell_args,
|
|
132
|
-
memory_gb=args.memory_per_job,
|
|
133
|
-
cpus_per_task=args.cpus_per_task,
|
|
134
|
-
# dependencies=f"afterok:{sample_job_id}",
|
|
135
|
-
)
|
|
136
|
-
cell_job_id = submit_slurm_job(cell_script)
|
|
137
|
-
|
|
138
|
-
# Step 4: Matrix Jobs (one per matrix type)
|
|
139
|
-
matrix_job_ids = []
|
|
140
|
-
matrix_options = manifest.get("matrix_options", [{"matrix_name": "counts"}])
|
|
141
|
-
if not isinstance(matrix_options, list):
|
|
142
|
-
matrix_options = [matrix_options]
|
|
143
|
-
|
|
144
|
-
for matrix_opt in matrix_options:
|
|
145
|
-
matrix_args = {
|
|
146
|
-
"files": manifest["files"],
|
|
147
|
-
"output_dir": str(final_dir),
|
|
148
|
-
"matrix_options": matrix_opt,
|
|
149
|
-
"gene_annotation_file": str(temp_dir / "gene_annotation/gene_set.json"),
|
|
150
|
-
"temp_dir": str(temp_dir / f"matrix_{matrix_opt['matrix_name']}"),
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
matrix_script = create_slurm_script(
|
|
154
|
-
job_name=f"cellarr_matrix_{matrix_opt['matrix_name']}",
|
|
155
|
-
log_dir=str(log_dir),
|
|
156
|
-
python_script="process_matrix.py",
|
|
157
|
-
args=matrix_args,
|
|
158
|
-
memory_gb=args.memory_per_job * 2, # More memory for matrix processing
|
|
159
|
-
cpus_per_task=args.cpus_per_task,
|
|
160
|
-
dependencies=f"afterok:{cell_job_id},{gene_job_id}",
|
|
161
|
-
)
|
|
162
|
-
job_id = submit_slurm_job(matrix_script)
|
|
163
|
-
matrix_job_ids.append(job_id)
|
|
164
|
-
|
|
165
|
-
# Step 5: Final Assembly Job
|
|
166
|
-
final_args = {
|
|
167
|
-
"input_dir": str(final_dir),
|
|
168
|
-
"output_dir": str(final_dir),
|
|
169
|
-
"matrix_names": [opt["matrix_name"] for opt in matrix_options],
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
final_script = create_slurm_script(
|
|
173
|
-
job_name="cellarr_final_assembly",
|
|
174
|
-
log_dir=str(log_dir),
|
|
175
|
-
python_script="final_assembly.py",
|
|
176
|
-
args=final_args,
|
|
177
|
-
memory_gb=args.memory_per_job,
|
|
178
|
-
cpus_per_task=args.cpus_per_task,
|
|
179
|
-
dependencies=f"afterok:{','.join(matrix_job_ids)}",
|
|
180
|
-
)
|
|
181
|
-
submit_slurm_job(final_script)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if __name__ == "__main__":
|
|
185
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|