Build branch openpipeline_spatial/v0.1 with version v0.1.1 to openpipeline_spatial on branch v0.1 (2baba3f)
Build pipeline: openpipelines-bio.openpipeline-spatial.0.1.1-5jtw5
Source commit: 2baba3fff0
Source message: merge main
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -55,4 +55,9 @@ trace*.txt
|
||||
|
||||
# vscode
|
||||
.vscode/launch.json
|
||||
.vscode/settings.json
|
||||
.vscode/settings.json
|
||||
|
||||
# linting
|
||||
renv.lock
|
||||
.Rprofile
|
||||
renv/
|
||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,3 +1,13 @@
|
||||
# openpipeline_spatial 0.1.1
|
||||
|
||||
## MINOR CHANGES
|
||||
|
||||
* Add a README (PR #21).
|
||||
|
||||
## NEW FUNCTIONALITY
|
||||
|
||||
* `convert`: Updated multiple components to accept spatial output bundles in .zip format (for CosMx, Xenium and Aviti) as input (PR #19).
|
||||
|
||||
# openpipeline_spatial 0.1.0
|
||||
|
||||
## NEW FUNCTIONALITY
|
||||
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 openpipelines-bio
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
55
README.md
Normal file
55
README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# OpenPipeline Spatial
|
||||
|
||||
Extensible spatial single cell analysis pipelines for reproducible and large-scale spatial single cell processing using Viash and Nextflow.
|
||||
|
||||
OpenPipeline Spatial extends the [OpenPipeline](https://github.com/openpipelines-bio/openpipeline/) ecosystem with specialized workflows and components for spatial transcriptomics analysis. It provides standardized, reproducible pipelines that are technology-agnostic and can be used for processing spatial omics data from various technologies and platforms.
|
||||
|
||||
[](https://www.viash-hub.com/packages/openpipeline_spatial)
|
||||
[](https://github.com/openpipelines-bio/openpipeline_spatial)
|
||||
[](https://github.com/openpipelines-bio/openpipeline_spatial/blob/main/LICENSE)
|
||||
[](https://github.com/openpipelines-bio/openpipeline_spatial/issues)
|
||||
[](https://viash.io)
|
||||
|
||||
## Functionality
|
||||
|
||||
OpenPipeline Spatial executes a list of predefined tasks specifically designed for spatial omics data. These discrete steps are also provided as standalone components that can be executed individually with a standardized interface.
|
||||
|
||||
The following spatial-specific workflows are provided:
|
||||
|
||||
- [Ingestion](https://www.viash-hub.com/packages/openpipeline_spatial/latest/components?search=mapping): Whereas many technologies generate count matrices on-instrument, functionality is provided for the mapping & quantification of 10X Visum data.
|
||||
- [Interoperability](https://www.viash-hub.com/packages/openpipeline_spatial/latest/components?search=convert): To make sure all spatial workflows are technology-agnostic, functionality is provided to convert count matrices from different technologies (e.g. Xenium, CosMx, AtoMx, Aviti) into a common format (H5MU). In addition, functionality is provided to convert between various Spatial data formats (e.g. Seurat, SpatialExperiment, MuData, SpatialData).
|
||||
- [QC](https://www.viash-hub.com/packages/openpipeline_spatial/latest/components?search=spatial_qc): Calculation of comprehensive quality control metrics.
|
||||
- [Sample Processing](https://www.viash-hub.com/packages/openpipeline_spatial/latest/components?search=spatial_process_samples): Batch processing of multiple spatial samples, including count-based filtering, normalisation and dimensionality reduction.
|
||||
|
||||
## Extended functionality
|
||||
|
||||
Whereas this package only provides spatial-specific functionality, it is designed to work seamlessly with the core [OpenPipeline package](https://github.com/openpipelines-bio/openpipeline/). This means that all core OpenPipeline workflows and components can be used in conjunction with the spatial-specific ones. For example, the [**integration**](https://www.viash-hub.com/packages/openpipeline/latest/components?search=workflows%2Fintegration) and [**cell type annotation**](https://www.viash-hub.com/packages/openpipeline/latest/components?search=workflows%2Fannotation) workflows can be applied to spatial data after it has been processed using the spatial-specific workflows.
|
||||
|
||||
``` mermaid lang="mermaid"
|
||||
flowchart LR
|
||||
demultiplexing["Step 1: Ingestion"]
|
||||
ingestion["Step 2: QC"]
|
||||
process_samples["Step 3: Process Samples"]
|
||||
integration["Step 4: Integration"]
|
||||
downstream["Step 5: Downstream Analysis"]
|
||||
demultiplexing-->ingestion-->process_samples-->integration-->downstream
|
||||
```
|
||||
|
||||
## Execution via CLI or Seqera Cloud
|
||||
|
||||
The openpipeline_spatial package is available via [Viash
|
||||
Hub](https://www.viash-hub.com/packages/openpipeline_spatial/latest/), where
|
||||
you can receive instructions on how to run the end-to-end workflow as
|
||||
well as individual subworkflows or components.
|
||||
|
||||
It’s possible to run the workflow directly from Seqera Cloud. The necessary Nextflow schema files have been [built and provided with the workflows](https://packages.viash-hub.com/vsh/openpipeline_spatial/-/tree/build/main/target/nextflow?ref_type=heads) in order to use the form-based input. However, Seqera Cloud can not deal with multiple-value parameters for batch processing of multiple samples. Therefore, it’s better to use Viash Hub also here for launching the workflow on Seqera Cloud.
|
||||
|
||||
* Navigate to the [Viash Hub package page](https://www.viash-hub.com/packages/openpipeline_spatial/latest/), select the workflow you want to launch and click the `launch` button.
|
||||
* Select the execution environment of choice (e.g. `Seqera Cloud`, `CLI` or `Executable`)
|
||||
* Fill in the form with the required parameters and launch the workflow.
|
||||
|
||||
## Support
|
||||
For issues specific to spatial analysis, please use the [GitHub issues tracker](https://github.com/openpipelines-bio/openpipeline_spatial/issues). For general OpenPipeline questions, refer to the main [OpenPipeline documentation](https://openpipelines.bio/).
|
||||
14
_viash.yaml
14
_viash.yaml
@@ -1,28 +1,22 @@
|
||||
viash_version: 0.9.4
|
||||
version: v0.1.0
|
||||
|
||||
version: v0.1.1
|
||||
source: src
|
||||
target: target
|
||||
|
||||
name: openpipeline_spatial
|
||||
organization: openpipelines-bio
|
||||
|
||||
organization: vsh
|
||||
links:
|
||||
repository: https://github.com/openpipelines-bio/openpipeline_spatial
|
||||
docker_registry: ghcr.io
|
||||
|
||||
repositories:
|
||||
- name: openpipeline
|
||||
repo: openpipeline
|
||||
type: vsh
|
||||
tag: v3.0.0
|
||||
|
||||
info:
|
||||
test_resources:
|
||||
- type: s3
|
||||
path: s3://openpipelines-bio/openpipeline_spatial/resources_test
|
||||
dest: resources_test
|
||||
|
||||
config_mods: |
|
||||
config_mods: |-
|
||||
.resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}
|
||||
.runners[.type == 'nextflow'].config.script := 'includeConfig("nextflow_labels.config")'
|
||||
.runners[.type == 'nextflow'].config.script := 'includeConfig("nextflow_labels.config")'
|
||||
|
||||
@@ -100,6 +100,7 @@ resources:
|
||||
- type: python_script
|
||||
path: script.py
|
||||
- path: /src/utils/setup_logger.py
|
||||
- path: /src/utils/unzip_archived_folder.py
|
||||
|
||||
test_resources:
|
||||
- type: python_script
|
||||
@@ -118,6 +119,9 @@ engines:
|
||||
packages:
|
||||
- pyarrow
|
||||
test_setup:
|
||||
- type: apt
|
||||
packages:
|
||||
- zip
|
||||
- type: python
|
||||
__merge__: [ /src/base/requirements/viashpy.yaml, .]
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import mudata as mu
|
||||
import anndata as ad
|
||||
import re
|
||||
import json
|
||||
import zipfile
|
||||
import os
|
||||
|
||||
## VIASH START
|
||||
par = {
|
||||
@@ -25,6 +27,8 @@ meta = {"resources_dir": "src/utils"}
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import extract_selected_files_from_zip
|
||||
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
@@ -162,27 +166,43 @@ def categorize_columns(column_list, target_panel):
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
# Read data from Aviti Teton output bundle
|
||||
def retrieve_input_data(cells2stats_output_bundle):
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── Cytoprofiling/
|
||||
# │ └── Instrument/
|
||||
# │ └── RawCellStats.parquet
|
||||
# └── Panel.json
|
||||
|
||||
logger.info("Reading input data...")
|
||||
input_dir = Path(par["input"])
|
||||
input_data = {
|
||||
"count_matrix": input_dir
|
||||
/ "Cytoprofiling"
|
||||
/ "Instrument"
|
||||
/ "RawCellStats.parquet",
|
||||
"target_panel": input_dir / "Panel.json",
|
||||
required_file_patterns = {
|
||||
"target_panel": "**/Panel.json",
|
||||
"count_matrix": "**/Cytoprofiling/Instrument/RawCellStats.parquet",
|
||||
}
|
||||
|
||||
assert all([file.exists() for file in input_data.values()]), (
|
||||
f"Not all required input files are found. Make sure that {par['input']} contains {input_data.values()}."
|
||||
if zipfile.is_zipfile(cells2stats_output_bundle):
|
||||
cells2stats_output_bundle = extract_selected_files_from_zip(
|
||||
cells2stats_output_bundle, members=required_file_patterns.values()
|
||||
)
|
||||
else:
|
||||
cells2stats_output_bundle = Path(cells2stats_output_bundle)
|
||||
|
||||
assert os.path.isdir(cells2stats_output_bundle), (
|
||||
"Input is expected to be a (compressed) directory."
|
||||
)
|
||||
|
||||
input_data = {}
|
||||
for key, pattern in required_file_patterns.items():
|
||||
file = list(cells2stats_output_bundle.glob(pattern))
|
||||
assert len(file) == 1, (
|
||||
f"Expected exactly one file matching pattern {pattern}, found {len(file)}."
|
||||
)
|
||||
input_data[key] = file[0]
|
||||
|
||||
return input_data
|
||||
|
||||
|
||||
def main():
|
||||
logger.info("Reading input data...")
|
||||
input_data = retrieve_input_data(par["input"])
|
||||
with open(input_data["target_panel"], "r") as f:
|
||||
target_panel = json.load(f)
|
||||
df = pd.read_parquet(input_data["count_matrix"], engine="pyarrow")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
import sys
|
||||
import mudata as mu
|
||||
import subprocess
|
||||
|
||||
## VIASH START
|
||||
meta = {
|
||||
@@ -51,6 +52,57 @@ def test_simple_execution(run_component, tmp_path):
|
||||
assert all(adata.obsm[obsm].dtype.kind == "f" for obsm in expected_obsm_keys)
|
||||
|
||||
|
||||
def test_compressed_input(run_component, tmp_path):
|
||||
output = tmp_path / "aviti.h5mu"
|
||||
zipped_input = tmp_path / "aviti.zip"
|
||||
|
||||
subprocess.run(
|
||||
["zip", "-r", str(zipped_input), "aviti"], cwd=meta["resources_dir"], check=True
|
||||
)
|
||||
|
||||
# run component
|
||||
run_component(
|
||||
[
|
||||
"--input",
|
||||
zipped_input,
|
||||
"--output",
|
||||
str(output),
|
||||
"--output_compression",
|
||||
"gzip",
|
||||
]
|
||||
)
|
||||
|
||||
assert output.is_file(), "output file was not created"
|
||||
|
||||
mdata = mu.read_h5mu(output)
|
||||
assert list(mdata.mod.keys()) == ["rna"], "Expected modality rna"
|
||||
adata = mdata.mod["rna"]
|
||||
|
||||
assert adata.X.dtype.kind == "f"
|
||||
expected_obs_keys = [
|
||||
"AreaUm",
|
||||
"Area",
|
||||
"Tile",
|
||||
"WellLabel",
|
||||
"Well",
|
||||
"Cell",
|
||||
"NuclearAreaUm",
|
||||
"NuclearArea",
|
||||
]
|
||||
assert all([obs in expected_obs_keys for obs in adata.obs.columns])
|
||||
obs_counts = ["Area", "Cell", "NuclearArea"]
|
||||
assert all([adata.obs[obs].dtype.kind == "u" for obs in obs_counts])
|
||||
obs_areas = ["AreaUm", "NuclearAreaUm"]
|
||||
assert all([adata.obs[obs].dtype.kind == "f" for obs in obs_areas])
|
||||
obs_categories = ["Tile", "WellLabel", "Well"]
|
||||
assert all([adata.obs[obs].dtype.kind == "O" for obs in obs_categories])
|
||||
|
||||
expected_obsm_keys = ["spatial", "spatial_um"]
|
||||
assert list(adata.obsm.keys()) == expected_obsm_keys
|
||||
assert list(adata.uns.keys()) == expected_obsm_keys
|
||||
assert all(adata.obsm[obsm].dtype.kind == "f" for obsm in expected_obsm_keys)
|
||||
|
||||
|
||||
def test_extended_parameters(run_component, tmp_path):
|
||||
output = tmp_path / "aviti_ext.h5mu"
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ resources:
|
||||
- type: python_script
|
||||
path: script.py
|
||||
- path: /src/utils/setup_logger.py
|
||||
- path: /src/utils/unzip_archived_folder.py
|
||||
|
||||
test_resources:
|
||||
- type: python_script
|
||||
path: test.py
|
||||
@@ -53,7 +55,11 @@ engines:
|
||||
- procps
|
||||
- type: python
|
||||
__merge__: [/src/base/requirements/anndata_mudata.yaml, /src/base/requirements/squidpy.yaml]
|
||||
__merge__: [ /src/base/requirements/python_test_setup.yaml, .]
|
||||
test_setup:
|
||||
- type: apt
|
||||
packages:
|
||||
- zip
|
||||
__merge__: [ /src/base/requirements/python_test_setup.yaml, . ]
|
||||
runners:
|
||||
- type: executable
|
||||
- type: nextflow
|
||||
|
||||
@@ -2,11 +2,12 @@ import sys
|
||||
import os
|
||||
import squidpy as sq
|
||||
import mudata as mu
|
||||
import glob
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
## VIASH START
|
||||
par = {
|
||||
"input": "./resources_test/cosmx/Lung5_Rep2_tiny",
|
||||
"input": "./resources_test/cosmx/Lung5_Rep2_tiny.zip",
|
||||
"output": "./resources_test/cosmx/Lung5_Rep2_tiny.h5mu",
|
||||
"modality": "rna",
|
||||
"output_compression": None,
|
||||
@@ -16,28 +17,57 @@ meta = {"resources_dir": "src/utils"}
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import extract_selected_files_from_zip
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
|
||||
def find_matrix_file(suffix):
|
||||
pattern = os.path.join(par["input"], f"*{suffix}")
|
||||
files = glob.glob(pattern)
|
||||
assert len(files) == 1, (
|
||||
f"Only one file matching pattern {pattern} should be present"
|
||||
def retrieve_input_data(cosmx_output_bundle):
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── *_exprMat_file.csv
|
||||
# ├── *_fov_positions_file.csv
|
||||
# └── *_metadata_file.csv
|
||||
|
||||
required_file_patterns = {
|
||||
"counts_file": "**/*exprMat_file.csv",
|
||||
"fov_file": "**/*fov_positions_file.csv",
|
||||
"meta_file": "**/*metadata_file.csv",
|
||||
}
|
||||
if zipfile.is_zipfile(cosmx_output_bundle):
|
||||
cosmx_output_bundle = extract_selected_files_from_zip(
|
||||
cosmx_output_bundle, members=required_file_patterns.values()
|
||||
)
|
||||
else:
|
||||
cosmx_output_bundle = Path(cosmx_output_bundle)
|
||||
|
||||
assert os.path.isdir(cosmx_output_bundle), (
|
||||
"Input is expected to be a (compressed) directory."
|
||||
)
|
||||
return files[0]
|
||||
|
||||
input_data = {}
|
||||
for key, pattern in required_file_patterns.items():
|
||||
file = list(cosmx_output_bundle.glob(pattern))
|
||||
assert len(file) == 1, f"Expected one file for {key}, found {len(file)}."
|
||||
input_data[key] = file[0]
|
||||
|
||||
return input_data
|
||||
|
||||
|
||||
counts_file = find_matrix_file("exprMat_file.csv")
|
||||
fov_file = find_matrix_file("fov_positions_file.csv")
|
||||
meta_file = find_matrix_file("metadata_file.csv")
|
||||
def main():
|
||||
logger.info("Reading in CosMx data...")
|
||||
input_data = retrieve_input_data(par["input"])
|
||||
|
||||
logger.info("Reading in CosMx data...")
|
||||
adata = sq.read.nanostring(
|
||||
path=par["input"], counts_file=counts_file, meta_file=meta_file, fov_file=fov_file
|
||||
)
|
||||
adata = sq.read.nanostring(
|
||||
path=par["input"],
|
||||
counts_file=input_data["counts_file"],
|
||||
meta_file=input_data["meta_file"],
|
||||
fov_file=input_data["fov_file"],
|
||||
)
|
||||
|
||||
logger.info("Writing output MuData object...")
|
||||
mdata = mu.MuData({par["modality"]: adata})
|
||||
mdata.write_h5mu(par["output"], compression=par["output_compression"])
|
||||
logger.info("Writing output MuData object...")
|
||||
mdata = mu.MuData({par["modality"]: adata})
|
||||
mdata.write_h5mu(par["output"], compression=par["output_compression"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
import sys
|
||||
import mudata as mu
|
||||
import subprocess
|
||||
|
||||
|
||||
def test_simple_execution(run_component, tmp_path):
|
||||
@@ -53,5 +54,62 @@ def test_simple_execution(run_component, tmp_path):
|
||||
assert adata.obsm["spatial_fov"].dtype == "float"
|
||||
|
||||
|
||||
def test_compressed_input(run_component, tmp_path):
|
||||
output = tmp_path / "cosmx_tiny.h5mu"
|
||||
zipped_input = tmp_path / "Lung5_Rep2_tiny.zip"
|
||||
|
||||
subprocess.run(
|
||||
["zip", "-r", str(zipped_input), "Lung5_Rep2_tiny"],
|
||||
cwd=meta["resources_dir"],
|
||||
check=True,
|
||||
)
|
||||
|
||||
run_component(
|
||||
[
|
||||
"--input",
|
||||
zipped_input,
|
||||
"--dataset_id",
|
||||
"Lung5_Rep2",
|
||||
"--num_fovs",
|
||||
"2",
|
||||
"--output",
|
||||
output,
|
||||
]
|
||||
)
|
||||
assert output.is_file(), "output file was not created"
|
||||
|
||||
mdata = mu.read_h5mu(output)
|
||||
assert list(mdata.mod.keys()) == ["rna"], "Expected modality rna"
|
||||
|
||||
adata = mdata.mod["rna"]
|
||||
|
||||
assert list(adata.obs.keys()) == [
|
||||
"fov",
|
||||
"Area",
|
||||
"AspectRatio",
|
||||
"CenterX_global_px",
|
||||
"CenterY_global_px",
|
||||
"Width",
|
||||
"Height",
|
||||
"Mean.MembraneStain",
|
||||
"Max.MembraneStain",
|
||||
"Mean.PanCK",
|
||||
"Max.PanCK",
|
||||
"Mean.CD45",
|
||||
"Max.CD45",
|
||||
"Mean.CD3",
|
||||
"Max.CD3",
|
||||
"Mean.DAPI",
|
||||
"Max.DAPI",
|
||||
"cell_ID",
|
||||
]
|
||||
|
||||
assert list(adata.uns.keys()) == ["spatial"]
|
||||
assert list(adata.obsm.keys()) == ["spatial", "spatial_fov"]
|
||||
|
||||
assert adata.obsm["spatial"].dtype == "int"
|
||||
assert adata.obsm["spatial_fov"].dtype == "float"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main([__file__]))
|
||||
|
||||
@@ -58,6 +58,7 @@ arguments:
|
||||
resources:
|
||||
- type: r_script
|
||||
path: script.R
|
||||
- path: /src/utils/unzip_archived_folder.R
|
||||
test_resources:
|
||||
- type: r_script
|
||||
path: test.R
|
||||
|
||||
@@ -2,7 +2,7 @@ library(SpatialExperimentIO)
|
||||
|
||||
### VIASH START
|
||||
par <- list(
|
||||
input = "resources_test/cosmx/Lung5_Rep2_tiny",
|
||||
input = "resources_test/cosmx/test2.zip",
|
||||
add_tx_path = TRUE,
|
||||
add_polygon_path = FALSE,
|
||||
add_fov_positions = TRUE,
|
||||
@@ -11,16 +11,41 @@ par <- list(
|
||||
),
|
||||
output = "spe_cosmx_test.rds"
|
||||
)
|
||||
meta <- list(
|
||||
resources_dir = "src/utils/"
|
||||
)
|
||||
### VIASH END
|
||||
|
||||
source(paste0(meta$resources_dir, "/unzip_archived_folder.R"))
|
||||
|
||||
cat("Reading input data...")
|
||||
if (tools::file_ext(par$input) == "zip") {
|
||||
expected_file_patterns <- c(
|
||||
"*.csv",
|
||||
"*.parquet"
|
||||
)
|
||||
tmp_dir <- extract_selected_files(
|
||||
par$input,
|
||||
members = expected_file_patterns
|
||||
)
|
||||
cosmx_output_bundle <- file.path(
|
||||
tmp_dir,
|
||||
tools::file_path_sans_ext(basename(par$input))
|
||||
)
|
||||
} else {
|
||||
cosmx_output_bundle <- par$input
|
||||
}
|
||||
|
||||
cat("Setting parameters...")
|
||||
if (par$add_polygon_path == FALSE && par$add_tx_path == FALSE) {
|
||||
add_parquet_paths <- FALSE
|
||||
} else {
|
||||
add_parquet_paths <- TRUE
|
||||
}
|
||||
|
||||
cat("Converting to SpatialExperiment...")
|
||||
spe <- readCosmxSXE(
|
||||
dirName = par$input,
|
||||
dirName = cosmx_output_bundle,
|
||||
returnType = "SPE",
|
||||
countMatPattern = "exprMat_file.csv",
|
||||
metaDataPattern = "metadata_file.csv",
|
||||
@@ -33,4 +58,5 @@ spe <- readCosmxSXE(
|
||||
altExps = par$alternative_experiment_features
|
||||
)
|
||||
|
||||
cat("Saving output...")
|
||||
saveRDS(spe, file = par$output)
|
||||
|
||||
@@ -69,6 +69,74 @@ dim_input <- dim(input)
|
||||
expect_equal(dim_rds, dim_input)
|
||||
|
||||
|
||||
cat("> Checking execution with compressed input\n")
|
||||
|
||||
spe <- paste0(meta[["resources_dir"]], "/Lung5_Rep2_tiny")
|
||||
out_rds <- "output.rds"
|
||||
|
||||
create_folder_archive <- function(
|
||||
folder_path,
|
||||
archive = "Lung5_Rep2_tiny.zip") {
|
||||
old_wd <- getwd()
|
||||
on.exit(setwd(old_wd))
|
||||
setwd(meta$resources_dir)
|
||||
system2("zip", c("-r", archive, "Lung5_Rep2_tiny"))
|
||||
paste0(meta$resources_dir, "/", archive)
|
||||
}
|
||||
|
||||
zipped_spe <- create_folder_archive(spe)
|
||||
|
||||
cat("> Running ", meta[["name"]], "\n", sep = "")
|
||||
out <- processx::run(
|
||||
meta[["executable"]],
|
||||
c(
|
||||
"--input", zipped_spe,
|
||||
"--add_tx_path", TRUE,
|
||||
"--add_polygon_path", FALSE,
|
||||
"--output", out_rds
|
||||
)
|
||||
)
|
||||
|
||||
cat("> Checking whether output file exists\n")
|
||||
expect_equal(out$status, 0)
|
||||
expect_true(file.exists(out_rds))
|
||||
|
||||
cat("> Reading output file\n")
|
||||
obj <- readRDS(file = out_rds)
|
||||
|
||||
cat("> Checking whether Seurat object is in the right format\n")
|
||||
# Object type
|
||||
expect_is(obj, "SpatialExperiment")
|
||||
# Assay structure
|
||||
expect_equal(names(slot(obj, "assays")), "counts")
|
||||
# Spatial coordinates
|
||||
expect_equal(
|
||||
spatialCoordsNames(obj),
|
||||
c("CenterX_global_px", "CenterY_global_px")
|
||||
)
|
||||
# Alternative experiments
|
||||
expect_equal(altExpNames(obj), c("NegPrb"))
|
||||
# Metadata components
|
||||
expect_named(
|
||||
metadata(obj),
|
||||
c("fov_positions", "transcripts"),
|
||||
ignore.order = TRUE
|
||||
)
|
||||
# Parquet paths
|
||||
expect_true(grepl("\\.parquet$", metadata(obj)[["transcripts"]]))
|
||||
# Dimensions
|
||||
input <- readCosmxSXE(
|
||||
dirName = spe,
|
||||
addParquetPaths = FALSE,
|
||||
returnType = "SPE"
|
||||
)
|
||||
|
||||
dim_rds <- dim(obj)
|
||||
dim_input <- dim(input)
|
||||
|
||||
expect_equal(dim_rds, dim_input)
|
||||
|
||||
|
||||
cat("> Checking parameter functionality\n")
|
||||
|
||||
out_rds_ext <- "output_ext.rds"
|
||||
|
||||
@@ -44,6 +44,7 @@ resources:
|
||||
- type: python_script
|
||||
path: script.py
|
||||
- path: /src/utils/setup_logger.py
|
||||
- path: /src/utils/unzip_archived_folder.py
|
||||
test_resources:
|
||||
- type: python_script
|
||||
path: test.py
|
||||
@@ -60,6 +61,9 @@ engines:
|
||||
packages:
|
||||
- pyarrow
|
||||
test_setup:
|
||||
- type: apt
|
||||
packages:
|
||||
- zip
|
||||
- type: python
|
||||
__merge__: [ /src/base/requirements/viashpy.yaml, .]
|
||||
runners:
|
||||
|
||||
@@ -3,11 +3,13 @@ from pathlib import Path
|
||||
import scanpy as sc
|
||||
import pandas as pd
|
||||
import mudata as mu
|
||||
import zipfile
|
||||
import json
|
||||
import os
|
||||
|
||||
## VIASH START
|
||||
par = {
|
||||
"input": "./resources_test/xenium/xenium_tiny",
|
||||
"input": "test/xenium_tiny.zip",
|
||||
"output": "xenium_tiny_test.h5mu",
|
||||
"output_compression": "gzip",
|
||||
"obsm_coordinates": "spatial",
|
||||
@@ -19,21 +21,46 @@ meta = {"resources_dir": "src/utils"}
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import extract_selected_files_from_zip
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── cell_feature_matrix.h5
|
||||
# ├── cells.parquet
|
||||
# ├── experiment.xenium
|
||||
# └── metrics_summary.csv
|
||||
input_dir = Path(par["input"])
|
||||
input_data = {
|
||||
"count_matrix": input_dir / "cell_feature_matrix.h5",
|
||||
"cells_metadata": input_dir / "cells.parquet",
|
||||
"experiment": input_dir / "experiment.xenium",
|
||||
"metrics_summary": input_dir / "metrics_summary.csv",
|
||||
}
|
||||
|
||||
def _retrieve_input_data(xenium_output_bundle):
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── cell_feature_matrix.h5
|
||||
# ├── cells.parquet
|
||||
# ├── experiment.xenium
|
||||
# └── metrics_summary.csv
|
||||
|
||||
required_file_patterns = {
|
||||
"count_matrix": "**/cell_feature_matrix.h5",
|
||||
"cells_metadata": "**/cells.parquet",
|
||||
"experiment": "**/experiment.xenium",
|
||||
"metrics_summary": "**/metrics_summary.csv",
|
||||
}
|
||||
|
||||
if zipfile.is_zipfile(xenium_output_bundle):
|
||||
xenium_output_bundle = extract_selected_files_from_zip(
|
||||
xenium_output_bundle,
|
||||
members=[pattern for pattern in required_file_patterns.values()],
|
||||
)
|
||||
else:
|
||||
xenium_output_bundle = Path(xenium_output_bundle)
|
||||
|
||||
assert os.path.isdir(xenium_output_bundle), (
|
||||
"Input is expected to be a (compressed) directory."
|
||||
)
|
||||
|
||||
input_data = {}
|
||||
for key, pattern in required_file_patterns.items():
|
||||
file = list(xenium_output_bundle.glob(pattern))
|
||||
assert len(file) == 1, (
|
||||
f"Expected exactly one file matching pattern {pattern}, found {len(file)}."
|
||||
)
|
||||
input_data[key] = file[0]
|
||||
|
||||
return input_data
|
||||
|
||||
|
||||
def _format_cell_id_column(cell_id_column: pd.Series) -> pd.Series:
|
||||
@@ -46,9 +73,7 @@ def _format_cell_id_column(cell_id_column: pd.Series) -> pd.Series:
|
||||
# Read data from Xenium output bundle
|
||||
logger.info("Reading input data...")
|
||||
|
||||
assert all([file.exists() for file in input_data.values()]), (
|
||||
f"Not all required input files are found. Make sure that {par['input']} contains {input_data.values()}."
|
||||
)
|
||||
input_data = _retrieve_input_data(par["input"])
|
||||
|
||||
adata = sc.read_10x_h5(input_data["count_matrix"])
|
||||
metadata = pd.read_parquet(input_data["cells_metadata"], engine="pyarrow")
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import pytest
|
||||
import sys
|
||||
import subprocess
|
||||
import mudata as mu
|
||||
|
||||
## VIASH START
|
||||
meta = {
|
||||
"executable": "./target/executable/convert/from_cellranger_multi_to_h5mu/from_cellranger_multi_to_h5mu",
|
||||
"executable": "./target/executable/convert/from_xenium_to_h5mu/from_xenium_to_h5mu",
|
||||
"resources_dir": "resources_test/",
|
||||
"config": "src/convert/from_cellranger_multi_to_h5mu/config.vsh.yaml",
|
||||
"config": "src/convert/from_xenium_to_h5mu/config.vsh.yaml",
|
||||
}
|
||||
## VIASH END
|
||||
|
||||
@@ -62,6 +63,69 @@ def test_simple_execution(run_component, tmp_path):
|
||||
assert all([adata.obs[obs].dtype == "float" for obs in obs_areas])
|
||||
|
||||
|
||||
def test_compressed_input(run_component, tmp_path):
|
||||
output = tmp_path / "xenium.h5mu"
|
||||
zipped_input = tmp_path / "xenium_tiny.zip"
|
||||
|
||||
subprocess.run(
|
||||
["zip", "-r", str(zipped_input), "xenium_tiny"],
|
||||
cwd=meta["resources_dir"],
|
||||
check=True,
|
||||
)
|
||||
|
||||
# run component
|
||||
run_component(
|
||||
[
|
||||
"--input",
|
||||
zipped_input,
|
||||
"--output",
|
||||
str(output),
|
||||
"--output_compression",
|
||||
"gzip",
|
||||
]
|
||||
)
|
||||
|
||||
assert output.is_file(), "output file was not created"
|
||||
|
||||
mdata = mu.read_h5mu(output)
|
||||
assert list(mdata.mod.keys()) == ["rna"], "Expected modality rna"
|
||||
adata = mdata.mod["rna"]
|
||||
|
||||
assert list(adata.obs.keys()) == [
|
||||
"transcript_counts",
|
||||
"control_probe_counts",
|
||||
"genomic_control_counts",
|
||||
"control_codeword_counts",
|
||||
"unassigned_codeword_counts",
|
||||
"deprecated_codeword_counts",
|
||||
"total_counts",
|
||||
"cell_area",
|
||||
"nucleus_area",
|
||||
"nucleus_count",
|
||||
"segmentation_method",
|
||||
]
|
||||
|
||||
assert list(adata.uns.keys()) == ["xenium_experiment", "xenium_metrics"]
|
||||
assert list(adata.obsm.keys()) == ["spatial"]
|
||||
assert list(adata.var.keys()) == ["gene_ids", "feature_types", "genome"]
|
||||
|
||||
assert adata.X.dtype.kind == "f"
|
||||
assert all(adata.var["feature_types"] == "Gene Expression")
|
||||
assert adata.obsm["spatial"].dtype == "float"
|
||||
obs_counts = [
|
||||
"transcript_counts",
|
||||
"control_probe_counts",
|
||||
"genomic_control_counts",
|
||||
"unassigned_codeword_counts",
|
||||
"deprecated_codeword_counts",
|
||||
"total_counts",
|
||||
"nucleus_count",
|
||||
]
|
||||
assert all([adata.obs[obs].dtype == "int" for obs in obs_counts])
|
||||
obs_areas = ["cell_area", "nucleus_area"]
|
||||
assert all([adata.obs[obs].dtype == "float" for obs in obs_areas])
|
||||
|
||||
|
||||
def test_rename_fields(run_component, tmp_path):
|
||||
output = tmp_path / "xenium.h5mu"
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ resources:
|
||||
- type: python_script
|
||||
path: script.py
|
||||
- path: /src/utils/setup_logger.py
|
||||
- path: /src/utils/unzip_archived_folder.py
|
||||
test_resources:
|
||||
- type: python_script
|
||||
path: test.py
|
||||
@@ -91,6 +92,10 @@ engines:
|
||||
- procps
|
||||
- type: python
|
||||
__merge__: [ /src/base/requirements/spatialdata-io.yaml ]
|
||||
test_setup:
|
||||
- type: apt
|
||||
packages:
|
||||
- zip
|
||||
__merge__: [ /src/base/requirements/python_test_setup.yaml, .]
|
||||
runners:
|
||||
- type: executable
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import sys
|
||||
from spatialdata_io import xenium
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
## VIASH START
|
||||
par = {
|
||||
"input": "./resources_test/xenium_tiny",
|
||||
"input": "xenium_tiny.zip",
|
||||
"output": "./test/xenium_tiny.zarr",
|
||||
"cells_boundaries": True,
|
||||
"nucleus_boundaries": True,
|
||||
@@ -22,12 +24,29 @@ meta = {"resources_dir": "src/utils"}
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import unzip_archived_folder
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
logger.info("Reading in Xenium data...")
|
||||
|
||||
if zipfile.is_zipfile(par["input"]):
|
||||
required_file_patterns = [
|
||||
"**/experiment.xenium",
|
||||
"**/nucleus_boundaries.parquet",
|
||||
"**/cell_boundaries.parquet",
|
||||
"**/transcripts.parquet",
|
||||
"**/cell_feature_matrix.h5",
|
||||
"**/cells.parquet",
|
||||
"**/morphology_mip.ome.tif",
|
||||
"**/morphology_focus.ome.tif",
|
||||
]
|
||||
xenium_output_bundle = unzip_archived_folder(par["input"])
|
||||
else:
|
||||
xenium_output_bundle = Path(par["input"])
|
||||
|
||||
sdata = xenium(
|
||||
par["input"],
|
||||
xenium_output_bundle,
|
||||
cells_boundaries=par["cells_boundaries"],
|
||||
nucleus_boundaries=par["nucleus_boundaries"],
|
||||
cells_as_circles=par["cells_as_circles"],
|
||||
|
||||
@@ -2,6 +2,7 @@ import pytest
|
||||
import os
|
||||
import sys
|
||||
import spatialdata as sd
|
||||
import subprocess
|
||||
|
||||
|
||||
def test_simple_execution(run_component, tmp_path):
|
||||
@@ -31,5 +32,38 @@ def test_simple_execution(run_component, tmp_path):
|
||||
assert (output_sd_path / "zmetadata").is_file(), "zmetadata file was not created"
|
||||
|
||||
|
||||
def test_compressed_input(run_component, tmp_path):
|
||||
output_sd_path = tmp_path / "sd"
|
||||
zipped_input = tmp_path / "xenium_tiny.zip"
|
||||
|
||||
subprocess.run(
|
||||
["zip", "-r", str(zipped_input), "xenium_tiny"],
|
||||
cwd=meta["resources_dir"],
|
||||
check=True,
|
||||
)
|
||||
run_component(
|
||||
[
|
||||
"--input",
|
||||
zipped_input,
|
||||
"--output",
|
||||
output_sd_path,
|
||||
]
|
||||
)
|
||||
|
||||
assert os.path.exists(output_sd_path), "Output zarr folder was not created"
|
||||
|
||||
sdata = sd.read_zarr(output_sd_path)
|
||||
assert isinstance(sdata, sd.SpatialData), (
|
||||
"the generated output is not a SpatialData object"
|
||||
)
|
||||
|
||||
assert os.path.exists(output_sd_path / "images"), "images folder was not created"
|
||||
assert os.path.exists(output_sd_path / "labels"), "labels folder was not created"
|
||||
assert os.path.exists(output_sd_path / "points"), "images folder was not created"
|
||||
assert os.path.exists(output_sd_path / "shapes"), "shapes folder was not created"
|
||||
assert os.path.exists(output_sd_path / "tables"), "tables folder was not created"
|
||||
assert (output_sd_path / "zmetadata").is_file(), "zmetadata file was not created"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main([__file__]))
|
||||
|
||||
@@ -51,6 +51,7 @@ arguments:
|
||||
resources:
|
||||
- type: r_script
|
||||
path: script.R
|
||||
- path: /src/utils/unzip_archived_folder.R
|
||||
test_resources:
|
||||
- type: r_script
|
||||
path: test.R
|
||||
|
||||
@@ -2,7 +2,7 @@ library(SpatialExperimentIO)
|
||||
|
||||
### VIASH START
|
||||
par <- list(
|
||||
input = "resources_test/xenium/xenium_tiny",
|
||||
input = "resources_test/xenium/temp_dir.zip",
|
||||
add_experiment_xenium = TRUE,
|
||||
add_parquet_paths = TRUE,
|
||||
alternative_experiment_features = c(
|
||||
@@ -11,11 +11,35 @@ par <- list(
|
||||
),
|
||||
output = "spe_test.rds"
|
||||
)
|
||||
meta <- list(
|
||||
resources_dir = "src/utils/"
|
||||
)
|
||||
### VIASH END
|
||||
|
||||
source(paste0(meta$resources_dir, "/unzip_archived_folder.R"))
|
||||
|
||||
cat("Reading input data...")
|
||||
if (tools::file_ext(par$input) == "zip") {
|
||||
required_file_patterns <- c(
|
||||
"**/cell_feature_matrix.h5",
|
||||
"**/*.parquet",
|
||||
"**/experiment.xenium"
|
||||
)
|
||||
tmp_dir <- extract_selected_files(
|
||||
par$input,
|
||||
members = required_file_patterns
|
||||
)
|
||||
xenium_output_bundle <- file.path(
|
||||
tmp_dir,
|
||||
tools::file_path_sans_ext(basename(par$input))
|
||||
)
|
||||
} else {
|
||||
xenium_output_bundle <- par$input
|
||||
}
|
||||
|
||||
cat("Converting to SpatialExperiment")
|
||||
spe <- readXeniumSXE(
|
||||
dirName = par$input,
|
||||
dirName = xenium_output_bundle,
|
||||
returnType = "SPE",
|
||||
countMatPattern = "cell_feature_matrix.h5",
|
||||
metaDataPattern = "cells.parquet",
|
||||
@@ -25,4 +49,5 @@ spe <- readXeniumSXE(
|
||||
altExps = par$alternative_experiment_features
|
||||
)
|
||||
|
||||
cat("Saving output...")
|
||||
saveRDS(spe, file = par$output)
|
||||
|
||||
@@ -71,6 +71,77 @@ dim_input <- dim(input)
|
||||
expect_equal(dim_rds, dim_input)
|
||||
|
||||
|
||||
cat("> Checking execution with compressed input\n")
|
||||
|
||||
spe <- paste0(
|
||||
meta[["resources_dir"]],
|
||||
"/xenium_tiny"
|
||||
)
|
||||
out_rds <- "output.rds"
|
||||
|
||||
create_folder_archive <- function(folder_path, archive = "xenium_tiny.zip") {
|
||||
old_wd <- getwd()
|
||||
on.exit(setwd(old_wd))
|
||||
setwd(meta$resources_dir)
|
||||
system2("zip", c("-r", archive, "xenium_tiny"))
|
||||
paste0(meta$resources_dir, "/", archive)
|
||||
}
|
||||
|
||||
zipped_spe <- create_folder_archive(spe)
|
||||
|
||||
cat("> Running ", meta[["name"]], "\n", sep = "")
|
||||
out <- processx::run(
|
||||
meta[["executable"]],
|
||||
c(
|
||||
"--input", zipped_spe,
|
||||
"--output", out_rds
|
||||
)
|
||||
)
|
||||
|
||||
cat("> Checking whether output file exists\n")
|
||||
expect_equal(out$status, 0)
|
||||
expect_true(file.exists(out_rds))
|
||||
|
||||
cat("> Reading output file\n")
|
||||
obj <- readRDS(file = out_rds)
|
||||
|
||||
cat("> Checking whether Seurat object is in the right format\n")
|
||||
# Object type
|
||||
expect_is(obj, "SpatialExperiment")
|
||||
# Assay structure
|
||||
expect_equal(names(slot(obj, "assays")), "counts")
|
||||
# Spatial coordinates
|
||||
expect_equal(spatialCoordsNames(obj), c("x_centroid", "y_centroid"))
|
||||
# Alternative experiments
|
||||
expect_equal(
|
||||
altExpNames(obj),
|
||||
c("NegControlProbe", "UnassignedCodeword", "NegControlCodeword")
|
||||
)
|
||||
# Metadata components
|
||||
metadata_components <- c(
|
||||
"experiment.xenium", "transcripts", "cell_boundaries", "nucleus_boundaries"
|
||||
)
|
||||
expect_named(
|
||||
metadata(obj),
|
||||
metadata_components,
|
||||
ignore.order = TRUE
|
||||
)
|
||||
# Parquet paths
|
||||
parquet_components <- c("transcripts", "cell_boundaries", "nucleus_boundaries")
|
||||
for (component in parquet_components) {
|
||||
expect_true(grepl("\\.parquet$", metadata(obj)[[component]]))
|
||||
}
|
||||
# Dimensions
|
||||
input <- readXeniumSXE(
|
||||
dirName = spe,
|
||||
returnType = "SPE"
|
||||
)
|
||||
dim_rds <- dim(obj)
|
||||
dim_input <- dim(input)
|
||||
|
||||
expect_equal(dim_rds, dim_input)
|
||||
|
||||
|
||||
cat("> Checking parameter functionality\n")
|
||||
|
||||
out_rds_ext <- "output_ext.rds"
|
||||
|
||||
22
src/utils/unzip_archived_folder.R
Normal file
22
src/utils/unzip_archived_folder.R
Normal file
@@ -0,0 +1,22 @@
|
||||
extract_selected_files <- function(zip_path, members) {
|
||||
# Create a temporary directory for extraction
|
||||
temp_dir <- tempfile("unzip_dir_")
|
||||
dir.create(temp_dir)
|
||||
|
||||
# List all files in the archive
|
||||
all_files <- utils::unzip(zip_path, list = TRUE)$Name
|
||||
|
||||
# Find files matching any of the glob patterns in 'members'
|
||||
selected <- unique(unlist(
|
||||
lapply(members, function(pattern) {
|
||||
regex <- glob2rx(pattern)
|
||||
grep(regex, all_files, value = TRUE)
|
||||
})
|
||||
))
|
||||
|
||||
# Extract only the selected files
|
||||
utils::unzip(zip_path, files = selected, exdir = temp_dir)
|
||||
|
||||
# Return the path to the extracted folder
|
||||
file.path(temp_dir)
|
||||
}
|
||||
50
src/utils/unzip_archived_folder.py
Normal file
50
src/utils/unzip_archived_folder.py
Normal file
@@ -0,0 +1,50 @@
|
||||
import fnmatch
|
||||
import zipfile
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
|
||||
def unzip_archived_folder(archived_folder: Union[str, Path]) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts a ZIP archive to a temporary directory and returns the path to the extracted folder.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
|
||||
Returns:
|
||||
extracted_path (Union[str, Path]): Path to the extracted folder inside the temporary directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
with zipfile.ZipFile(archived_folder, "r") as archive:
|
||||
archive.extractall(temp_dir)
|
||||
|
||||
return temp_dir / Path(archived_folder).stem
|
||||
|
||||
|
||||
def extract_selected_files_from_zip(
|
||||
zip_path: Union[str, Path], members: list[Union[str, Path]]
|
||||
) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts selected files (supports glob patterns) from a ZIP archive to a temporary directory.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
members (list[str]): List of file paths within the archive to extract.
|
||||
|
||||
Returns:
|
||||
Path: Path to the extraction directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
|
||||
with zipfile.ZipFile(zip_path, "r") as archive:
|
||||
all_files = archive.namelist()
|
||||
selected = set()
|
||||
for pattern in members:
|
||||
selected.update(fnmatch.filter(all_files, str(pattern)))
|
||||
for member in selected:
|
||||
archive.extract(member, temp_dir)
|
||||
|
||||
return temp_dir
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_cells2stats_to_h5mu"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -150,6 +150,8 @@ resources:
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "setup_logger.py"
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.py"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -256,7 +258,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.13-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -274,6 +276,10 @@ engines:
|
||||
nelse: exit(1)\")"
|
||||
upgrade: true
|
||||
test_setup:
|
||||
- type: "apt"
|
||||
packages:
|
||||
- "zip"
|
||||
interactive: false
|
||||
- type: "python"
|
||||
user: false
|
||||
packages:
|
||||
@@ -290,11 +296,11 @@ build_info:
|
||||
output: "target/executable/convert/from_cells2stats_to_h5mu"
|
||||
executable: "target/executable/convert/from_cells2stats_to_h5mu/from_cells2stats_to_h5mu"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -314,7 +320,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# from_cells2stats_to_h5mu v0.1.0
|
||||
# from_cells2stats_to_h5mu v0.1.1
|
||||
#
|
||||
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -458,10 +458,10 @@ RUN pip install --upgrade pip && \
|
||||
|
||||
LABEL org.opencontainers.image.authors="Dorien Roosen"
|
||||
LABEL org.opencontainers.image.description="Companion container for running component convert from_cells2stats_to_h5mu"
|
||||
LABEL org.opencontainers.image.created="2025-08-25T12:22:56Z"
|
||||
LABEL org.opencontainers.image.created="2025-10-02T08:36:59Z"
|
||||
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
LABEL org.opencontainers.image.version="v0.1.0"
|
||||
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
LABEL org.opencontainers.image.version="v0.1.1"
|
||||
|
||||
VIASHDOCKER
|
||||
fi
|
||||
@@ -578,7 +578,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
|
||||
|
||||
# ViashHelp: Display helpful explanation about this executable
|
||||
function ViashHelp {
|
||||
echo "from_cells2stats_to_h5mu v0.1.0"
|
||||
echo "from_cells2stats_to_h5mu v0.1.1"
|
||||
echo ""
|
||||
echo "Convert spatial data resulting from Aviti Teton sequencers that have been"
|
||||
echo "processed by the Element Biosciences cells2stats workflow to H5MU format."
|
||||
@@ -722,7 +722,7 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 1
|
||||
;;
|
||||
--version)
|
||||
echo "from_cells2stats_to_h5mu v0.1.0"
|
||||
echo "from_cells2stats_to_h5mu v0.1.1"
|
||||
exit
|
||||
;;
|
||||
--input)
|
||||
@@ -923,7 +923,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
|
||||
|
||||
# determine docker image id
|
||||
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_cells2stats_to_h5mu:v0.1.0'
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_cells2stats_to_h5mu:v0.1.1'
|
||||
fi
|
||||
|
||||
# print dockerfile
|
||||
@@ -1242,6 +1242,8 @@ import mudata as mu
|
||||
import anndata as ad
|
||||
import re
|
||||
import json
|
||||
import zipfile
|
||||
import os
|
||||
|
||||
## VIASH START
|
||||
# The following code has been auto-generated by Viash.
|
||||
@@ -1285,6 +1287,8 @@ dep = {
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import extract_selected_files_from_zip
|
||||
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
@@ -1422,27 +1426,43 @@ def categorize_columns(column_list, target_panel):
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
# Read data from Aviti Teton output bundle
|
||||
def retrieve_input_data(cells2stats_output_bundle):
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── Cytoprofiling/
|
||||
# │ └── Instrument/
|
||||
# │ └── RawCellStats.parquet
|
||||
# └── Panel.json
|
||||
|
||||
logger.info("Reading input data...")
|
||||
input_dir = Path(par["input"])
|
||||
input_data = {
|
||||
"count_matrix": input_dir
|
||||
/ "Cytoprofiling"
|
||||
/ "Instrument"
|
||||
/ "RawCellStats.parquet",
|
||||
"target_panel": input_dir / "Panel.json",
|
||||
required_file_patterns = {
|
||||
"target_panel": "**/Panel.json",
|
||||
"count_matrix": "**/Cytoprofiling/Instrument/RawCellStats.parquet",
|
||||
}
|
||||
|
||||
assert all([file.exists() for file in input_data.values()]), (
|
||||
f"Not all required input files are found. Make sure that {par['input']} contains {input_data.values()}."
|
||||
if zipfile.is_zipfile(cells2stats_output_bundle):
|
||||
cells2stats_output_bundle = extract_selected_files_from_zip(
|
||||
cells2stats_output_bundle, members=required_file_patterns.values()
|
||||
)
|
||||
else:
|
||||
cells2stats_output_bundle = Path(cells2stats_output_bundle)
|
||||
|
||||
assert os.path.isdir(cells2stats_output_bundle), (
|
||||
"Input is expected to be a (compressed) directory."
|
||||
)
|
||||
|
||||
input_data = {}
|
||||
for key, pattern in required_file_patterns.items():
|
||||
file = list(cells2stats_output_bundle.glob(pattern))
|
||||
assert len(file) == 1, (
|
||||
f"Expected exactly one file matching pattern {pattern}, found {len(file)}."
|
||||
)
|
||||
input_data[key] = file[0]
|
||||
|
||||
return input_data
|
||||
|
||||
|
||||
def main():
|
||||
logger.info("Reading input data...")
|
||||
input_data = retrieve_input_data(par["input"])
|
||||
with open(input_data["target_panel"], "r") as f:
|
||||
target_panel = json.load(f)
|
||||
df = pd.read_parquet(input_data["count_matrix"], engine="pyarrow")
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import fnmatch
|
||||
import zipfile
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
|
||||
def unzip_archived_folder(archived_folder: Union[str, Path]) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts a ZIP archive to a temporary directory and returns the path to the extracted folder.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
|
||||
Returns:
|
||||
extracted_path (Union[str, Path]): Path to the extracted folder inside the temporary directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
with zipfile.ZipFile(archived_folder, "r") as archive:
|
||||
archive.extractall(temp_dir)
|
||||
|
||||
return temp_dir / Path(archived_folder).stem
|
||||
|
||||
|
||||
def extract_selected_files_from_zip(
|
||||
zip_path: Union[str, Path], members: list[Union[str, Path]]
|
||||
) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts selected files (supports glob patterns) from a ZIP archive to a temporary directory.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
members (list[str]): List of file paths within the archive to extract.
|
||||
|
||||
Returns:
|
||||
Path: Path to the extraction directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
|
||||
with zipfile.ZipFile(zip_path, "r") as archive:
|
||||
all_files = archive.namelist()
|
||||
selected = set()
|
||||
for pattern in members:
|
||||
selected.update(fnmatch.filter(all_files, str(pattern)))
|
||||
for member in selected:
|
||||
archive.extract(member, temp_dir)
|
||||
|
||||
return temp_dir
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_cosmx_to_h5mu"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -81,6 +81,8 @@ resources:
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "setup_logger.py"
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.py"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -184,7 +186,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.12-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -214,6 +216,10 @@ engines:
|
||||
github:
|
||||
- "openpipelines-bio/core#subdirectory=packages/python/openpipeline_testutils"
|
||||
upgrade: true
|
||||
- type: "apt"
|
||||
packages:
|
||||
- "zip"
|
||||
interactive: false
|
||||
entrypoint: []
|
||||
cmd: null
|
||||
- type: "native"
|
||||
@@ -225,11 +231,11 @@ build_info:
|
||||
output: "target/executable/convert/from_cosmx_to_h5mu"
|
||||
executable: "target/executable/convert/from_cosmx_to_h5mu/from_cosmx_to_h5mu"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -249,7 +255,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# from_cosmx_to_h5mu v0.1.0
|
||||
# from_cosmx_to_h5mu v0.1.1
|
||||
#
|
||||
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -459,10 +459,10 @@ RUN pip install --upgrade pip && \
|
||||
|
||||
LABEL org.opencontainers.image.authors="Dorien Roosen, Weiwei Schultz"
|
||||
LABEL org.opencontainers.image.description="Companion container for running component convert from_cosmx_to_h5mu"
|
||||
LABEL org.opencontainers.image.created="2025-08-25T12:22:57Z"
|
||||
LABEL org.opencontainers.image.created="2025-10-02T08:37:01Z"
|
||||
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
LABEL org.opencontainers.image.version="v0.1.0"
|
||||
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
LABEL org.opencontainers.image.version="v0.1.1"
|
||||
|
||||
VIASHDOCKER
|
||||
fi
|
||||
@@ -579,7 +579,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
|
||||
|
||||
# ViashHelp: Display helpful explanation about this executable
|
||||
function ViashHelp {
|
||||
echo "from_cosmx_to_h5mu v0.1.0"
|
||||
echo "from_cosmx_to_h5mu v0.1.1"
|
||||
echo ""
|
||||
echo "Converts the output from NanoString experiment into a MuData objcet."
|
||||
echo " - \`<dataset_id>_exprMat_file.csv\`: File containing the counts."
|
||||
@@ -658,7 +658,7 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 1
|
||||
;;
|
||||
--version)
|
||||
echo "from_cosmx_to_h5mu v0.1.0"
|
||||
echo "from_cosmx_to_h5mu v0.1.1"
|
||||
exit
|
||||
;;
|
||||
--input)
|
||||
@@ -805,7 +805,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
|
||||
|
||||
# determine docker image id
|
||||
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_cosmx_to_h5mu:v0.1.0'
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_cosmx_to_h5mu:v0.1.1'
|
||||
fi
|
||||
|
||||
# print dockerfile
|
||||
@@ -1113,7 +1113,8 @@ import sys
|
||||
import os
|
||||
import squidpy as sq
|
||||
import mudata as mu
|
||||
import glob
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
## VIASH START
|
||||
# The following code has been auto-generated by Viash.
|
||||
@@ -1151,31 +1152,60 @@ dep = {
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import extract_selected_files_from_zip
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
|
||||
def find_matrix_file(suffix):
|
||||
pattern = os.path.join(par["input"], f"*{suffix}")
|
||||
files = glob.glob(pattern)
|
||||
assert len(files) == 1, (
|
||||
f"Only one file matching pattern {pattern} should be present"
|
||||
def retrieve_input_data(cosmx_output_bundle):
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── *_exprMat_file.csv
|
||||
# ├── *_fov_positions_file.csv
|
||||
# └── *_metadata_file.csv
|
||||
|
||||
required_file_patterns = {
|
||||
"counts_file": "**/*exprMat_file.csv",
|
||||
"fov_file": "**/*fov_positions_file.csv",
|
||||
"meta_file": "**/*metadata_file.csv",
|
||||
}
|
||||
if zipfile.is_zipfile(cosmx_output_bundle):
|
||||
cosmx_output_bundle = extract_selected_files_from_zip(
|
||||
cosmx_output_bundle, members=required_file_patterns.values()
|
||||
)
|
||||
else:
|
||||
cosmx_output_bundle = Path(cosmx_output_bundle)
|
||||
|
||||
assert os.path.isdir(cosmx_output_bundle), (
|
||||
"Input is expected to be a (compressed) directory."
|
||||
)
|
||||
return files[0]
|
||||
|
||||
input_data = {}
|
||||
for key, pattern in required_file_patterns.items():
|
||||
file = list(cosmx_output_bundle.glob(pattern))
|
||||
assert len(file) == 1, f"Expected one file for {key}, found {len(file)}."
|
||||
input_data[key] = file[0]
|
||||
|
||||
return input_data
|
||||
|
||||
|
||||
counts_file = find_matrix_file("exprMat_file.csv")
|
||||
fov_file = find_matrix_file("fov_positions_file.csv")
|
||||
meta_file = find_matrix_file("metadata_file.csv")
|
||||
def main():
|
||||
logger.info("Reading in CosMx data...")
|
||||
input_data = retrieve_input_data(par["input"])
|
||||
|
||||
logger.info("Reading in CosMx data...")
|
||||
adata = sq.read.nanostring(
|
||||
path=par["input"], counts_file=counts_file, meta_file=meta_file, fov_file=fov_file
|
||||
)
|
||||
adata = sq.read.nanostring(
|
||||
path=par["input"],
|
||||
counts_file=input_data["counts_file"],
|
||||
meta_file=input_data["meta_file"],
|
||||
fov_file=input_data["fov_file"],
|
||||
)
|
||||
|
||||
logger.info("Writing output MuData object...")
|
||||
mdata = mu.MuData({par["modality"]: adata})
|
||||
mdata.write_h5mu(par["output"], compression=par["output_compression"])
|
||||
logger.info("Writing output MuData object...")
|
||||
mdata = mu.MuData({par["modality"]: adata})
|
||||
mdata.write_h5mu(par["output"], compression=par["output_compression"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
VIASHMAIN
|
||||
python -B "\$tempscript" &
|
||||
wait "\$!"
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import fnmatch
|
||||
import zipfile
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
|
||||
def unzip_archived_folder(archived_folder: Union[str, Path]) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts a ZIP archive to a temporary directory and returns the path to the extracted folder.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
|
||||
Returns:
|
||||
extracted_path (Union[str, Path]): Path to the extracted folder inside the temporary directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
with zipfile.ZipFile(archived_folder, "r") as archive:
|
||||
archive.extractall(temp_dir)
|
||||
|
||||
return temp_dir / Path(archived_folder).stem
|
||||
|
||||
|
||||
def extract_selected_files_from_zip(
|
||||
zip_path: Union[str, Path], members: list[Union[str, Path]]
|
||||
) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts selected files (supports glob patterns) from a ZIP archive to a temporary directory.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
members (list[str]): List of file paths within the archive to extract.
|
||||
|
||||
Returns:
|
||||
Path: Path to the extraction directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
|
||||
with zipfile.ZipFile(zip_path, "r") as archive:
|
||||
all_files = archive.namelist()
|
||||
selected = set()
|
||||
for pattern in members:
|
||||
selected.update(fnmatch.filter(all_files, str(pattern)))
|
||||
for member in selected:
|
||||
archive.extract(member, temp_dir)
|
||||
|
||||
return temp_dir
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_cosmx_to_spatialexperiment"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -98,6 +98,8 @@ resources:
|
||||
- type: "r_script"
|
||||
path: "script.R"
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.R"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -202,7 +204,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "rocker/r2u:24.04"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -232,11 +234,11 @@ build_info:
|
||||
output: "target/executable/convert/from_cosmx_to_spatialexperiment"
|
||||
executable: "target/executable/convert/from_cosmx_to_spatialexperiment/from_cosmx_to_spatialexperiment"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -256,7 +258,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# from_cosmx_to_spatialexperiment v0.1.0
|
||||
# from_cosmx_to_spatialexperiment v0.1.1
|
||||
#
|
||||
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -457,10 +457,10 @@ RUN Rscript -e 'options(warn = 2); if (!requireNamespace("BiocManager", quietly
|
||||
|
||||
LABEL org.opencontainers.image.authors="Dorien Roosen"
|
||||
LABEL org.opencontainers.image.description="Companion container for running component convert from_cosmx_to_spatialexperiment"
|
||||
LABEL org.opencontainers.image.created="2025-08-25T12:22:56Z"
|
||||
LABEL org.opencontainers.image.created="2025-10-02T08:37:00Z"
|
||||
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
LABEL org.opencontainers.image.version="v0.1.0"
|
||||
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
LABEL org.opencontainers.image.version="v0.1.1"
|
||||
|
||||
VIASHDOCKER
|
||||
fi
|
||||
@@ -577,7 +577,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
|
||||
|
||||
# ViashHelp: Display helpful explanation about this executable
|
||||
function ViashHelp {
|
||||
echo "from_cosmx_to_spatialexperiment v0.1.0"
|
||||
echo "from_cosmx_to_spatialexperiment v0.1.1"
|
||||
echo ""
|
||||
echo "Creates a SpatialExperiment object from the downloaded unzipped CosMx directory"
|
||||
echo "for Nanostring"
|
||||
@@ -678,7 +678,7 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 1
|
||||
;;
|
||||
--version)
|
||||
echo "from_cosmx_to_spatialexperiment v0.1.0"
|
||||
echo "from_cosmx_to_spatialexperiment v0.1.1"
|
||||
exit
|
||||
;;
|
||||
--input)
|
||||
@@ -853,7 +853,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
|
||||
|
||||
# determine docker image id
|
||||
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_cosmx_to_spatialexperiment:v0.1.0'
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_cosmx_to_spatialexperiment:v0.1.1'
|
||||
fi
|
||||
|
||||
# print dockerfile
|
||||
@@ -1221,14 +1221,36 @@ rm(.viash_orig_warn)
|
||||
|
||||
### VIASH END
|
||||
|
||||
source(paste0(meta\$resources_dir, "/unzip_archived_folder.R"))
|
||||
|
||||
cat("Reading input data...")
|
||||
if (tools::file_ext(par\$input) == "zip") {
|
||||
expected_file_patterns <- c(
|
||||
"*.csv",
|
||||
"*.parquet"
|
||||
)
|
||||
tmp_dir <- extract_selected_files(
|
||||
par\$input,
|
||||
members = expected_file_patterns
|
||||
)
|
||||
cosmx_output_bundle <- file.path(
|
||||
tmp_dir,
|
||||
tools::file_path_sans_ext(basename(par\$input))
|
||||
)
|
||||
} else {
|
||||
cosmx_output_bundle <- par\$input
|
||||
}
|
||||
|
||||
cat("Setting parameters...")
|
||||
if (par\$add_polygon_path == FALSE && par\$add_tx_path == FALSE) {
|
||||
add_parquet_paths <- FALSE
|
||||
} else {
|
||||
add_parquet_paths <- TRUE
|
||||
}
|
||||
|
||||
cat("Converting to SpatialExperiment...")
|
||||
spe <- readCosmxSXE(
|
||||
dirName = par\$input,
|
||||
dirName = cosmx_output_bundle,
|
||||
returnType = "SPE",
|
||||
countMatPattern = "exprMat_file.csv",
|
||||
metaDataPattern = "metadata_file.csv",
|
||||
@@ -1241,6 +1263,7 @@ spe <- readCosmxSXE(
|
||||
altExps = par\$alternative_experiment_features
|
||||
)
|
||||
|
||||
cat("Saving output...")
|
||||
saveRDS(spe, file = par\$output)
|
||||
VIASHMAIN
|
||||
Rscript "\$tempscript" &
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
extract_selected_files <- function(zip_path, members) {
|
||||
# Create a temporary directory for extraction
|
||||
temp_dir <- tempfile("unzip_dir_")
|
||||
dir.create(temp_dir)
|
||||
|
||||
# List all files in the archive
|
||||
all_files <- utils::unzip(zip_path, list = TRUE)$Name
|
||||
|
||||
# Find files matching any of the glob patterns in 'members'
|
||||
selected <- unique(unlist(
|
||||
lapply(members, function(pattern) {
|
||||
regex <- glob2rx(pattern)
|
||||
grep(regex, all_files, value = TRUE)
|
||||
})
|
||||
))
|
||||
|
||||
# Extract only the selected files
|
||||
utils::unzip(zip_path, files = selected, exdir = temp_dir)
|
||||
|
||||
# Return the path to the extracted folder
|
||||
file.path(temp_dir)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_h5mu_to_spatialexperiment"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -171,7 +171,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "rocker/r2u:22.04"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -224,11 +224,11 @@ build_info:
|
||||
output: "target/executable/convert/from_h5mu_to_spatialexperiment"
|
||||
executable: "target/executable/convert/from_h5mu_to_spatialexperiment/from_h5mu_to_spatialexperiment"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -248,7 +248,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# from_h5mu_to_spatialexperiment v0.1.0
|
||||
# from_h5mu_to_spatialexperiment v0.1.1
|
||||
#
|
||||
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -458,10 +458,10 @@ RUN Rscript -e 'options(warn = 2); if (!requireNamespace("remotes", quietly = TR
|
||||
|
||||
LABEL org.opencontainers.image.authors="Dorien Roosen"
|
||||
LABEL org.opencontainers.image.description="Companion container for running component convert from_h5mu_to_spatialexperiment"
|
||||
LABEL org.opencontainers.image.created="2025-08-25T12:22:57Z"
|
||||
LABEL org.opencontainers.image.created="2025-10-02T08:37:00Z"
|
||||
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
LABEL org.opencontainers.image.version="v0.1.0"
|
||||
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
LABEL org.opencontainers.image.version="v0.1.1"
|
||||
|
||||
VIASHDOCKER
|
||||
fi
|
||||
@@ -578,7 +578,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
|
||||
|
||||
# ViashHelp: Display helpful explanation about this executable
|
||||
function ViashHelp {
|
||||
echo "from_h5mu_to_spatialexperiment v0.1.0"
|
||||
echo "from_h5mu_to_spatialexperiment v0.1.1"
|
||||
echo ""
|
||||
echo "Converts an h5mu file into a SpatialExperiment object."
|
||||
echo ""
|
||||
@@ -650,7 +650,7 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 1
|
||||
;;
|
||||
--version)
|
||||
echo "from_h5mu_to_spatialexperiment v0.1.0"
|
||||
echo "from_h5mu_to_spatialexperiment v0.1.1"
|
||||
exit
|
||||
;;
|
||||
--input)
|
||||
@@ -797,7 +797,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
|
||||
|
||||
# determine docker image id
|
||||
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_h5mu_to_spatialexperiment:v0.1.0'
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_h5mu_to_spatialexperiment:v0.1.1'
|
||||
fi
|
||||
|
||||
# print dockerfile
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_spatialdata_to_h5mu"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -180,7 +180,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.12-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -220,11 +220,11 @@ build_info:
|
||||
output: "target/executable/convert/from_spatialdata_to_h5mu"
|
||||
executable: "target/executable/convert/from_spatialdata_to_h5mu/from_spatialdata_to_h5mu"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -244,7 +244,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# from_spatialdata_to_h5mu v0.1.0
|
||||
# from_spatialdata_to_h5mu v0.1.1
|
||||
#
|
||||
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -459,10 +459,10 @@ RUN pip install --upgrade pip && \
|
||||
|
||||
LABEL org.opencontainers.image.authors="Dorien Roosen, Weiwei Schultz"
|
||||
LABEL org.opencontainers.image.description="Companion container for running component convert from_spatialdata_to_h5mu"
|
||||
LABEL org.opencontainers.image.created="2025-08-25T12:22:56Z"
|
||||
LABEL org.opencontainers.image.created="2025-10-02T08:37:00Z"
|
||||
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
LABEL org.opencontainers.image.version="v0.1.0"
|
||||
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
LABEL org.opencontainers.image.version="v0.1.1"
|
||||
|
||||
VIASHDOCKER
|
||||
fi
|
||||
@@ -579,7 +579,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
|
||||
|
||||
# ViashHelp: Display helpful explanation about this executable
|
||||
function ViashHelp {
|
||||
echo "from_spatialdata_to_h5mu v0.1.0"
|
||||
echo "from_spatialdata_to_h5mu v0.1.1"
|
||||
echo ""
|
||||
echo "Reads in the Tables field stored in a SpatialData object and converts it to an"
|
||||
echo "h5mu file."
|
||||
@@ -651,7 +651,7 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 1
|
||||
;;
|
||||
--version)
|
||||
echo "from_spatialdata_to_h5mu v0.1.0"
|
||||
echo "from_spatialdata_to_h5mu v0.1.1"
|
||||
exit
|
||||
;;
|
||||
--input)
|
||||
@@ -798,7 +798,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
|
||||
|
||||
# determine docker image id
|
||||
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_spatialdata_to_h5mu:v0.1.0'
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_spatialdata_to_h5mu:v0.1.1'
|
||||
fi
|
||||
|
||||
# print dockerfile
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_xenium_to_h5mu"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -97,6 +97,8 @@ resources:
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "setup_logger.py"
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.py"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -198,7 +200,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.12-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -217,6 +219,10 @@ engines:
|
||||
nelse: exit(1)\")"
|
||||
upgrade: true
|
||||
test_setup:
|
||||
- type: "apt"
|
||||
packages:
|
||||
- "zip"
|
||||
interactive: false
|
||||
- type: "python"
|
||||
user: false
|
||||
packages:
|
||||
@@ -233,11 +239,11 @@ build_info:
|
||||
output: "target/executable/convert/from_xenium_to_h5mu"
|
||||
executable: "target/executable/convert/from_xenium_to_h5mu/from_xenium_to_h5mu"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -257,7 +263,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# from_xenium_to_h5mu v0.1.0
|
||||
# from_xenium_to_h5mu v0.1.1
|
||||
#
|
||||
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -458,10 +458,10 @@ RUN pip install --upgrade pip && \
|
||||
|
||||
LABEL org.opencontainers.image.authors="Dorien Roosen"
|
||||
LABEL org.opencontainers.image.description="Companion container for running component convert from_xenium_to_h5mu"
|
||||
LABEL org.opencontainers.image.created="2025-08-25T12:22:56Z"
|
||||
LABEL org.opencontainers.image.created="2025-10-02T08:37:00Z"
|
||||
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
LABEL org.opencontainers.image.version="v0.1.0"
|
||||
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
LABEL org.opencontainers.image.version="v0.1.1"
|
||||
|
||||
VIASHDOCKER
|
||||
fi
|
||||
@@ -578,7 +578,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
|
||||
|
||||
# ViashHelp: Display helpful explanation about this executable
|
||||
function ViashHelp {
|
||||
echo "from_xenium_to_h5mu v0.1.0"
|
||||
echo "from_xenium_to_h5mu v0.1.1"
|
||||
echo ""
|
||||
echo "Converts the output from Xenium to a single .h5mu file, where the count matrix"
|
||||
echo "is written to the \`rna\` modality."
|
||||
@@ -670,7 +670,7 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 1
|
||||
;;
|
||||
--version)
|
||||
echo "from_xenium_to_h5mu v0.1.0"
|
||||
echo "from_xenium_to_h5mu v0.1.1"
|
||||
exit
|
||||
;;
|
||||
--input)
|
||||
@@ -839,7 +839,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
|
||||
|
||||
# determine docker image id
|
||||
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_xenium_to_h5mu:v0.1.0'
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_xenium_to_h5mu:v0.1.1'
|
||||
fi
|
||||
|
||||
# print dockerfile
|
||||
@@ -1154,7 +1154,9 @@ from pathlib import Path
|
||||
import scanpy as sc
|
||||
import pandas as pd
|
||||
import mudata as mu
|
||||
import zipfile
|
||||
import json
|
||||
import os
|
||||
|
||||
## VIASH START
|
||||
# The following code has been auto-generated by Viash.
|
||||
@@ -1194,21 +1196,46 @@ dep = {
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import extract_selected_files_from_zip
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── cell_feature_matrix.h5
|
||||
# ├── cells.parquet
|
||||
# ├── experiment.xenium
|
||||
# └── metrics_summary.csv
|
||||
input_dir = Path(par["input"])
|
||||
input_data = {
|
||||
"count_matrix": input_dir / "cell_feature_matrix.h5",
|
||||
"cells_metadata": input_dir / "cells.parquet",
|
||||
"experiment": input_dir / "experiment.xenium",
|
||||
"metrics_summary": input_dir / "metrics_summary.csv",
|
||||
}
|
||||
|
||||
def _retrieve_input_data(xenium_output_bundle):
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── cell_feature_matrix.h5
|
||||
# ├── cells.parquet
|
||||
# ├── experiment.xenium
|
||||
# └── metrics_summary.csv
|
||||
|
||||
required_file_patterns = {
|
||||
"count_matrix": "**/cell_feature_matrix.h5",
|
||||
"cells_metadata": "**/cells.parquet",
|
||||
"experiment": "**/experiment.xenium",
|
||||
"metrics_summary": "**/metrics_summary.csv",
|
||||
}
|
||||
|
||||
if zipfile.is_zipfile(xenium_output_bundle):
|
||||
xenium_output_bundle = extract_selected_files_from_zip(
|
||||
xenium_output_bundle,
|
||||
members=[pattern for pattern in required_file_patterns.values()],
|
||||
)
|
||||
else:
|
||||
xenium_output_bundle = Path(xenium_output_bundle)
|
||||
|
||||
assert os.path.isdir(xenium_output_bundle), (
|
||||
"Input is expected to be a (compressed) directory."
|
||||
)
|
||||
|
||||
input_data = {}
|
||||
for key, pattern in required_file_patterns.items():
|
||||
file = list(xenium_output_bundle.glob(pattern))
|
||||
assert len(file) == 1, (
|
||||
f"Expected exactly one file matching pattern {pattern}, found {len(file)}."
|
||||
)
|
||||
input_data[key] = file[0]
|
||||
|
||||
return input_data
|
||||
|
||||
|
||||
def _format_cell_id_column(cell_id_column: pd.Series) -> pd.Series:
|
||||
@@ -1221,9 +1248,7 @@ def _format_cell_id_column(cell_id_column: pd.Series) -> pd.Series:
|
||||
# Read data from Xenium output bundle
|
||||
logger.info("Reading input data...")
|
||||
|
||||
assert all([file.exists() for file in input_data.values()]), (
|
||||
f"Not all required input files are found. Make sure that {par['input']} contains {input_data.values()}."
|
||||
)
|
||||
input_data = _retrieve_input_data(par["input"])
|
||||
|
||||
adata = sc.read_10x_h5(input_data["count_matrix"])
|
||||
metadata = pd.read_parquet(input_data["cells_metadata"], engine="pyarrow")
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import fnmatch
|
||||
import zipfile
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
|
||||
def unzip_archived_folder(archived_folder: Union[str, Path]) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts a ZIP archive to a temporary directory and returns the path to the extracted folder.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
|
||||
Returns:
|
||||
extracted_path (Union[str, Path]): Path to the extracted folder inside the temporary directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
with zipfile.ZipFile(archived_folder, "r") as archive:
|
||||
archive.extractall(temp_dir)
|
||||
|
||||
return temp_dir / Path(archived_folder).stem
|
||||
|
||||
|
||||
def extract_selected_files_from_zip(
|
||||
zip_path: Union[str, Path], members: list[Union[str, Path]]
|
||||
) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts selected files (supports glob patterns) from a ZIP archive to a temporary directory.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
members (list[str]): List of file paths within the archive to extract.
|
||||
|
||||
Returns:
|
||||
Path: Path to the extraction directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
|
||||
with zipfile.ZipFile(zip_path, "r") as archive:
|
||||
all_files = archive.namelist()
|
||||
selected = set()
|
||||
for pattern in members:
|
||||
selected.update(fnmatch.filter(all_files, str(pattern)))
|
||||
for member in selected:
|
||||
archive.extract(member, temp_dir)
|
||||
|
||||
return temp_dir
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_xenium_to_spatialdata"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -173,6 +173,8 @@ resources:
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "setup_logger.py"
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.py"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -278,7 +280,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.12-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -303,6 +305,10 @@ engines:
|
||||
github:
|
||||
- "openpipelines-bio/core#subdirectory=packages/python/openpipeline_testutils"
|
||||
upgrade: true
|
||||
- type: "apt"
|
||||
packages:
|
||||
- "zip"
|
||||
interactive: false
|
||||
entrypoint: []
|
||||
cmd: null
|
||||
- type: "native"
|
||||
@@ -314,11 +320,11 @@ build_info:
|
||||
output: "target/executable/convert/from_xenium_to_spatialdata"
|
||||
executable: "target/executable/convert/from_xenium_to_spatialdata/from_xenium_to_spatialdata"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -338,7 +344,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# from_xenium_to_spatialdata v0.1.0
|
||||
# from_xenium_to_spatialdata v0.1.1
|
||||
#
|
||||
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -458,10 +458,10 @@ RUN pip install --upgrade pip && \
|
||||
|
||||
LABEL org.opencontainers.image.authors="Dorien Roosen, Weiwei Schultz"
|
||||
LABEL org.opencontainers.image.description="Companion container for running component convert from_xenium_to_spatialdata"
|
||||
LABEL org.opencontainers.image.created="2025-08-25T12:22:57Z"
|
||||
LABEL org.opencontainers.image.created="2025-10-02T08:36:59Z"
|
||||
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
LABEL org.opencontainers.image.version="v0.1.0"
|
||||
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
LABEL org.opencontainers.image.version="v0.1.1"
|
||||
|
||||
VIASHDOCKER
|
||||
fi
|
||||
@@ -578,7 +578,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
|
||||
|
||||
# ViashHelp: Display helpful explanation about this executable
|
||||
function ViashHelp {
|
||||
echo "from_xenium_to_spatialdata v0.1.0"
|
||||
echo "from_xenium_to_spatialdata v0.1.1"
|
||||
echo ""
|
||||
echo "Converts the output from 10X Genomics Xenium dataset into a SpatialData objcet."
|
||||
echo "By default, the following files will be converted:"
|
||||
@@ -711,7 +711,7 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 1
|
||||
;;
|
||||
--version)
|
||||
echo "from_xenium_to_spatialdata v0.1.0"
|
||||
echo "from_xenium_to_spatialdata v0.1.1"
|
||||
exit
|
||||
;;
|
||||
--input)
|
||||
@@ -951,7 +951,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
|
||||
|
||||
# determine docker image id
|
||||
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_xenium_to_spatialdata:v0.1.0'
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_xenium_to_spatialdata:v0.1.1'
|
||||
fi
|
||||
|
||||
# print dockerfile
|
||||
@@ -1340,6 +1340,8 @@ trap interrupt INT SIGINT
|
||||
cat > "\$tempscript" << 'VIASHMAIN'
|
||||
import sys
|
||||
from spatialdata_io import xenium
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
## VIASH START
|
||||
# The following code has been auto-generated by Viash.
|
||||
@@ -1386,12 +1388,29 @@ dep = {
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import unzip_archived_folder
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
logger.info("Reading in Xenium data...")
|
||||
|
||||
if zipfile.is_zipfile(par["input"]):
|
||||
required_file_patterns = [
|
||||
"**/experiment.xenium",
|
||||
"**/nucleus_boundaries.parquet",
|
||||
"**/cell_boundaries.parquet",
|
||||
"**/transcripts.parquet",
|
||||
"**/cell_feature_matrix.h5",
|
||||
"**/cells.parquet",
|
||||
"**/morphology_mip.ome.tif",
|
||||
"**/morphology_focus.ome.tif",
|
||||
]
|
||||
xenium_output_bundle = unzip_archived_folder(par["input"])
|
||||
else:
|
||||
xenium_output_bundle = Path(par["input"])
|
||||
|
||||
sdata = xenium(
|
||||
par["input"],
|
||||
xenium_output_bundle,
|
||||
cells_boundaries=par["cells_boundaries"],
|
||||
nucleus_boundaries=par["nucleus_boundaries"],
|
||||
cells_as_circles=par["cells_as_circles"],
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import fnmatch
|
||||
import zipfile
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
|
||||
def unzip_archived_folder(archived_folder: Union[str, Path]) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts a ZIP archive to a temporary directory and returns the path to the extracted folder.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
|
||||
Returns:
|
||||
extracted_path (Union[str, Path]): Path to the extracted folder inside the temporary directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
with zipfile.ZipFile(archived_folder, "r") as archive:
|
||||
archive.extractall(temp_dir)
|
||||
|
||||
return temp_dir / Path(archived_folder).stem
|
||||
|
||||
|
||||
def extract_selected_files_from_zip(
|
||||
zip_path: Union[str, Path], members: list[Union[str, Path]]
|
||||
) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts selected files (supports glob patterns) from a ZIP archive to a temporary directory.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
members (list[str]): List of file paths within the archive to extract.
|
||||
|
||||
Returns:
|
||||
Path: Path to the extraction directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
|
||||
with zipfile.ZipFile(zip_path, "r") as archive:
|
||||
all_files = archive.namelist()
|
||||
selected = set()
|
||||
for pattern in members:
|
||||
selected.update(fnmatch.filter(all_files, str(pattern)))
|
||||
for member in selected:
|
||||
archive.extract(member, temp_dir)
|
||||
|
||||
return temp_dir
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_xenium_to_spatialexperiment"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -88,6 +88,8 @@ resources:
|
||||
- type: "r_script"
|
||||
path: "script.R"
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.R"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -192,7 +194,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "rocker/r2u:24.04"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -222,11 +224,11 @@ build_info:
|
||||
output: "target/executable/convert/from_xenium_to_spatialexperiment"
|
||||
executable: "target/executable/convert/from_xenium_to_spatialexperiment/from_xenium_to_spatialexperiment"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -246,7 +248,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# from_xenium_to_spatialexperiment v0.1.0
|
||||
# from_xenium_to_spatialexperiment v0.1.1
|
||||
#
|
||||
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -457,10 +457,10 @@ RUN Rscript -e 'options(warn = 2); if (!requireNamespace("BiocManager", quietly
|
||||
|
||||
LABEL org.opencontainers.image.authors="Dorien Roosen"
|
||||
LABEL org.opencontainers.image.description="Companion container for running component convert from_xenium_to_spatialexperiment"
|
||||
LABEL org.opencontainers.image.created="2025-08-25T12:22:56Z"
|
||||
LABEL org.opencontainers.image.created="2025-10-02T08:37:00Z"
|
||||
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
LABEL org.opencontainers.image.version="v0.1.0"
|
||||
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
LABEL org.opencontainers.image.version="v0.1.1"
|
||||
|
||||
VIASHDOCKER
|
||||
fi
|
||||
@@ -577,7 +577,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
|
||||
|
||||
# ViashHelp: Display helpful explanation about this executable
|
||||
function ViashHelp {
|
||||
echo "from_xenium_to_spatialexperiment v0.1.0"
|
||||
echo "from_xenium_to_spatialexperiment v0.1.1"
|
||||
echo ""
|
||||
echo "Creates a SpatialExperiment object from the downloaded unzipped Xenium Output"
|
||||
echo "Bundle directory"
|
||||
@@ -673,7 +673,7 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 1
|
||||
;;
|
||||
--version)
|
||||
echo "from_xenium_to_spatialexperiment v0.1.0"
|
||||
echo "from_xenium_to_spatialexperiment v0.1.1"
|
||||
exit
|
||||
;;
|
||||
--input)
|
||||
@@ -837,7 +837,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
|
||||
|
||||
# determine docker image id
|
||||
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_xenium_to_spatialexperiment:v0.1.0'
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_xenium_to_spatialexperiment:v0.1.1'
|
||||
fi
|
||||
|
||||
# print dockerfile
|
||||
@@ -1195,9 +1195,30 @@ rm(.viash_orig_warn)
|
||||
|
||||
### VIASH END
|
||||
|
||||
source(paste0(meta\$resources_dir, "/unzip_archived_folder.R"))
|
||||
|
||||
cat("Reading input data...")
|
||||
if (tools::file_ext(par\$input) == "zip") {
|
||||
required_file_patterns <- c(
|
||||
"**/cell_feature_matrix.h5",
|
||||
"**/*.parquet",
|
||||
"**/experiment.xenium"
|
||||
)
|
||||
tmp_dir <- extract_selected_files(
|
||||
par\$input,
|
||||
members = required_file_patterns
|
||||
)
|
||||
xenium_output_bundle <- file.path(
|
||||
tmp_dir,
|
||||
tools::file_path_sans_ext(basename(par\$input))
|
||||
)
|
||||
} else {
|
||||
xenium_output_bundle <- par\$input
|
||||
}
|
||||
|
||||
cat("Converting to SpatialExperiment")
|
||||
spe <- readXeniumSXE(
|
||||
dirName = par\$input,
|
||||
dirName = xenium_output_bundle,
|
||||
returnType = "SPE",
|
||||
countMatPattern = "cell_feature_matrix.h5",
|
||||
metaDataPattern = "cells.parquet",
|
||||
@@ -1207,6 +1228,7 @@ spe <- readXeniumSXE(
|
||||
altExps = par\$alternative_experiment_features
|
||||
)
|
||||
|
||||
cat("Saving output...")
|
||||
saveRDS(spe, file = par\$output)
|
||||
VIASHMAIN
|
||||
Rscript "\$tempscript" &
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
extract_selected_files <- function(zip_path, members) {
|
||||
# Create a temporary directory for extraction
|
||||
temp_dir <- tempfile("unzip_dir_")
|
||||
dir.create(temp_dir)
|
||||
|
||||
# List all files in the archive
|
||||
all_files <- utils::unzip(zip_path, list = TRUE)$Name
|
||||
|
||||
# Find files matching any of the glob patterns in 'members'
|
||||
selected <- unique(unlist(
|
||||
lapply(members, function(pattern) {
|
||||
regex <- glob2rx(pattern)
|
||||
grep(regex, all_files, value = TRUE)
|
||||
})
|
||||
))
|
||||
|
||||
# Extract only the selected files
|
||||
utils::unzip(zip_path, files = selected, exdir = temp_dir)
|
||||
|
||||
# Return the path to the extracted folder
|
||||
file.path(temp_dir)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "subset_cosmx"
|
||||
namespace: "filter"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -191,7 +191,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.12-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -227,11 +227,11 @@ build_info:
|
||||
output: "target/executable/filter/subset_cosmx"
|
||||
executable: "target/executable/filter/subset_cosmx/subset_cosmx"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -251,7 +251,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# subset_cosmx v0.1.0
|
||||
# subset_cosmx v0.1.1
|
||||
#
|
||||
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -458,10 +458,10 @@ RUN pip install --upgrade pip && \
|
||||
|
||||
LABEL org.opencontainers.image.authors="Dorien Roosen, Weiwei Schultz"
|
||||
LABEL org.opencontainers.image.description="Companion container for running component filter subset_cosmx"
|
||||
LABEL org.opencontainers.image.created="2025-08-25T12:22:56Z"
|
||||
LABEL org.opencontainers.image.created="2025-10-02T08:36:59Z"
|
||||
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
LABEL org.opencontainers.image.version="v0.1.0"
|
||||
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
LABEL org.opencontainers.image.version="v0.1.1"
|
||||
|
||||
VIASHDOCKER
|
||||
fi
|
||||
@@ -578,7 +578,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
|
||||
|
||||
# ViashHelp: Display helpful explanation about this executable
|
||||
function ViashHelp {
|
||||
echo "subset_cosmx v0.1.0"
|
||||
echo "subset_cosmx v0.1.1"
|
||||
echo ""
|
||||
echo "Filters the output from NanoString experiment to keep only a subset of the"
|
||||
echo "fields of view."
|
||||
@@ -666,7 +666,7 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 1
|
||||
;;
|
||||
--version)
|
||||
echo "subset_cosmx v0.1.0"
|
||||
echo "subset_cosmx v0.1.1"
|
||||
exit
|
||||
;;
|
||||
--input)
|
||||
@@ -824,7 +824,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
|
||||
|
||||
# determine docker image id
|
||||
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/filter/subset_cosmx:v0.1.0'
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/filter/subset_cosmx:v0.1.1'
|
||||
fi
|
||||
|
||||
# print dockerfile
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "spaceranger_count"
|
||||
namespace: "mapping"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Jakub Majercik"
|
||||
roles:
|
||||
@@ -408,7 +408,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "ghcr.io/data-intuitive/spaceranger:3.1"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "docker"
|
||||
@@ -426,11 +426,11 @@ build_info:
|
||||
output: "target/executable/mapping/spaceranger_count"
|
||||
executable: "target/executable/mapping/spaceranger_count/spaceranger_count"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -450,7 +450,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# spaceranger_count v0.1.0
|
||||
# spaceranger_count v0.1.1
|
||||
#
|
||||
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -453,10 +453,10 @@ apt upgrade -y && apt install -y procps && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
LABEL org.opencontainers.image.authors="Jakub Majercik"
|
||||
LABEL org.opencontainers.image.description="Companion container for running component mapping spaceranger_count"
|
||||
LABEL org.opencontainers.image.created="2025-08-25T12:22:57Z"
|
||||
LABEL org.opencontainers.image.created="2025-10-02T08:36:59Z"
|
||||
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
LABEL org.opencontainers.image.version="v0.1.0"
|
||||
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
LABEL org.opencontainers.image.version="v0.1.1"
|
||||
|
||||
VIASHDOCKER
|
||||
fi
|
||||
@@ -573,7 +573,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
|
||||
|
||||
# ViashHelp: Display helpful explanation about this executable
|
||||
function ViashHelp {
|
||||
echo "spaceranger_count v0.1.0"
|
||||
echo "spaceranger_count v0.1.1"
|
||||
echo ""
|
||||
echo "Count gene expression and protein expression reads from a single capture area."
|
||||
echo ""
|
||||
@@ -775,7 +775,7 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 1
|
||||
;;
|
||||
--version)
|
||||
echo "spaceranger_count v0.1.0"
|
||||
echo "spaceranger_count v0.1.1"
|
||||
exit
|
||||
;;
|
||||
--gex_reference)
|
||||
@@ -1135,7 +1135,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
|
||||
|
||||
# determine docker image id
|
||||
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/mapping/spaceranger_count:v0.1.0'
|
||||
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/mapping/spaceranger_count:v0.1.1'
|
||||
fi
|
||||
|
||||
# print dockerfile
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_cells2stats_to_h5mu"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -150,6 +150,8 @@ resources:
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "setup_logger.py"
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.py"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -256,7 +258,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.13-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -274,6 +276,10 @@ engines:
|
||||
nelse: exit(1)\")"
|
||||
upgrade: true
|
||||
test_setup:
|
||||
- type: "apt"
|
||||
packages:
|
||||
- "zip"
|
||||
interactive: false
|
||||
- type: "python"
|
||||
user: false
|
||||
packages:
|
||||
@@ -290,11 +296,11 @@ build_info:
|
||||
output: "target/nextflow/convert/from_cells2stats_to_h5mu"
|
||||
executable: "target/nextflow/convert/from_cells2stats_to_h5mu/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -314,7 +320,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// from_cells2stats_to_h5mu v0.1.0
|
||||
// from_cells2stats_to_h5mu v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3035,7 +3035,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "from_cells2stats_to_h5mu",
|
||||
"namespace" : "convert",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dorien Roosen",
|
||||
@@ -3214,6 +3214,10 @@ meta = [
|
||||
"type" : "file",
|
||||
"path" : "/src/utils/setup_logger.py"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/utils/unzip_archived_folder.py"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/workflows/utils/labels.config",
|
||||
@@ -3336,7 +3340,7 @@ meta = [
|
||||
"id" : "docker",
|
||||
"image" : "python:3.13-slim",
|
||||
"target_registry" : "images.viash-hub.com",
|
||||
"target_tag" : "v0.1.0",
|
||||
"target_tag" : "v0.1.1",
|
||||
"namespace_separator" : "/",
|
||||
"setup" : [
|
||||
{
|
||||
@@ -3361,6 +3365,13 @@ meta = [
|
||||
}
|
||||
],
|
||||
"test_setup" : [
|
||||
{
|
||||
"type" : "apt",
|
||||
"packages" : [
|
||||
"zip"
|
||||
],
|
||||
"interactive" : false
|
||||
},
|
||||
{
|
||||
"type" : "python",
|
||||
"user" : false,
|
||||
@@ -3382,12 +3393,12 @@ meta = [
|
||||
"engine" : "docker|native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/convert/from_cells2stats_to_h5mu",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3412,7 +3423,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
@@ -3440,6 +3451,8 @@ import mudata as mu
|
||||
import anndata as ad
|
||||
import re
|
||||
import json
|
||||
import zipfile
|
||||
import os
|
||||
|
||||
## VIASH START
|
||||
# The following code has been auto-generated by Viash.
|
||||
@@ -3483,6 +3496,8 @@ dep = {
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import extract_selected_files_from_zip
|
||||
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
@@ -3620,27 +3635,43 @@ def categorize_columns(column_list, target_panel):
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
# Read data from Aviti Teton output bundle
|
||||
def retrieve_input_data(cells2stats_output_bundle):
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── Cytoprofiling/
|
||||
# │ └── Instrument/
|
||||
# │ └── RawCellStats.parquet
|
||||
# └── Panel.json
|
||||
|
||||
logger.info("Reading input data...")
|
||||
input_dir = Path(par["input"])
|
||||
input_data = {
|
||||
"count_matrix": input_dir
|
||||
/ "Cytoprofiling"
|
||||
/ "Instrument"
|
||||
/ "RawCellStats.parquet",
|
||||
"target_panel": input_dir / "Panel.json",
|
||||
required_file_patterns = {
|
||||
"target_panel": "**/Panel.json",
|
||||
"count_matrix": "**/Cytoprofiling/Instrument/RawCellStats.parquet",
|
||||
}
|
||||
|
||||
assert all([file.exists() for file in input_data.values()]), (
|
||||
f"Not all required input files are found. Make sure that {par['input']} contains {input_data.values()}."
|
||||
if zipfile.is_zipfile(cells2stats_output_bundle):
|
||||
cells2stats_output_bundle = extract_selected_files_from_zip(
|
||||
cells2stats_output_bundle, members=required_file_patterns.values()
|
||||
)
|
||||
else:
|
||||
cells2stats_output_bundle = Path(cells2stats_output_bundle)
|
||||
|
||||
assert os.path.isdir(cells2stats_output_bundle), (
|
||||
"Input is expected to be a (compressed) directory."
|
||||
)
|
||||
|
||||
input_data = {}
|
||||
for key, pattern in required_file_patterns.items():
|
||||
file = list(cells2stats_output_bundle.glob(pattern))
|
||||
assert len(file) == 1, (
|
||||
f"Expected exactly one file matching pattern {pattern}, found {len(file)}."
|
||||
)
|
||||
input_data[key] = file[0]
|
||||
|
||||
return input_data
|
||||
|
||||
|
||||
def main():
|
||||
logger.info("Reading input data...")
|
||||
input_data = retrieve_input_data(par["input"])
|
||||
with open(input_data["target_panel"], "r") as f:
|
||||
target_panel = json.load(f)
|
||||
df = pd.read_parquet(input_data["count_matrix"], engine="pyarrow")
|
||||
@@ -4123,7 +4154,7 @@ meta["defaults"] = [
|
||||
"container" : {
|
||||
"registry" : "images.viash-hub.com",
|
||||
"image" : "vsh/openpipeline_spatial/convert/from_cells2stats_to_h5mu",
|
||||
"tag" : "v0.1.0"
|
||||
"tag" : "v0.1.1"
|
||||
},
|
||||
"label" : [
|
||||
"lowmem",
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'convert/from_cells2stats_to_h5mu'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'Convert spatial data resulting from Aviti Teton sequencers that have been processed by the Element Biosciences cells2stats workflow to H5MU format.\n\nThis component processes cells2stats count matrices to create a standardized H5MU file for downstream analysis.\n\nThe component reads:\n- Parquet file containing the count matrix and metadata\n- Panel.json with target and batch information\n\nAnd outputs an H5MU file with:\n- Count data as the main .X matrix\n- Spatial coordinates in obsm\n- Cell Paint intensities in obsm (optional)\n- Nuclear count data as a layer (optional)\n- CellProfiler morphology metrics in obsm (optional)\n- Unassigned targets in obsm (optional)\n'
|
||||
author = 'Dorien Roosen'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import fnmatch
|
||||
import zipfile
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
|
||||
def unzip_archived_folder(archived_folder: Union[str, Path]) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts a ZIP archive to a temporary directory and returns the path to the extracted folder.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
|
||||
Returns:
|
||||
extracted_path (Union[str, Path]): Path to the extracted folder inside the temporary directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
with zipfile.ZipFile(archived_folder, "r") as archive:
|
||||
archive.extractall(temp_dir)
|
||||
|
||||
return temp_dir / Path(archived_folder).stem
|
||||
|
||||
|
||||
def extract_selected_files_from_zip(
|
||||
zip_path: Union[str, Path], members: list[Union[str, Path]]
|
||||
) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts selected files (supports glob patterns) from a ZIP archive to a temporary directory.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
members (list[str]): List of file paths within the archive to extract.
|
||||
|
||||
Returns:
|
||||
Path: Path to the extraction directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
|
||||
with zipfile.ZipFile(zip_path, "r") as archive:
|
||||
all_files = archive.namelist()
|
||||
selected = set()
|
||||
for pattern in members:
|
||||
selected.update(fnmatch.filter(all_files, str(pattern)))
|
||||
for member in selected:
|
||||
archive.extract(member, temp_dir)
|
||||
|
||||
return temp_dir
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_cosmx_to_h5mu"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -81,6 +81,8 @@ resources:
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "setup_logger.py"
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.py"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -184,7 +186,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.12-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -214,6 +216,10 @@ engines:
|
||||
github:
|
||||
- "openpipelines-bio/core#subdirectory=packages/python/openpipeline_testutils"
|
||||
upgrade: true
|
||||
- type: "apt"
|
||||
packages:
|
||||
- "zip"
|
||||
interactive: false
|
||||
entrypoint: []
|
||||
cmd: null
|
||||
- type: "native"
|
||||
@@ -225,11 +231,11 @@ build_info:
|
||||
output: "target/nextflow/convert/from_cosmx_to_h5mu"
|
||||
executable: "target/nextflow/convert/from_cosmx_to_h5mu/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -249,7 +255,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// from_cosmx_to_h5mu v0.1.0
|
||||
// from_cosmx_to_h5mu v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3036,7 +3036,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "from_cosmx_to_h5mu",
|
||||
"namespace" : "convert",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dorien Roosen",
|
||||
@@ -3152,6 +3152,10 @@ meta = [
|
||||
"type" : "file",
|
||||
"path" : "/src/utils/setup_logger.py"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/utils/unzip_archived_folder.py"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/workflows/utils/labels.config",
|
||||
@@ -3274,7 +3278,7 @@ meta = [
|
||||
"id" : "docker",
|
||||
"image" : "python:3.12-slim",
|
||||
"target_registry" : "images.viash-hub.com",
|
||||
"target_tag" : "v0.1.0",
|
||||
"target_tag" : "v0.1.1",
|
||||
"namespace_separator" : "/",
|
||||
"setup" : [
|
||||
{
|
||||
@@ -3317,6 +3321,13 @@ meta = [
|
||||
"openpipelines-bio/core#subdirectory=packages/python/openpipeline_testutils"
|
||||
],
|
||||
"upgrade" : true
|
||||
},
|
||||
{
|
||||
"type" : "apt",
|
||||
"packages" : [
|
||||
"zip"
|
||||
],
|
||||
"interactive" : false
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3331,12 +3342,12 @@ meta = [
|
||||
"engine" : "docker|native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/convert/from_cosmx_to_h5mu",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3361,7 +3372,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
@@ -3385,7 +3396,8 @@ import sys
|
||||
import os
|
||||
import squidpy as sq
|
||||
import mudata as mu
|
||||
import glob
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
## VIASH START
|
||||
# The following code has been auto-generated by Viash.
|
||||
@@ -3423,31 +3435,60 @@ dep = {
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import extract_selected_files_from_zip
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
|
||||
def find_matrix_file(suffix):
|
||||
pattern = os.path.join(par["input"], f"*{suffix}")
|
||||
files = glob.glob(pattern)
|
||||
assert len(files) == 1, (
|
||||
f"Only one file matching pattern {pattern} should be present"
|
||||
def retrieve_input_data(cosmx_output_bundle):
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── *_exprMat_file.csv
|
||||
# ├── *_fov_positions_file.csv
|
||||
# └── *_metadata_file.csv
|
||||
|
||||
required_file_patterns = {
|
||||
"counts_file": "**/*exprMat_file.csv",
|
||||
"fov_file": "**/*fov_positions_file.csv",
|
||||
"meta_file": "**/*metadata_file.csv",
|
||||
}
|
||||
if zipfile.is_zipfile(cosmx_output_bundle):
|
||||
cosmx_output_bundle = extract_selected_files_from_zip(
|
||||
cosmx_output_bundle, members=required_file_patterns.values()
|
||||
)
|
||||
else:
|
||||
cosmx_output_bundle = Path(cosmx_output_bundle)
|
||||
|
||||
assert os.path.isdir(cosmx_output_bundle), (
|
||||
"Input is expected to be a (compressed) directory."
|
||||
)
|
||||
return files[0]
|
||||
|
||||
input_data = {}
|
||||
for key, pattern in required_file_patterns.items():
|
||||
file = list(cosmx_output_bundle.glob(pattern))
|
||||
assert len(file) == 1, f"Expected one file for {key}, found {len(file)}."
|
||||
input_data[key] = file[0]
|
||||
|
||||
return input_data
|
||||
|
||||
|
||||
counts_file = find_matrix_file("exprMat_file.csv")
|
||||
fov_file = find_matrix_file("fov_positions_file.csv")
|
||||
meta_file = find_matrix_file("metadata_file.csv")
|
||||
def main():
|
||||
logger.info("Reading in CosMx data...")
|
||||
input_data = retrieve_input_data(par["input"])
|
||||
|
||||
logger.info("Reading in CosMx data...")
|
||||
adata = sq.read.nanostring(
|
||||
path=par["input"], counts_file=counts_file, meta_file=meta_file, fov_file=fov_file
|
||||
)
|
||||
adata = sq.read.nanostring(
|
||||
path=par["input"],
|
||||
counts_file=input_data["counts_file"],
|
||||
meta_file=input_data["meta_file"],
|
||||
fov_file=input_data["fov_file"],
|
||||
)
|
||||
|
||||
logger.info("Writing output MuData object...")
|
||||
mdata = mu.MuData({par["modality"]: adata})
|
||||
mdata.write_h5mu(par["output"], compression=par["output_compression"])
|
||||
logger.info("Writing output MuData object...")
|
||||
mdata = mu.MuData({par["modality"]: adata})
|
||||
mdata.write_h5mu(par["output"], compression=par["output_compression"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
VIASHMAIN
|
||||
python -B "$tempscript"
|
||||
'''
|
||||
@@ -3830,7 +3871,7 @@ meta["defaults"] = [
|
||||
"container" : {
|
||||
"registry" : "images.viash-hub.com",
|
||||
"image" : "vsh/openpipeline_spatial/convert/from_cosmx_to_h5mu",
|
||||
"tag" : "v0.1.0"
|
||||
"tag" : "v0.1.1"
|
||||
},
|
||||
"label" : [
|
||||
"lowmem",
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'convert/from_cosmx_to_h5mu'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'Converts the output from NanoString experiment into a MuData objcet.\n - `<dataset_id>_exprMat_file.csv`: File containing the counts.\n - `<dataset_id>`_metadata_file: File containing the spatial coordinates and additional cell-level metadata.\n - `<dataset_id>_fov_file.csv`: File containing the coordinates of all the fields of view.\nIn addition to reading the regular Nanostring output, it loads CellComposite and CellLabels directories, if present,\ncontaining the images.\n'
|
||||
author = 'Dorien Roosen, Weiwei Schultz'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import fnmatch
|
||||
import zipfile
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
|
||||
def unzip_archived_folder(archived_folder: Union[str, Path]) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts a ZIP archive to a temporary directory and returns the path to the extracted folder.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
|
||||
Returns:
|
||||
extracted_path (Union[str, Path]): Path to the extracted folder inside the temporary directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
with zipfile.ZipFile(archived_folder, "r") as archive:
|
||||
archive.extractall(temp_dir)
|
||||
|
||||
return temp_dir / Path(archived_folder).stem
|
||||
|
||||
|
||||
def extract_selected_files_from_zip(
|
||||
zip_path: Union[str, Path], members: list[Union[str, Path]]
|
||||
) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts selected files (supports glob patterns) from a ZIP archive to a temporary directory.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
members (list[str]): List of file paths within the archive to extract.
|
||||
|
||||
Returns:
|
||||
Path: Path to the extraction directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
|
||||
with zipfile.ZipFile(zip_path, "r") as archive:
|
||||
all_files = archive.namelist()
|
||||
selected = set()
|
||||
for pattern in members:
|
||||
selected.update(fnmatch.filter(all_files, str(pattern)))
|
||||
for member in selected:
|
||||
archive.extract(member, temp_dir)
|
||||
|
||||
return temp_dir
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_cosmx_to_spatialexperiment"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -98,6 +98,8 @@ resources:
|
||||
- type: "r_script"
|
||||
path: "script.R"
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.R"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -202,7 +204,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "rocker/r2u:24.04"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -232,11 +234,11 @@ build_info:
|
||||
output: "target/nextflow/convert/from_cosmx_to_spatialexperiment"
|
||||
executable: "target/nextflow/convert/from_cosmx_to_spatialexperiment/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -256,7 +258,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// from_cosmx_to_spatialexperiment v0.1.0
|
||||
// from_cosmx_to_spatialexperiment v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3035,7 +3035,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "from_cosmx_to_spatialexperiment",
|
||||
"namespace" : "convert",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dorien Roosen",
|
||||
@@ -3158,6 +3158,10 @@ meta = [
|
||||
"path" : "script.R",
|
||||
"is_executable" : true
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/utils/unzip_archived_folder.R"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/workflows/utils/labels.config",
|
||||
@@ -3280,7 +3284,7 @@ meta = [
|
||||
"id" : "docker",
|
||||
"image" : "rocker/r2u:24.04",
|
||||
"target_registry" : "images.viash-hub.com",
|
||||
"target_tag" : "v0.1.0",
|
||||
"target_tag" : "v0.1.1",
|
||||
"namespace_separator" : "/",
|
||||
"setup" : [
|
||||
{
|
||||
@@ -3322,12 +3326,12 @@ meta = [
|
||||
"engine" : "docker|native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/convert/from_cosmx_to_spatialexperiment",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3352,7 +3356,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
@@ -3418,14 +3422,36 @@ rm(.viash_orig_warn)
|
||||
|
||||
### VIASH END
|
||||
|
||||
source(paste0(meta\\$resources_dir, "/unzip_archived_folder.R"))
|
||||
|
||||
cat("Reading input data...")
|
||||
if (tools::file_ext(par\\$input) == "zip") {
|
||||
expected_file_patterns <- c(
|
||||
"*.csv",
|
||||
"*.parquet"
|
||||
)
|
||||
tmp_dir <- extract_selected_files(
|
||||
par\\$input,
|
||||
members = expected_file_patterns
|
||||
)
|
||||
cosmx_output_bundle <- file.path(
|
||||
tmp_dir,
|
||||
tools::file_path_sans_ext(basename(par\\$input))
|
||||
)
|
||||
} else {
|
||||
cosmx_output_bundle <- par\\$input
|
||||
}
|
||||
|
||||
cat("Setting parameters...")
|
||||
if (par\\$add_polygon_path == FALSE && par\\$add_tx_path == FALSE) {
|
||||
add_parquet_paths <- FALSE
|
||||
} else {
|
||||
add_parquet_paths <- TRUE
|
||||
}
|
||||
|
||||
cat("Converting to SpatialExperiment...")
|
||||
spe <- readCosmxSXE(
|
||||
dirName = par\\$input,
|
||||
dirName = cosmx_output_bundle,
|
||||
returnType = "SPE",
|
||||
countMatPattern = "exprMat_file.csv",
|
||||
metaDataPattern = "metadata_file.csv",
|
||||
@@ -3438,6 +3464,7 @@ spe <- readCosmxSXE(
|
||||
altExps = par\\$alternative_experiment_features
|
||||
)
|
||||
|
||||
cat("Saving output...")
|
||||
saveRDS(spe, file = par\\$output)
|
||||
VIASHMAIN
|
||||
Rscript "$tempscript"
|
||||
@@ -3821,7 +3848,7 @@ meta["defaults"] = [
|
||||
"container" : {
|
||||
"registry" : "images.viash-hub.com",
|
||||
"image" : "vsh/openpipeline_spatial/convert/from_cosmx_to_spatialexperiment",
|
||||
"tag" : "v0.1.0"
|
||||
"tag" : "v0.1.1"
|
||||
},
|
||||
"label" : [
|
||||
"lowmem",
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'convert/from_cosmx_to_spatialexperiment'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'Creates a SpatialExperiment object from the downloaded unzipped CosMx directory for Nanostring\nCosMx spatial gene expression data, and saves it as a SpatialExperiment object.\nThe constructor assumes the downloaded unzipped CosMx Folder has the following structure:\n\nMandatory files\n· | — *_exprMat_file.csv\n· | — *_metadata_file.csv\nOptional files, by default added to the metadata() as a list of paths (will be converted to parquet):\n· | —*_fov_positions_file.csv\n· | — *_tx_file.csv\n· | — *_polygons.csv\n'
|
||||
author = 'Dorien Roosen'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
extract_selected_files <- function(zip_path, members) {
|
||||
# Create a temporary directory for extraction
|
||||
temp_dir <- tempfile("unzip_dir_")
|
||||
dir.create(temp_dir)
|
||||
|
||||
# List all files in the archive
|
||||
all_files <- utils::unzip(zip_path, list = TRUE)$Name
|
||||
|
||||
# Find files matching any of the glob patterns in 'members'
|
||||
selected <- unique(unlist(
|
||||
lapply(members, function(pattern) {
|
||||
regex <- glob2rx(pattern)
|
||||
grep(regex, all_files, value = TRUE)
|
||||
})
|
||||
))
|
||||
|
||||
# Extract only the selected files
|
||||
utils::unzip(zip_path, files = selected, exdir = temp_dir)
|
||||
|
||||
# Return the path to the extracted folder
|
||||
file.path(temp_dir)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_h5mu_to_spatialexperiment"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -171,7 +171,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "rocker/r2u:22.04"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -224,11 +224,11 @@ build_info:
|
||||
output: "target/nextflow/convert/from_h5mu_to_spatialexperiment"
|
||||
executable: "target/nextflow/convert/from_h5mu_to_spatialexperiment/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -248,7 +248,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// from_h5mu_to_spatialexperiment v0.1.0
|
||||
// from_h5mu_to_spatialexperiment v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3035,7 +3035,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "from_h5mu_to_spatialexperiment",
|
||||
"namespace" : "convert",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dorien Roosen",
|
||||
@@ -3257,7 +3257,7 @@ meta = [
|
||||
"id" : "docker",
|
||||
"image" : "rocker/r2u:22.04",
|
||||
"target_registry" : "images.viash-hub.com",
|
||||
"target_tag" : "v0.1.0",
|
||||
"target_tag" : "v0.1.1",
|
||||
"namespace_separator" : "/",
|
||||
"setup" : [
|
||||
{
|
||||
@@ -3332,12 +3332,12 @@ meta = [
|
||||
"engine" : "docker|native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/convert/from_h5mu_to_spatialexperiment",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3362,7 +3362,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
@@ -3910,7 +3910,7 @@ meta["defaults"] = [
|
||||
"container" : {
|
||||
"registry" : "images.viash-hub.com",
|
||||
"image" : "vsh/openpipeline_spatial/convert/from_h5mu_to_spatialexperiment",
|
||||
"tag" : "v0.1.0"
|
||||
"tag" : "v0.1.1"
|
||||
},
|
||||
"label" : [
|
||||
"lowmem",
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'convert/from_h5mu_to_spatialexperiment'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'Converts an h5mu file into a SpatialExperiment object.\n'
|
||||
author = 'Dorien Roosen'
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_spatialdata_to_h5mu"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -180,7 +180,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.12-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -220,11 +220,11 @@ build_info:
|
||||
output: "target/nextflow/convert/from_spatialdata_to_h5mu"
|
||||
executable: "target/nextflow/convert/from_spatialdata_to_h5mu/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -244,7 +244,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// from_spatialdata_to_h5mu v0.1.0
|
||||
// from_spatialdata_to_h5mu v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3036,7 +3036,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "from_spatialdata_to_h5mu",
|
||||
"namespace" : "convert",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dorien Roosen",
|
||||
@@ -3274,7 +3274,7 @@ meta = [
|
||||
"id" : "docker",
|
||||
"image" : "python:3.12-slim",
|
||||
"target_registry" : "images.viash-hub.com",
|
||||
"target_tag" : "v0.1.0",
|
||||
"target_tag" : "v0.1.1",
|
||||
"namespace_separator" : "/",
|
||||
"setup" : [
|
||||
{
|
||||
@@ -3330,12 +3330,12 @@ meta = [
|
||||
"engine" : "docker|native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/convert/from_spatialdata_to_h5mu",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3360,7 +3360,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
@@ -3814,7 +3814,7 @@ meta["defaults"] = [
|
||||
"container" : {
|
||||
"registry" : "images.viash-hub.com",
|
||||
"image" : "vsh/openpipeline_spatial/convert/from_spatialdata_to_h5mu",
|
||||
"tag" : "v0.1.0"
|
||||
"tag" : "v0.1.1"
|
||||
},
|
||||
"label" : [
|
||||
"lowmem",
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'convert/from_spatialdata_to_h5mu'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'Reads in the Tables field stored in a SpatialData object and converts it to an h5mu file.\n \n'
|
||||
author = 'Dorien Roosen, Weiwei Schultz'
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_xenium_to_h5mu"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -97,6 +97,8 @@ resources:
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "setup_logger.py"
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.py"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -198,7 +200,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.12-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -217,6 +219,10 @@ engines:
|
||||
nelse: exit(1)\")"
|
||||
upgrade: true
|
||||
test_setup:
|
||||
- type: "apt"
|
||||
packages:
|
||||
- "zip"
|
||||
interactive: false
|
||||
- type: "python"
|
||||
user: false
|
||||
packages:
|
||||
@@ -233,11 +239,11 @@ build_info:
|
||||
output: "target/nextflow/convert/from_xenium_to_h5mu"
|
||||
executable: "target/nextflow/convert/from_xenium_to_h5mu/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -257,7 +263,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// from_xenium_to_h5mu v0.1.0
|
||||
// from_xenium_to_h5mu v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3035,7 +3035,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "from_xenium_to_h5mu",
|
||||
"namespace" : "convert",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dorien Roosen",
|
||||
@@ -3162,6 +3162,10 @@ meta = [
|
||||
"type" : "file",
|
||||
"path" : "/src/utils/setup_logger.py"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/utils/unzip_archived_folder.py"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/workflows/utils/labels.config",
|
||||
@@ -3284,7 +3288,7 @@ meta = [
|
||||
"id" : "docker",
|
||||
"image" : "python:3.12-slim",
|
||||
"target_registry" : "images.viash-hub.com",
|
||||
"target_tag" : "v0.1.0",
|
||||
"target_tag" : "v0.1.1",
|
||||
"namespace_separator" : "/",
|
||||
"setup" : [
|
||||
{
|
||||
@@ -3310,6 +3314,13 @@ meta = [
|
||||
}
|
||||
],
|
||||
"test_setup" : [
|
||||
{
|
||||
"type" : "apt",
|
||||
"packages" : [
|
||||
"zip"
|
||||
],
|
||||
"interactive" : false
|
||||
},
|
||||
{
|
||||
"type" : "python",
|
||||
"user" : false,
|
||||
@@ -3331,12 +3342,12 @@ meta = [
|
||||
"engine" : "docker|native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/convert/from_xenium_to_h5mu",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3361,7 +3372,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
@@ -3386,7 +3397,9 @@ from pathlib import Path
|
||||
import scanpy as sc
|
||||
import pandas as pd
|
||||
import mudata as mu
|
||||
import zipfile
|
||||
import json
|
||||
import os
|
||||
|
||||
## VIASH START
|
||||
# The following code has been auto-generated by Viash.
|
||||
@@ -3426,21 +3439,46 @@ dep = {
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import extract_selected_files_from_zip
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── cell_feature_matrix.h5
|
||||
# ├── cells.parquet
|
||||
# ├── experiment.xenium
|
||||
# └── metrics_summary.csv
|
||||
input_dir = Path(par["input"])
|
||||
input_data = {
|
||||
"count_matrix": input_dir / "cell_feature_matrix.h5",
|
||||
"cells_metadata": input_dir / "cells.parquet",
|
||||
"experiment": input_dir / "experiment.xenium",
|
||||
"metrics_summary": input_dir / "metrics_summary.csv",
|
||||
}
|
||||
|
||||
def _retrieve_input_data(xenium_output_bundle):
|
||||
# Expected folder structure (showing only relevant files):
|
||||
# ├── cell_feature_matrix.h5
|
||||
# ├── cells.parquet
|
||||
# ├── experiment.xenium
|
||||
# └── metrics_summary.csv
|
||||
|
||||
required_file_patterns = {
|
||||
"count_matrix": "**/cell_feature_matrix.h5",
|
||||
"cells_metadata": "**/cells.parquet",
|
||||
"experiment": "**/experiment.xenium",
|
||||
"metrics_summary": "**/metrics_summary.csv",
|
||||
}
|
||||
|
||||
if zipfile.is_zipfile(xenium_output_bundle):
|
||||
xenium_output_bundle = extract_selected_files_from_zip(
|
||||
xenium_output_bundle,
|
||||
members=[pattern for pattern in required_file_patterns.values()],
|
||||
)
|
||||
else:
|
||||
xenium_output_bundle = Path(xenium_output_bundle)
|
||||
|
||||
assert os.path.isdir(xenium_output_bundle), (
|
||||
"Input is expected to be a (compressed) directory."
|
||||
)
|
||||
|
||||
input_data = {}
|
||||
for key, pattern in required_file_patterns.items():
|
||||
file = list(xenium_output_bundle.glob(pattern))
|
||||
assert len(file) == 1, (
|
||||
f"Expected exactly one file matching pattern {pattern}, found {len(file)}."
|
||||
)
|
||||
input_data[key] = file[0]
|
||||
|
||||
return input_data
|
||||
|
||||
|
||||
def _format_cell_id_column(cell_id_column: pd.Series) -> pd.Series:
|
||||
@@ -3453,9 +3491,7 @@ def _format_cell_id_column(cell_id_column: pd.Series) -> pd.Series:
|
||||
# Read data from Xenium output bundle
|
||||
logger.info("Reading input data...")
|
||||
|
||||
assert all([file.exists() for file in input_data.values()]), (
|
||||
f"Not all required input files are found. Make sure that {par['input']} contains {input_data.values()}."
|
||||
)
|
||||
input_data = _retrieve_input_data(par["input"])
|
||||
|
||||
adata = sc.read_10x_h5(input_data["count_matrix"])
|
||||
metadata = pd.read_parquet(input_data["cells_metadata"], engine="pyarrow")
|
||||
@@ -3862,7 +3898,7 @@ meta["defaults"] = [
|
||||
"container" : {
|
||||
"registry" : "images.viash-hub.com",
|
||||
"image" : "vsh/openpipeline_spatial/convert/from_xenium_to_h5mu",
|
||||
"tag" : "v0.1.0"
|
||||
"tag" : "v0.1.1"
|
||||
},
|
||||
"label" : [
|
||||
"lowmem",
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'convert/from_xenium_to_h5mu'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'Converts the output from Xenium to a single .h5mu file, where the count matrix is written to the `rna` modality.\nThe following files are expected to be present in the Xenium output bundle:\n├── cell_feature_matrix.h5\n├── cells.parquet\n├── experiment.xenium\n└── metrics_summary.csv\n'
|
||||
author = 'Dorien Roosen'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import fnmatch
|
||||
import zipfile
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
|
||||
def unzip_archived_folder(archived_folder: Union[str, Path]) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts a ZIP archive to a temporary directory and returns the path to the extracted folder.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
|
||||
Returns:
|
||||
extracted_path (Union[str, Path]): Path to the extracted folder inside the temporary directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
with zipfile.ZipFile(archived_folder, "r") as archive:
|
||||
archive.extractall(temp_dir)
|
||||
|
||||
return temp_dir / Path(archived_folder).stem
|
||||
|
||||
|
||||
def extract_selected_files_from_zip(
|
||||
zip_path: Union[str, Path], members: list[Union[str, Path]]
|
||||
) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts selected files (supports glob patterns) from a ZIP archive to a temporary directory.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
members (list[str]): List of file paths within the archive to extract.
|
||||
|
||||
Returns:
|
||||
Path: Path to the extraction directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
|
||||
with zipfile.ZipFile(zip_path, "r") as archive:
|
||||
all_files = archive.namelist()
|
||||
selected = set()
|
||||
for pattern in members:
|
||||
selected.update(fnmatch.filter(all_files, str(pattern)))
|
||||
for member in selected:
|
||||
archive.extract(member, temp_dir)
|
||||
|
||||
return temp_dir
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_xenium_to_spatialdata"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -173,6 +173,8 @@ resources:
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "setup_logger.py"
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.py"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -278,7 +280,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.12-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -303,6 +305,10 @@ engines:
|
||||
github:
|
||||
- "openpipelines-bio/core#subdirectory=packages/python/openpipeline_testutils"
|
||||
upgrade: true
|
||||
- type: "apt"
|
||||
packages:
|
||||
- "zip"
|
||||
interactive: false
|
||||
entrypoint: []
|
||||
cmd: null
|
||||
- type: "native"
|
||||
@@ -314,11 +320,11 @@ build_info:
|
||||
output: "target/nextflow/convert/from_xenium_to_spatialdata"
|
||||
executable: "target/nextflow/convert/from_xenium_to_spatialdata/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -338,7 +344,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// from_xenium_to_spatialdata v0.1.0
|
||||
// from_xenium_to_spatialdata v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3036,7 +3036,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "from_xenium_to_spatialdata",
|
||||
"namespace" : "convert",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dorien Roosen",
|
||||
@@ -3251,6 +3251,10 @@ meta = [
|
||||
"type" : "file",
|
||||
"path" : "/src/utils/setup_logger.py"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/utils/unzip_archived_folder.py"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/workflows/utils/labels.config",
|
||||
@@ -3373,7 +3377,7 @@ meta = [
|
||||
"id" : "docker",
|
||||
"image" : "python:3.12-slim",
|
||||
"target_registry" : "images.viash-hub.com",
|
||||
"target_tag" : "v0.1.0",
|
||||
"target_tag" : "v0.1.1",
|
||||
"namespace_separator" : "/",
|
||||
"setup" : [
|
||||
{
|
||||
@@ -3411,6 +3415,13 @@ meta = [
|
||||
"openpipelines-bio/core#subdirectory=packages/python/openpipeline_testutils"
|
||||
],
|
||||
"upgrade" : true
|
||||
},
|
||||
{
|
||||
"type" : "apt",
|
||||
"packages" : [
|
||||
"zip"
|
||||
],
|
||||
"interactive" : false
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3425,12 +3436,12 @@ meta = [
|
||||
"engine" : "docker|native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/convert/from_xenium_to_spatialdata",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3455,7 +3466,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
@@ -3477,6 +3488,8 @@ tempscript=".viash_script.py"
|
||||
cat > "$tempscript" << VIASHMAIN
|
||||
import sys
|
||||
from spatialdata_io import xenium
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
## VIASH START
|
||||
# The following code has been auto-generated by Viash.
|
||||
@@ -3523,12 +3536,29 @@ dep = {
|
||||
|
||||
sys.path.append(meta["resources_dir"])
|
||||
from setup_logger import setup_logger
|
||||
from unzip_archived_folder import unzip_archived_folder
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
logger.info("Reading in Xenium data...")
|
||||
|
||||
if zipfile.is_zipfile(par["input"]):
|
||||
required_file_patterns = [
|
||||
"**/experiment.xenium",
|
||||
"**/nucleus_boundaries.parquet",
|
||||
"**/cell_boundaries.parquet",
|
||||
"**/transcripts.parquet",
|
||||
"**/cell_feature_matrix.h5",
|
||||
"**/cells.parquet",
|
||||
"**/morphology_mip.ome.tif",
|
||||
"**/morphology_focus.ome.tif",
|
||||
]
|
||||
xenium_output_bundle = unzip_archived_folder(par["input"])
|
||||
else:
|
||||
xenium_output_bundle = Path(par["input"])
|
||||
|
||||
sdata = xenium(
|
||||
par["input"],
|
||||
xenium_output_bundle,
|
||||
cells_boundaries=par["cells_boundaries"],
|
||||
nucleus_boundaries=par["nucleus_boundaries"],
|
||||
cells_as_circles=par["cells_as_circles"],
|
||||
@@ -3927,7 +3957,7 @@ meta["defaults"] = [
|
||||
"container" : {
|
||||
"registry" : "images.viash-hub.com",
|
||||
"image" : "vsh/openpipeline_spatial/convert/from_xenium_to_spatialdata",
|
||||
"tag" : "v0.1.0"
|
||||
"tag" : "v0.1.1"
|
||||
},
|
||||
"label" : [
|
||||
"lowmem",
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'convert/from_xenium_to_spatialdata'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'Converts the output from 10X Genomics Xenium dataset into a SpatialData objcet.\nBy default, the following files will be converted:\n - `experiment.xenium`: File containing specifications.\n - `nucleus_boundaries.parquet`: Polygons of nucleus boundaries.\n - `cell_boundaries.parquet`: Polygons of cell boundaries.\n - `transcripts.parquet`: File containing transcripts.\n - `cell_feature_matrix.h5`: File containing cell feature matrix.\n - `cells.parquet`: File containing cell metadata.\n - `morphology_mip.ome.tif`: File containing morphology mip.\n - `morphology_focus.ome.tif`: File containing morphology focus.\n \n'
|
||||
author = 'Dorien Roosen, Weiwei Schultz'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import fnmatch
|
||||
import zipfile
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
|
||||
def unzip_archived_folder(archived_folder: Union[str, Path]) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts a ZIP archive to a temporary directory and returns the path to the extracted folder.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
|
||||
Returns:
|
||||
extracted_path (Union[str, Path]): Path to the extracted folder inside the temporary directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
with zipfile.ZipFile(archived_folder, "r") as archive:
|
||||
archive.extractall(temp_dir)
|
||||
|
||||
return temp_dir / Path(archived_folder).stem
|
||||
|
||||
|
||||
def extract_selected_files_from_zip(
|
||||
zip_path: Union[str, Path], members: list[Union[str, Path]]
|
||||
) -> Union[str, Path]:
|
||||
"""
|
||||
Extracts selected files (supports glob patterns) from a ZIP archive to a temporary directory.
|
||||
|
||||
Args:
|
||||
zip_path (Union[str, Path]): Path to the ZIP archive.
|
||||
members (list[str]): List of file paths within the archive to extract.
|
||||
|
||||
Returns:
|
||||
Path: Path to the extraction directory.
|
||||
"""
|
||||
|
||||
temp_dir = Path(tempfile.TemporaryDirectory().name)
|
||||
|
||||
with zipfile.ZipFile(zip_path, "r") as archive:
|
||||
all_files = archive.namelist()
|
||||
selected = set()
|
||||
for pattern in members:
|
||||
selected.update(fnmatch.filter(all_files, str(pattern)))
|
||||
for member in selected:
|
||||
archive.extract(member, temp_dir)
|
||||
|
||||
return temp_dir
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "from_xenium_to_spatialexperiment"
|
||||
namespace: "convert"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -88,6 +88,8 @@ resources:
|
||||
- type: "r_script"
|
||||
path: "script.R"
|
||||
is_executable: true
|
||||
- type: "file"
|
||||
path: "unzip_archived_folder.R"
|
||||
- type: "file"
|
||||
path: "nextflow_labels.config"
|
||||
dest: "nextflow_labels.config"
|
||||
@@ -192,7 +194,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "rocker/r2u:24.04"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -222,11 +224,11 @@ build_info:
|
||||
output: "target/nextflow/convert/from_xenium_to_spatialexperiment"
|
||||
executable: "target/nextflow/convert/from_xenium_to_spatialexperiment/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -246,7 +248,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// from_xenium_to_spatialexperiment v0.1.0
|
||||
// from_xenium_to_spatialexperiment v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3035,7 +3035,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "from_xenium_to_spatialexperiment",
|
||||
"namespace" : "convert",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dorien Roosen",
|
||||
@@ -3147,6 +3147,10 @@ meta = [
|
||||
"path" : "script.R",
|
||||
"is_executable" : true
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/utils/unzip_archived_folder.R"
|
||||
},
|
||||
{
|
||||
"type" : "file",
|
||||
"path" : "/src/workflows/utils/labels.config",
|
||||
@@ -3269,7 +3273,7 @@ meta = [
|
||||
"id" : "docker",
|
||||
"image" : "rocker/r2u:24.04",
|
||||
"target_registry" : "images.viash-hub.com",
|
||||
"target_tag" : "v0.1.0",
|
||||
"target_tag" : "v0.1.1",
|
||||
"namespace_separator" : "/",
|
||||
"setup" : [
|
||||
{
|
||||
@@ -3311,12 +3315,12 @@ meta = [
|
||||
"engine" : "docker|native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/convert/from_xenium_to_spatialexperiment",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3341,7 +3345,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
@@ -3406,9 +3410,30 @@ rm(.viash_orig_warn)
|
||||
|
||||
### VIASH END
|
||||
|
||||
source(paste0(meta\\$resources_dir, "/unzip_archived_folder.R"))
|
||||
|
||||
cat("Reading input data...")
|
||||
if (tools::file_ext(par\\$input) == "zip") {
|
||||
required_file_patterns <- c(
|
||||
"**/cell_feature_matrix.h5",
|
||||
"**/*.parquet",
|
||||
"**/experiment.xenium"
|
||||
)
|
||||
tmp_dir <- extract_selected_files(
|
||||
par\\$input,
|
||||
members = required_file_patterns
|
||||
)
|
||||
xenium_output_bundle <- file.path(
|
||||
tmp_dir,
|
||||
tools::file_path_sans_ext(basename(par\\$input))
|
||||
)
|
||||
} else {
|
||||
xenium_output_bundle <- par\\$input
|
||||
}
|
||||
|
||||
cat("Converting to SpatialExperiment")
|
||||
spe <- readXeniumSXE(
|
||||
dirName = par\\$input,
|
||||
dirName = xenium_output_bundle,
|
||||
returnType = "SPE",
|
||||
countMatPattern = "cell_feature_matrix.h5",
|
||||
metaDataPattern = "cells.parquet",
|
||||
@@ -3418,6 +3443,7 @@ spe <- readXeniumSXE(
|
||||
altExps = par\\$alternative_experiment_features
|
||||
)
|
||||
|
||||
cat("Saving output...")
|
||||
saveRDS(spe, file = par\\$output)
|
||||
VIASHMAIN
|
||||
Rscript "$tempscript"
|
||||
@@ -3801,7 +3827,7 @@ meta["defaults"] = [
|
||||
"container" : {
|
||||
"registry" : "images.viash-hub.com",
|
||||
"image" : "vsh/openpipeline_spatial/convert/from_xenium_to_spatialexperiment",
|
||||
"tag" : "v0.1.0"
|
||||
"tag" : "v0.1.1"
|
||||
},
|
||||
"label" : [
|
||||
"lowmem",
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'convert/from_xenium_to_spatialexperiment'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'Creates a SpatialExperiment object from the downloaded unzipped Xenium Output Bundle directory\nfor 10x Genomics Xenium spatial gene expression data, and saves it as a SpatialExperiment object.\nThe constructor assumes the downloaded unzipped Xenium Output Bundle has the following structure:\n\nMandatory files\n· | — cell_feature_matrix.h5\n· | — cells.parquet\nOptional files, by default added to the metadata() as a list of paths (will be converted to parquet):\n· | — transcripts.parquet\n· | — cell_boundaries.parquet\n· | — nucleus_boundaries.parquet\n· | — experiment.xenium\n'
|
||||
author = 'Dorien Roosen'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
extract_selected_files <- function(zip_path, members) {
|
||||
# Create a temporary directory for extraction
|
||||
temp_dir <- tempfile("unzip_dir_")
|
||||
dir.create(temp_dir)
|
||||
|
||||
# List all files in the archive
|
||||
all_files <- utils::unzip(zip_path, list = TRUE)$Name
|
||||
|
||||
# Find files matching any of the glob patterns in 'members'
|
||||
selected <- unique(unlist(
|
||||
lapply(members, function(pattern) {
|
||||
regex <- glob2rx(pattern)
|
||||
grep(regex, all_files, value = TRUE)
|
||||
})
|
||||
))
|
||||
|
||||
# Extract only the selected files
|
||||
utils::unzip(zip_path, files = selected, exdir = temp_dir)
|
||||
|
||||
# Return the path to the extracted folder
|
||||
file.path(temp_dir)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "subset_cosmx"
|
||||
namespace: "filter"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dorien Roosen"
|
||||
roles:
|
||||
@@ -191,7 +191,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "python:3.12-slim"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "apt"
|
||||
@@ -227,11 +227,11 @@ build_info:
|
||||
output: "target/nextflow/filter/subset_cosmx"
|
||||
executable: "target/nextflow/filter/subset_cosmx/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -251,7 +251,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// subset_cosmx v0.1.0
|
||||
// subset_cosmx v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3036,7 +3036,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "subset_cosmx",
|
||||
"namespace" : "filter",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dorien Roosen",
|
||||
@@ -3281,7 +3281,7 @@ meta = [
|
||||
"id" : "docker",
|
||||
"image" : "python:3.12-slim",
|
||||
"target_registry" : "images.viash-hub.com",
|
||||
"target_tag" : "v0.1.0",
|
||||
"target_tag" : "v0.1.1",
|
||||
"namespace_separator" : "/",
|
||||
"setup" : [
|
||||
{
|
||||
@@ -3333,12 +3333,12 @@ meta = [
|
||||
"engine" : "docker|native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/filter/subset_cosmx",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3363,7 +3363,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
@@ -3858,7 +3858,7 @@ meta["defaults"] = [
|
||||
"container" : {
|
||||
"registry" : "images.viash-hub.com",
|
||||
"image" : "vsh/openpipeline_spatial/filter/subset_cosmx",
|
||||
"tag" : "v0.1.0"
|
||||
"tag" : "v0.1.1"
|
||||
},
|
||||
"label" : [
|
||||
"lowmem",
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'filter/subset_cosmx'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'Filters the output from NanoString experiment to keep only a subset of the fields of view.\nExpected input folder structure:\npath/to/dataset/\n ├── CellComposite/\n ├── CellLabels/\n ├── CellOverlay/\n ├── CompartmentLabels/\n ├── <dataset_id>_exprMat_file.csv\n ├── <dataset_id>_fov_positions_file.csv\n ├── <dataset_id>_metadata_file.csv\n └── <dataset_id>_tx_file.csv \n'
|
||||
author = 'Dorien Roosen, Weiwei Schultz'
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "spaceranger_count"
|
||||
namespace: "mapping"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Jakub Majercik"
|
||||
roles:
|
||||
@@ -408,7 +408,7 @@ engines:
|
||||
id: "docker"
|
||||
image: "ghcr.io/data-intuitive/spaceranger:3.1"
|
||||
target_registry: "images.viash-hub.com"
|
||||
target_tag: "v0.1.0"
|
||||
target_tag: "v0.1.1"
|
||||
namespace_separator: "/"
|
||||
setup:
|
||||
- type: "docker"
|
||||
@@ -426,11 +426,11 @@ build_info:
|
||||
output: "target/nextflow/mapping/spaceranger_count"
|
||||
executable: "target/nextflow/mapping/spaceranger_count/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -450,7 +450,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// spaceranger_count v0.1.0
|
||||
// spaceranger_count v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3035,7 +3035,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "spaceranger_count",
|
||||
"namespace" : "mapping",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Jakub Majercik",
|
||||
@@ -3526,7 +3526,7 @@ meta = [
|
||||
"id" : "docker",
|
||||
"image" : "ghcr.io/data-intuitive/spaceranger:3.1",
|
||||
"target_registry" : "images.viash-hub.com",
|
||||
"target_tag" : "v0.1.0",
|
||||
"target_tag" : "v0.1.1",
|
||||
"namespace_separator" : "/",
|
||||
"setup" : [
|
||||
{
|
||||
@@ -3548,12 +3548,12 @@ meta = [
|
||||
"engine" : "docker|native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/mapping/spaceranger_count",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3578,7 +3578,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
@@ -4072,7 +4072,7 @@ meta["defaults"] = [
|
||||
"container" : {
|
||||
"registry" : "images.viash-hub.com",
|
||||
"image" : "vsh/openpipeline_spatial/mapping/spaceranger_count",
|
||||
"tag" : "v0.1.0"
|
||||
"tag" : "v0.1.1"
|
||||
},
|
||||
"tag" : "$id"
|
||||
}'''),
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'mapping/spaceranger_count'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'Count gene expression and protein expression reads from a single capture area.'
|
||||
author = 'Jakub Majercik'
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "spatial_process_samples"
|
||||
namespace: "workflows/multiomics"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dries Schaumont"
|
||||
roles:
|
||||
@@ -640,13 +640,13 @@ build_info:
|
||||
output: "target/nextflow/workflows/multiomics/spatial_process_samples"
|
||||
executable: "target/nextflow/workflows/multiomics/spatial_process_samples/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
dependencies:
|
||||
- "target/dependencies/vsh/vsh/openpipeline/v3.0.0/nextflow/workflows/multiomics/process_samples"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -666,7 +666,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// spatial_process_samples v0.1.0
|
||||
// spatial_process_samples v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3037,7 +3037,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "spatial_process_samples",
|
||||
"namespace" : "workflows/multiomics",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dries Schaumont",
|
||||
@@ -3807,12 +3807,12 @@ meta = [
|
||||
"engine" : "native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/workflows/multiomics/spatial_process_samples",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3837,7 +3837,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'workflows/multiomics/spatial_process_samples'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'A pipeline to pre-process multiple spatial omics samples.'
|
||||
author = 'Dries Schaumont, Dorien Roosen, Weiwei Schultz'
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: "spatial_qc"
|
||||
namespace: "workflows/qc"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
authors:
|
||||
- name: "Dries Schaumont"
|
||||
roles:
|
||||
@@ -387,13 +387,13 @@ build_info:
|
||||
output: "target/nextflow/workflows/qc/spatial_qc"
|
||||
executable: "target/nextflow/workflows/qc/spatial_qc/main.nf"
|
||||
viash_version: "0.9.4"
|
||||
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
|
||||
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
|
||||
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
dependencies:
|
||||
- "target/dependencies/vsh/vsh/openpipeline/v3.0.0/nextflow/workflows/qc/qc"
|
||||
package_config:
|
||||
name: "openpipeline_spatial"
|
||||
version: "v0.1.0"
|
||||
version: "v0.1.1"
|
||||
info:
|
||||
test_resources:
|
||||
- type: "s3"
|
||||
@@ -413,7 +413,7 @@ package_config:
|
||||
)'"
|
||||
- ".engines += { type: \"native\" }"
|
||||
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
organization: "vsh"
|
||||
links:
|
||||
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// spatial_qc v0.1.0
|
||||
// spatial_qc v0.1.1
|
||||
//
|
||||
// This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
|
||||
// work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
|
||||
@@ -3037,7 +3037,7 @@ meta = [
|
||||
"config": processConfig(readJsonBlob('''{
|
||||
"name" : "spatial_qc",
|
||||
"namespace" : "workflows/qc",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Dries Schaumont",
|
||||
@@ -3505,12 +3505,12 @@ meta = [
|
||||
"engine" : "native",
|
||||
"output" : "/workdir/root/repo/target/nextflow/workflows/qc/spatial_qc",
|
||||
"viash_version" : "0.9.4",
|
||||
"git_commit" : "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36",
|
||||
"git_commit" : "2baba3fff0930478c26da7e1bd99b29ee5dd83b3",
|
||||
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
|
||||
},
|
||||
"package_config" : {
|
||||
"name" : "openpipeline_spatial",
|
||||
"version" : "v0.1.0",
|
||||
"version" : "v0.1.1",
|
||||
"info" : {
|
||||
"test_resources" : [
|
||||
{
|
||||
@@ -3535,7 +3535,7 @@ meta = [
|
||||
".resources += {path: '/src/workflows/utils/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
|
||||
".engines += { type: \\"native\\" }",
|
||||
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.0'"
|
||||
".engines[.type == 'docker'].target_tag := 'v0.1.1'"
|
||||
],
|
||||
"organization" : "vsh",
|
||||
"links" : {
|
||||
|
||||
@@ -2,7 +2,7 @@ manifest {
|
||||
name = 'workflows/qc/spatial_qc'
|
||||
mainScript = 'main.nf'
|
||||
nextflowVersion = '!>=20.12.1-edge'
|
||||
version = 'v0.1.0'
|
||||
version = 'v0.1.1'
|
||||
description = 'A pipeline to add basic qc statistics to a MuData containing spatial data.'
|
||||
author = 'Dries Schaumont, Dorien Roosen, Weiwei Schultz'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user