Build branch openpipeline_spatial/niche-compass with version niche-compass to openpipeline_spatial on branch niche-compass (87e6260)

Build pipeline: openpipelines-bio.openpipeline-spatial.niche-compass-8zcq9

Source commit: 87e62605aa

Source message: add cmake to test container
This commit is contained in:
CI
2026-03-25 11:11:31 +00:00
parent f057217658
commit adbd282fec
393 changed files with 26718 additions and 1455 deletions

View File

@@ -1,10 +1,24 @@
# openpipeline_spatial x.x.x
# openpipeline_spatial 0.4.0
## NEW FUNCTIONALITY
* `feature_annotation/spatial_autocorr`: Added a spatial autocorrelation component (PR #45).
* `feature_annotation/xenium_spatial_statistics`: Added a component to calculate spatial statistics on Xenium-ingested data (PR #46).
* `neighbors/join_graphs`: Combine spatial and expression neighborhood graphs into a single graph (PR #47).
# openpipeline_spatial 0.3.0
## NEW FUNCTIONALITY
* `convert/from_h5mu_to_spatialdata`: Added a converter component to convert from H5MU to SpatialData (PR #40)
## MINOR CHANGES
* Bump squidpy to 1.8.1 and spatialdata to 0.7.2 (PR #41).
* Update openpipeline dependencies to v4.0.2 (PR #42).
* Update openpipeline dependencies to v4.0.3 (PR #42, PR #44).
# openpipeline_spatial 0.2.0

View File

@@ -10,7 +10,7 @@ repositories:
- name: openpipeline
repo: openpipeline
type: vsh
tag: v4.0.2
tag: v4.0.3
info:
test_resources:
- type: s3

5
resources_test_scripts/visium_tiny.sh Normal file → Executable file
View File

@@ -7,6 +7,7 @@ REPO_ROOT=$(git rev-parse --show-toplevel)
# Define absolute directory path
DIR="$REPO_ROOT/resources_test/visium"
ID="Visium_FFPE_Human_Ovarian_Cancer_tiny"
# from https://www.10xgenomics.com/resources/datasets/human-ovarian-cancer-1-standard
mkdir -p "$DIR"
@@ -46,6 +47,10 @@ echo "> Running spaceranger complete"
rm -rf "$DIR/Visium_FFPE_Human_Ovarian_Cancer_fastqs"
rm -f "$DIR/Visium_FFPE_Human_Ovarian_Cancer_image.jpg"
viash run "$REPO_ROOT/src/convert/from_spaceranger_to_h5mu/config.vsh.yaml" -- \
--input "$DIR/Visium_FFPE_Human_Ovarian_Cancer_tiny_spaceranger" \
--output "$DIR/$ID.h5mu"
aws s3 sync \
--profile di \
--exclude "*.yaml" \

View File

@@ -19,14 +19,16 @@ function clean_up {
trap clean_up EXIT
if [ ! -d "$OUT" ]; then
tiny_dataset="https://raw.githubusercontent.com/nf-core/test-datasets/spatialxe/Xenium_Prime_Mouse_Ileum_tiny_outs.zip"
wget "$tiny_dataset" -O "$TMPDIR/xenium_tiny.zip"
tiny_dataset="https://raw.githubusercontent.com/nf-core/test-datasets/spatialxe/Xenium_Prime_Mouse_Ileum_tiny_outs.tar.gz"
wget "$tiny_dataset" -O "$TMPDIR/xenium_tiny.tar.gz"
unzip -q "$TMPDIR/xenium_tiny.zip" -d "$TMPDIR/xenium_tiny"
mkdir -p "$TMPDIR/xenium_tiny"
tar -xzf "$TMPDIR/xenium_tiny.tar.gz" -C "$TMPDIR/xenium_tiny"
mkdir -p "$OUT"
mv "$TMPDIR/xenium_tiny/Xenium_Prime_Mouse_Ileum_tiny_outs/"* "$OUT/"
fi
rm -rf "$DIR/$ID.zarr"
viash run "$REPO_ROOT/src/convert/from_xenium_to_spatialdata/config.vsh.yaml" -- \
--input "$OUT" \
--output "$DIR/$ID.zarr"
@@ -35,11 +37,73 @@ viash run "$REPO_ROOT/src/convert/from_spatialdata_to_h5mu/config.vsh.yaml" -- \
--input "$DIR/$ID.zarr" \
--output "$DIR/$ID.h5mu"
viash run src/neighbors/spatial_neighborhood_graph/config.vsh.yaml -- \
--input "$DIR/$ID.h5mu" \
--output "$DIR/$ID.h5mu"
cat > /tmp/qc.yaml <<EOF
param_list:
- id: xenium_tiny
input: "$DIR/$ID.h5mu"
var_name_mitochondrial_genes: mitochondrial
var_name_ribosomal_genes: ribosomal
output: '\$id.qc.h5mu'
output_compression: gzip
publish_dir: "$DIR"
EOF
nextflow run openpipelines-bio/openpipeline \
-latest \
-r 2.1.0 \
-main-script target/nextflow/workflows/qc/qc/main.nf \
-profile docker \
-params-file /tmp/qc.yaml \
-resume \
-config src/workflows/utils/labels_ci.config
viash run "$REPO_ROOT/src/neighbors/spatial_neighborhood_graph/config.vsh.yaml" -- \
--input "$DIR/$ID.qc.h5mu" \
--output "$DIR/${ID}.qc.neighbors.h5mu"
cat > /tmp/pca.yaml <<EOF
param_list:
- id: xenium_tiny
input: "$DIR/${ID}.qc.neighbors.h5mu"
output: '\$id.qc.neighbors.pca.h5mu'
output_compression: gzip
publish_dir: "$TMPDIR"
EOF
nextflow run openpipelines-bio/openpipeline \
-latest \
-r v4.0.3 \
-main-script target/nextflow/dimred/pca/main.nf \
-profile docker \
-params-file /tmp/pca.yaml \
-config src/workflows/utils/labels_ci.config \
-resume
cat > /tmp/find_neighbors.yaml <<EOF
param_list:
- id: xenium_tiny
input: "$TMPDIR/xenium_tiny.qc.neighbors.pca.h5mu"
output: '\$id.qc.all_neighbors.pca.h5mu'
output_compression: gzip
publish_dir: "$TMPDIR"
EOF
nextflow run openpipelines-bio/openpipeline \
-latest \
-r v4.0.3 \
-main-script target/nextflow/neighbors/find_neighbors/main.nf \
-profile docker \
-params-file /tmp/find_neighbors.yaml \
-config src/workflows/utils/labels_ci.config \
-resume
# Move the final output to the destination directory
mv "$TMPDIR/xenium_tiny.qc.all_neighbors.pca.h5mu" "$DIR/xenium_tiny.qc.all_neighbors.pca.h5mu"
# Sync to S3
aws s3 sync \
--profile di \

View File

@@ -0,0 +1,12 @@
name: Luke Zappia
info:
role: Contributor
links:
email: luke@data-intuitive.com
github: lazappi
orcid: 0000-0001-7744-8565
linkedin: lazappi
organizations:
- name: Data Intuitive
href: https://www.data-intuitive.com
role: Data Science Engineer

View File

@@ -1,3 +1,6 @@
packages:
- spatialdata~=0.7.2
- ome-zarr~=0.12.2
- pyarrow~=18.0.0
script: |
exec("try:\n import zarr; from importlib.metadata import version\nexcept ModuleNotFoundError:\n exit(0)\nelse: assert int(version(\"zarr\").partition(\".\")[0]) > 2")

View File

@@ -0,0 +1,64 @@
name: "from_h5mu_to_spatialdata"
namespace: "convert"
scope: "public"
description: |
Reads in an H5MU file and saves it as a SpatialData Zarr store. The selected
modality in the MuData is stored as the main table in the SpatialData object.
If a matching existing SpatialData is provided, it will be used to fill the
remaining SpatialData slots.
authors:
- __merge__: /src/authors/dorien_roosen.yaml
roles: [ maintainer ]
- __merge__: /src/authors/luke_zappia.yaml
roles: [ author ]
arguments:
- name: "--input"
alternatives: ["-i"]
type: file
description: Input H5MU file.
example: input.h5mu
direction: input
required: true
- name: "--input_spatialdata"
type: file
description: An optional existing SpatialData Zarr store to fill remaining slots from.
example: existing.zarr
direction: input
required: false
- name: "--modality"
type: string
default: rna
description: The modality in the MuData to be used as the main table in the SpatialData object.
- name: "--output"
alternatives: ["-o"]
type: file
description: The path to the output SpatialData Zarr store.
example: "output.zarr"
direction: output
required: true
resources:
- type: python_script
path: script.py
- path: /src/utils/setup_logger.py
test_resources:
- type: python_script
path: test.py
- path: /resources_test/xenium/xenium_tiny.h5mu
- path: /resources_test/xenium/xenium_tiny.zarr
engines:
- type: docker
image: python:3.12-slim
setup:
- type: apt
packages:
- procps
- type: python
__merge__: [/src/base/requirements/anndata_mudata.yaml, /src/base/requirements/spatialdata.yaml]
__merge__: [ /src/base/requirements/python_test_setup.yaml, .]
runners:
- type: executable
- type: nextflow
directives:
label: [lowmem, singlecpu]

View File

@@ -0,0 +1,60 @@
import logging
import sys
import mudata as mu
import spatialdata as sd
## VIASH START
par = {
"input": "./resources_test/xenium/xenium_tiny.h5mu",
"input_spatialdata": "./resources_test/xenium/xenium_tiny.zarr",
"output": "./resources_test/xenium/xenium_tiny_from_h5mu.zarr",
"modality": "rna",
}
meta = {"resources_dir": "src/utils"}
## VIASH END
sys.path.append(meta["resources_dir"])
from setup_logger import setup_logger
logger = setup_logger()
logger.info("Starting conversion from H5MU to SpatialData...")
logger.info(f"Reading input H5MU file from {par['input']}...")
mdata = mu.read_h5mu(par["input"])
logger.info("Extracting modality from MuData object...")
mod = mdata.mod[par["modality"]]
if par.get("input_spatialdata", None) is not None:
logger.info(f"Reading existing SpatialData from {par['input_spatialdata']}...")
# Disable logger messages from spatialdata when reading
logger.setLevel(logging.WARNING)
sdata_existing = sd.read_zarr(par["input_spatialdata"])
logger.setLevel(logging.INFO)
logger.info("Checking modality matches existing SpatialData table...")
if not mod.n_obs == sdata_existing["table"].n_obs:
raise ValueError(
"The number of observations in the selected modality does not match the existing SpatialData table."
)
if not mod.obs_names.equals(sdata_existing["table"].obs_names):
raise ValueError(
"The observation names in the selected modality do not match the existing SpatialData table."
)
logger.info("Creating SpatialData object...")
if par.get("input_spatialdata", None) is not None:
logger.info("Using existing SpatialData...")
sdata = sdata_existing
sdata["table"] = mod
else:
logger.info("Creating new SpatialData...")
sdata = sd.SpatialData(tables={"table": mod})
logger.info(f"Writing output SpatialData Zarr store to {par['output']}...")
sdata.write(par["output"], overwrite=True)
logger.info("Done!")

View File

@@ -0,0 +1,143 @@
import os
import sys
import mudata as mu
import pytest
import spatialdata as sd
def test_simple_execution(run_component, tmp_path):
input = meta["resources_dir"] + "/xenium_tiny.h5mu"
input_spatialdata = meta["resources_dir"] + "/xenium_tiny.zarr"
output = tmp_path / "output.zarr"
run_component(
[
"--input",
input,
"--input_spatialdata",
input_spatialdata,
"--output",
output,
]
)
assert os.path.exists(output), "output zarr was not created"
mdata = mu.read_h5mu(input)
mod = mdata.mod["rna"]
sdata = sd.read_zarr(output)
table = sdata["table"]
# Check that the main table in the SpatialData object matches the selected modality in the MuData object
assert table.n_obs == mod.n_obs, (
"The number of observations in the SpatialData table does not match the selected modality in the MuData object."
)
assert table.obs_names.equals(mod.obs_names), (
"The observation names in the SpatialData table do not match the selected modality in the MuData object."
)
assert table.n_vars == mod.n_vars, (
"The number of variables in the SpatialData table does not match the selected modality in the MuData object."
)
assert table.var_names.equals(mod.var_names), (
"The variable names in the SpatialData table do not match the selected modality in the MuData object."
)
assert table.obs.keys().equals(mod.obs.keys()), (
"The observation metadata columns in the SpatialData table do not match those in the selected modality of the MuData object."
)
assert table.var.keys().equals(mod.var.keys()), (
"The variable metadata columns in the SpatialData table do not match those in the selected modality of the MuData object."
)
assert set(table.uns.keys()) == set(mod.uns.keys()), (
"The unstructured metadata keys in the SpatialData table do not match those in the selected modality of the MuData object."
)
assert set(table.obsm.keys()) == set(mod.obsm.keys()), (
"The obsm keys in the SpatialData table do not match those in the selected modality of the MuData object."
)
assert set(table.varm.keys()) == set(mod.varm.keys()), (
"The varm keys in the SpatialData table do not match those in the selected modality of the MuData object."
)
sdata_existing = sd.read_zarr(input_spatialdata)
# Check that remaining slots in the SpatialData object are filled from the existing SpatialData when provided
assert sdata.images.keys() == sdata_existing.images.keys(), (
"The image keys in the output SpatialData do not match those in the existing SpatialData."
)
assert sdata.labels.keys() == sdata_existing.labels.keys(), (
"The label keys in the output SpatialData do not match those in the existing SpatialData."
)
assert sdata.shapes.keys() == sdata_existing.shapes.keys(), (
"The shape keys in the output SpatialData do not match those in the existing SpatialData."
)
assert sdata.points.keys() == sdata_existing.points.keys(), (
"The point keys in the output SpatialData do not match those in the existing SpatialData."
)
def test_execution_without_input_spatialdata(run_component, tmp_path):
input = meta["resources_dir"] + "/xenium_tiny.h5mu"
output = tmp_path / "output_no_spatialdata.zarr"
run_component(
[
"--input",
input,
"--output",
output,
]
)
assert os.path.exists(output), "output zarr was not created"
mdata = mu.read_h5mu(input)
mod = mdata.mod["rna"]
sdata = sd.read_zarr(output)
table = sdata["table"]
# Check that the main table in the SpatialData object matches the selected modality in the MuData object
assert table.n_obs == mod.n_obs, (
"The number of observations in the SpatialData table does not match the selected modality in the MuData object."
)
assert table.obs_names.equals(mod.obs_names), (
"The observation names in the SpatialData table do not match the selected modality in the MuData object."
)
assert table.n_vars == mod.n_vars, (
"The number of variables in the SpatialData table does not match the selected modality in the MuData object."
)
assert table.var_names.equals(mod.var_names), (
"The variable names in the SpatialData table do not match the selected modality in the MuData object."
)
assert table.obs.keys().equals(mod.obs.keys()), (
"The observation metadata columns in the SpatialData table do not match those in the selected modality of the MuData object."
)
assert table.var.keys().equals(mod.var.keys()), (
"The variable metadata columns in the SpatialData table do not match those in the selected modality of the MuData object."
)
assert set(table.uns.keys()) == set(mod.uns.keys()), (
"The unstructured metadata keys in the SpatialData table do not match those in the selected modality of the MuData object."
)
assert set(table.obsm.keys()) == set(mod.obsm.keys()), (
"The obsm keys in the SpatialData table do not match those in the selected modality of the MuData object."
)
assert set(table.varm.keys()) == set(mod.varm.keys()), (
"The varm keys in the SpatialData table do not match those in the selected modality of the MuData object."
)
# When no existing SpatialData is provided, remaining slots should be empty
assert len(sdata.images) == 0, (
"Expected no images when input_spatialdata is not provided."
)
assert len(sdata.labels) == 0, (
"Expected no labels when input_spatialdata is not provided."
)
assert len(sdata.shapes) == 0, (
"Expected no shapes when input_spatialdata is not provided."
)
assert len(sdata.points) == 0, (
"Expected no points when input_spatialdata is not provided."
)
if __name__ == "__main__":
sys.exit(pytest.main([__file__]))

View File

@@ -64,6 +64,7 @@ engines:
- python3-pip
- python3-dev
- python-is-python3
- cmake
- type: r
cran: [ reticulate, testthat ]
- type: python

View File

@@ -68,8 +68,6 @@ engines:
env: ["LIBARROW_MINIMAL=false"]
- type: r
script: 'install.packages("arrow", type = "source")'
- type: r
script: 'Sys.setenv(LIBARROW_MINIMAL = "false"); install.packages("arrow", type = "source")'
- type: r
bioc: [ SpatialExperimentIO ]
test_setup:

View File

@@ -1,73 +0,0 @@
name: split_h5mu
namespace: "dataflow"
scope: "public"
description: |
Split the samples of a single modality from a .h5mu (multimodal) sample into seperate .h5mu files based on the values of an .obs column of this modality.
authors:
- __merge__: /src/authors/dorien_roosen.yaml
roles: [ author, maintainer ]
argument_groups:
- name: Input & specifications
arguments:
- name: "--input"
type: file
description: Path to a single .h5mu file.
required: true
- name: "--modality"
description: |
Which modality from the input MuData file to process.
type: string
default: "rna"
required: false
- name: "--obs_feature"
type: string
required: true
description: The .obs column to split the mudata on.
example: "celltype"
- name: "--drop_obs_nan"
type: boolean_true
description: Whether to drop all .obs columns that contain only nan values after splitting.
- name: "--ensure_unique_filenames"
type: boolean_true
description: Append number suffixes to ensure unique filenames after sanitizing obs feature values.
- name: Outputs
arguments:
- name: "--output"
type: file
required: true
direction: output
example: "/path/to/output"
description: Output directory containing multiple h5mu files.
- name: "--output_files"
type: file
required: true
direction: output
example: sample_files.csv
description: A csv containing the base filename and obs feature by which it was split.
__merge__: [., /src/base/h5_compression_argument.yaml]
resources:
- type: python_script
path: script.py
- path: /src/utils/setup_logger.py
test_resources:
- type: python_script
path: test.py
engines:
- type: docker
image: python:3.12-slim
setup:
- type: apt
packages:
- procps
- type: python
__merge__: /src/base/requirements/anndata_mudata.yaml
__merge__: [ /src/base/requirements/python_test_setup.yaml, .]
runners:
- type: executable
- type: nextflow
directives:
label: [ lowcpu, highmem, highdisk]

View File

@@ -1,119 +0,0 @@
import sys
import mudata as mu
import pandas as pd
import re
import gc
from pathlib import Path
from collections import defaultdict
### VIASH START
par = {
"input": "cart_atomx_process_samples.h5mu",
"modality": "rna",
"obs_feature": "sample_id",
"output": "reference_download/sample_split",
"drop_obs_nan": "true",
"output_compression": None,
"output_files": "reference_download/sample_files.csv",
"ensure_unique_filenames": True,
}
meta = {
"resources_dir": "src/utils",
}
# import anndata as ad
# df = pd.DataFrame(
# [[1, 2, 3], [4, 5, 6]], index=["obs1", "obs2"], columns=["var1", "var2", "var3"]
# )
# var3 = pd.DataFrame(["d", "e", "g"], index=df.columns, columns=["Feat"])
# obs3 = pd.DataFrame(["C C", "C_C"], index=df.index, columns=["Obs"])
# ad3 = ad.AnnData(df, obs=obs3, var=var3)
# mdata = mu.MuData({"rna": ad3})
# mdata.write_h5mu("test_san.h5mu")
# par["input"] = "test_san.h5mu"
# par["obs_feature"] = "Obs"
### VIASH END
sys.path.append(meta["resources_dir"])
from setup_logger import setup_logger
logger = setup_logger()
def main():
logger.info(f"Reading {par['input']}")
input_file = Path(par["input"].strip())
mdata = mu.read_h5mu(input_file)
adata = mdata.mod[par["modality"]]
logger.info(f"Reading unique features from {par['obs_feature']}")
obs_features = adata.obs[par["obs_feature"]].unique().tolist()
# sanitize --obs_feature values
obs_features_s = [re.sub(r"[-\s]", "_", str(s).strip()) for s in obs_features]
obs_features_s = [re.sub(r"[^A-Za-z0-9_]", "", s) for s in obs_features_s]
# ensure that names are unique, if not raise or append number as suffix
if not len(obs_features_s) == len(set(obs_features_s)):
if not par["ensure_unique_filenames"]:
raise ValueError(
f"File names are not unique after sanitizing the --obs_feature {par['obs_feature']} values"
)
logger.info("Ensuring unique names for par['obs_feature']")
counts = defaultdict(lambda: -1)
for i, feature in enumerate(obs_features_s):
counts[feature] += 1
if (curr_counts := counts[feature]) > 0:
obs_features_s[i] += f"_{curr_counts}"
# generate output dir
output_dir = Path(par["output"])
if not output_dir.is_dir():
output_dir.mkdir(parents=True)
# split modality of mdata file base on obs_feature
logger.info(f"Splitting file based on {par['obs_feature']} values {obs_features}")
obs_files = []
for obs_name, file_name in zip(obs_features, obs_features_s):
logger.info(
f"Filtering modality '{par['modality']}' observations by .obs['{par['obs_feature']}'] == {obs_name}"
)
mdata_obs = mdata.copy()
adata_full = mdata_obs.mod[par["modality"]]
# split the samples
mask = adata_full.obs[par["obs_feature"]] == obs_name
adata_obs = adata_full[mask].copy()
# Dropping columns that only have nan values after splitting
if par["drop_obs_nan"]:
logger.info("Dropping all .obs columns with NaN values")
adata_obs.obs = adata_obs.obs.dropna(axis=1, how="all")
mdata_obs.mod[par["modality"]] = adata_obs
mdata_obs_name = f"{input_file.stem}_{file_name}.h5mu"
out_path = output_dir / mdata_obs_name
# replace mdata file with modality adata contianing split samples
logger.info(
f"Writing h5mu filtered for {par['obs_feature']} {obs_name} to file {out_path}"
)
mdata_obs.write_h5mu(out_path, compression=par["output_compression"])
# avoid keeping files in memory
obs_files.append(mdata_obs_name)
del mdata_obs, adata_obs
gc.collect()
logger.info(f"Writing output_files CSV file to {par['output_files']}")
df = pd.DataFrame({"name": obs_features_s, "filename": obs_files})
df.to_csv(par["output_files"], index=False)
if __name__ == "__main__":
main()

View File

@@ -1,288 +0,0 @@
import sys
from textwrap import dedent
import pytest
import mudata as mu
import anndata as ad
import numpy as np
import pandas as pd
import subprocess
import re
@pytest.fixture
def input_modality_1():
df = pd.DataFrame(
[[1, 2, 3], [4, 5, 6]], index=["obs1", "obs2"], columns=["var1", "var2", "var3"]
)
obs = pd.DataFrame({"Obs": ["A", "B"], "Obs_nan": [np.nan, np.nan]}, index=df.index)
var = pd.DataFrame([["a"], ["b"], ["c"]], index=df.columns, columns=["Feat"])
ad1 = ad.AnnData(df, obs=obs, var=var)
return ad1
@pytest.fixture
def input_modality_2():
df = pd.DataFrame(
[[1, 2, 3], [4, 5, 6]], index=["obs1", "obs2"], columns=["var1", "var2", "var3"]
)
var2 = pd.DataFrame(["d", "e", "g"], index=df.columns, columns=["Feat"])
obs2 = pd.DataFrame(["C", "D"], index=df.index, columns=["Obs"])
ad2 = ad.AnnData(df, obs=obs2, var=var2)
return ad2
@pytest.fixture
def input_modality_3():
df = pd.DataFrame(
[[1, 2, 3], [4, 5, 6]], index=["obs1", "obs2"], columns=["var1", "var2", "var3"]
)
var3 = pd.DataFrame(["d", "e", "g"], index=df.columns, columns=["Feat"])
obs3 = pd.DataFrame(["C C", "C_C"], index=df.index, columns=["Obs"])
ad3 = ad.AnnData(df, obs=obs3, var=var3)
return ad3
@pytest.fixture
def input_h5mu(input_modality_1, input_modality_2):
tmp_mudata = mu.MuData({"mod1": input_modality_1, "mod2": input_modality_2})
return tmp_mudata
@pytest.fixture
def input_h5mu_path(write_mudata_to_file, input_h5mu):
return write_mudata_to_file(input_h5mu)
@pytest.fixture
def input_h5mu_non_unique_filenames(input_modality_3):
tmp_mudata = mu.MuData({"mod3": input_modality_3})
return tmp_mudata
@pytest.fixture
def input_h5mu_path_non_unique_filenames(
write_mudata_to_file, input_h5mu_non_unique_filenames
):
return write_mudata_to_file(input_h5mu_non_unique_filenames)
def test_sample_split(run_component, random_path, input_h5mu, input_h5mu_path):
output_dir = random_path()
output_files = random_path(extension="csv")
args = [
"--input",
input_h5mu_path,
"--output",
str(output_dir),
"--modality",
"mod1",
"--obs_feature",
"Obs",
"--output_files",
str(output_files),
]
run_component(args)
assert output_files.is_file()
assert output_dir.is_dir()
# check output dir and file names
dir_content = [
h5mu_file
for h5mu_file in output_dir.iterdir()
if h5mu_file.suffix == ".h5mu" and h5mu_file != input_h5mu_path
]
s1_file = output_dir / f"{input_h5mu_path.stem}_A.h5mu"
s2_file = output_dir / f"{input_h5mu_path.stem}_B.h5mu"
assert set(dir_content) == set([s1_file, s2_file])
# check that number of modalities, variables and observations
s1 = mu.read_h5mu(s1_file)
s2 = mu.read_h5mu(s2_file)
assert s1.n_mod == 2
assert s2.n_mod == 2
assert s1.n_obs == input_h5mu.n_obs, (
"number of observations of split file does not match input file"
)
assert s2.n_obs == input_h5mu.n_obs, (
"number of observations of split file does not match input file"
)
assert s1.mod["mod1"].n_obs == 1, (
"number of observations of split file s1 modality mod1 should equal 1"
)
assert s1.mod["mod2"].n_obs == input_h5mu.n_obs, (
"number of observations of split file s1 modality mod2 should equal input file"
)
assert len(s1.mod["mod1"].obs.keys()) == 2, (
"number of observation keys split file s1 modality mod1 should equal 2"
)
assert len(s1.mod["mod2"].obs.keys()) == 1, (
"number of observation keys split file s1 modality mod2 should equal 1"
)
assert s2.mod["mod1"].n_obs == 1, (
"number of observations of split file s2 modality mod1 should equal 1"
)
assert s2.mod["mod2"].n_obs == input_h5mu.n_obs, (
"number of observations of split file s2 modality mod2 should equal input file"
)
assert s1.n_vars == input_h5mu.n_vars, (
"number of variables of split file s1 should equal input file"
)
assert s2.n_vars == input_h5mu.n_vars, (
"number of variables of split file s1 should equal input file"
)
assert s1.mod["mod1"].n_vars == input_h5mu.mod["mod1"].n_vars, (
"number of variables of split file s1 modalitty mod1 should equal input file"
)
assert s1.mod["mod2"].n_vars == input_h5mu.mod["mod1"].n_vars, (
"number of variables of split file s1 modalitty mod2 should equal input file"
)
assert s2.mod["mod1"].n_vars == input_h5mu.mod["mod1"].n_vars, (
"number of variables of split file s2 modalitty mod1 should equal input file"
)
assert s2.mod["mod2"].n_vars == input_h5mu.mod["mod1"].n_vars, (
"number of variables of split file s2 modalitty mod2 should equal input file"
)
# check correct sample splitting
assert np.all(s1.mod["mod1"].obs["Obs"] == "A"), (
"observation of .obs Obs in s1 should equal A"
)
assert np.all(s2.mod["mod1"].obs["Obs"] == "B"), (
"observation of .obs Obs in s2 should equal B"
)
# Check contents of csv file
expected_csv_output = dedent(
f"""\
name,filename
A,{s1_file.name}
B,{s2_file.name}
"""
)
with open(output_files, "r") as open_csv_file:
result = open_csv_file.read()
assert result == expected_csv_output
def test_sample_split_dropna(run_component, random_path, input_h5mu, input_h5mu_path):
output_dir = random_path()
output_files = random_path(extension="csv")
args = [
"--input",
input_h5mu_path,
"--output",
str(output_dir),
"--modality",
"mod1",
"--obs_feature",
"Obs",
"--drop_obs_nan",
"true",
"--output_files",
str(output_files),
]
run_component(args)
# check output dir and file names
s1_file = output_dir / f"{input_h5mu_path.stem}_A.h5mu"
s2_file = output_dir / f"{input_h5mu_path.stem}_B.h5mu"
# check that .obs columns with only nan values are dropped correctly
s1 = mu.read_h5mu(s1_file)
s2 = mu.read_h5mu(s2_file)
assert s1.n_obs == input_h5mu.n_obs, (
"number of observations of split file does not match input file"
)
assert s2.n_obs == input_h5mu.n_obs, (
"number of observations of split file does not match input file"
)
assert s1.mod["mod1"].n_obs == 1, (
"number of observations of split file s1 modality mod1 should equal 1"
)
assert s1.mod["mod2"].n_obs == input_h5mu.n_obs, (
"number of observations of split file s1 modality mod2 should equal input file"
)
assert len(s1.mod["mod1"].obs.keys()) == 1, (
"number of observation keys split file s1 modality mod1 should equal 1"
)
assert len(s1.mod["mod2"].obs.keys()) == 1, (
"number of observation keys split file s1 modality mod2 should equal 1"
)
def test_sanitizing(run_component, random_path, input_h5mu_path_non_unique_filenames):
output_dir = random_path()
output_files = random_path(extension="csv")
args = [
"--input",
input_h5mu_path_non_unique_filenames,
"--output",
str(output_dir),
"--modality",
"mod3",
"--obs_feature",
"Obs",
"--drop_obs_nan",
"true",
"--output_files",
str(output_files),
]
with pytest.raises(subprocess.CalledProcessError) as err:
run_component(args)
assert re.search(
r"ValueError: File names are not unique after sanitizing the --obs_feature Obs values",
err.value.stdout.decode("utf-8"),
)
args_san = [
"--input",
input_h5mu_path_non_unique_filenames,
"--output",
str(output_dir),
"--modality",
"mod3",
"--obs_feature",
"Obs",
"--drop_obs_nan",
"true",
"--output_files",
str(output_files),
"--ensure_unique_filenames",
"true",
]
run_component(args_san)
# check output dir and file names
dir_content = [
h5mu_file
for h5mu_file in output_dir.iterdir()
if h5mu_file.suffix == ".h5mu"
and h5mu_file != input_h5mu_path_non_unique_filenames
]
s1_file = output_dir / f"{input_h5mu_path_non_unique_filenames.stem}_C_C.h5mu"
s2_file = output_dir / f"{input_h5mu_path_non_unique_filenames.stem}_C_C_1.h5mu"
assert s1_file.is_file(), f"{s1_file} does not exist"
assert s2_file.is_file(), f"{s2_file} does not exist"
assert set(dir_content) == set([s1_file, s2_file]), (
"Output files do not match file names in csv"
)
if __name__ == "__main__":
sys.exit(pytest.main([__file__]))

View File

@@ -0,0 +1,111 @@
name: spatial_autocorr
namespace: feature_annotation
label: Spatial Autocorrelation
summary: Calculate spatial autocorrelation for genes using Moran's I or Geary's C.
description: |
Calculate spatial autocorrelation for genes using Moran's I or Geary's C.
This allows identifying spatially variable genes.
argument_groups:
- name: Inputs
arguments:
- name: --input
type: file
required: true
description: Input h5mu file.
- name: --modality
type: string
default: rna
description: Modality to use.
- name: --layer
type: string
description: |
Layer in the AnnData object to use.
- If `attr` is 'X', this is the key in `.layers` to use. If not provided, `.X` is used.
- If `attr` is 'obsm', this is the key in `.obsm` to use.
- name: --input_genes
type: string
multiple: true
multiple_sep: ","
description: |
The features to calculate autocorrelation for. Meaning depends on `--attr`:
- If `attr` is 'X' (default), this must be a list of gene names from `.var_names`.
If not provided, it defaults to using genes in `.var['highly_variable']` (if present), or all genes.
This behavior can be overridden by setting `--use_all_genes` to `true`.
Note: You cannot pass a column name from `.var` here.
- If `attr` is 'obs', this must be a list of column names from `.obs`.
- If `attr` is 'obsm', this must be indices in `.obsm[layer]` (as strings).
- name: --obsp_neighborhood_graph
type: string
default: spatial_connectivities
description: Key in .obsp where spatial connectivities are stored.
- name: --use_all_genes
type: boolean
default: false
description: |
Whether to use all genes even if highly variable genes are present in .var.
If set to true, all genes will be used.
- name: Parameters
arguments:
- name: --mode
type: string
default: moran
choices: [moran, geary]
description: Mode of spatial autocorrelation.
- name: --attr
type: string
default: X
choices: [X, obs, obsm]
description: |
The attribute of the AnnData object to use for calculation.
- 'X': Use gene expression data (default).
- 'obs': Use cell metadata.
- 'obsm': Use multidimensional embeddings.
- name: --n_perms
type: integer
default: 100
description: Number of permutations for p-value calculation.
- name: --use_raw
type: boolean
default: false
description: Whether to use .raw attribute of AnnData.
- name: Outputs
arguments:
- name: --output
type: file
direction: output
required: true
description: Output h5mu file with results in .uns.
resources:
- type: python_script
path: script.py
test_resources:
- type: python_script
path: test.py
- path: /resources_test/xenium/xenium_tiny.qc.neighbors.h5mu
engines:
- type: docker
image: python:3.13-slim
setup:
- type: apt
packages:
- procps
- type: python
__merge__: [/src/base/requirements/anndata_mudata.yaml, /src/base/requirements/scanpy.yaml, /src/base/requirements/squidpy.yaml]
test_setup:
- type: python
packages:
- pytest
- viashpy
- type: native
runners:
- type: executable
- type: nextflow
directives:
label: [midcpu, midmem]

View File

@@ -0,0 +1,80 @@
import mudata as mu
import squidpy as sq
## VIASH START
par = {
"input": "resources_test/xenium/xenium_tiny_qc_graph.h5mu",
"output": "output.h5mu",
"modality": "rna",
"mode": "moran",
"input_genes": None,
"attr": "X",
"n_perms": 100,
"layer": None,
"use_raw": False,
"obsp_neighborhood_graph": "spatial_connectivities",
"use_all_genes": False,
}
## VIASH END
def main():
print("Reading input MuData...", flush=True)
mdata = mu.read_h5mu(par["input"])
adata = mdata.mod[par["modality"]]
# Check for connectivity key
if par["obsp_neighborhood_graph"] not in adata.obsp:
raise ValueError(
f"Connectivity key '{par['obsp_neighborhood_graph']}' not found in .obsp of modality '{par['modality']}'."
)
genes = par["input_genes"]
if genes and len(genes) == 0:
genes = None
if genes is None and par["use_all_genes"] and par["attr"] == "X":
genes = list(adata.var_names)
# Handle layer
layer = par["layer"]
if layer == "None":
layer = None
print(f"Calculating spatial autocorrelation ({par['mode']})...", flush=True)
# Run Squidpy spatial_autocorr
# Note: sq.gr.spatial_autocorr modifies adata in-place, adding results to .uns
sq.gr.spatial_autocorr(
adata,
connectivity_key=par["obsp_neighborhood_graph"],
genes=genes,
mode=par["mode"],
attr=par["attr"],
n_perms=par["n_perms"],
layer=layer,
use_raw=par["use_raw"],
)
result_key = f"{par['mode']}I" if par["mode"] == "moran" else f"{par['mode']}C"
if result_key in adata.uns:
# Log top spatially variable genes
df = adata.uns[result_key]
if not df.empty:
sort_col = "I" if par["mode"] == "moran" else "C"
print("Top spatially variable genes:", flush=True)
print(df.sort_values(by=sort_col, ascending=False).head(), flush=True)
else:
print(
f"Warning: Expected key '{result_key}' not found in .uns after calculation.",
flush=True,
)
print("Writing output...", flush=True)
mdata.write_h5mu(par["output"])
print("Done!", flush=True)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,220 @@
import mudata as mu
import sys
import pytest
import pandas as pd
## VIASH START
meta = {
"resources_dir": "resources_test/xenium",
"executable": "./calculate_spatial_autocorrelation",
}
## VIASH END
def test_calculate_spatial_autocorrelation_moran(run_component, tmp_path):
input_path = meta["resources_dir"] + "/xenium_tiny.qc.neighbors.h5mu"
output_path = tmp_path / "output_moran.h5mu"
print(f"Running component with Moran's I on {input_path}")
run_component(
[
"--input",
str(input_path),
"--output",
str(output_path),
"--modality",
"rna",
"--obsp_neighborhood_graph",
"spatial_connectivities",
"--mode",
"moran",
"--n_perms",
"10", # Reduce permutations for speed
]
)
assert output_path.exists(), "Output file not created"
mdata = mu.read_h5mu(output_path)
adata = mdata.mod["rna"]
assert "moranI" in adata.uns, "moranI key missing from .uns"
df = adata.uns["moranI"]
assert isinstance(df, pd.DataFrame), "moranI should be a DataFrame"
assert not df.empty, "moranI DataFrame is empty"
# Check essential columns
expected_cols = ["I", "pval_norm", "var_norm"]
for col in expected_cols:
assert col in df.columns, f"Missing column {col} in moranI dataframe"
# Check values range
assert df["I"].max() <= 1.0, "Moran's I > 1 (theoretical max)"
assert df["I"].min() >= -1.0, "Moran's I < -1 (theoretical min)"
def test_calculate_spatial_autocorrelation_geary(run_component, tmp_path):
input_path = meta["resources_dir"] + "/xenium_tiny.qc.neighbors.h5mu"
output_path = tmp_path / "output_geary.h5mu"
mdata = mu.read_h5mu(input_path)
genes = list(mdata.mod["rna"].var_names[:5]) # Test with first 5 genes
genes_str = ",".join(genes)
cmd = [
"--input",
str(input_path),
"--output",
str(output_path),
"--modality",
"rna",
"--obsp_neighborhood_graph",
"spatial_connectivities",
"--mode",
"geary",
"--n_perms",
"10",
"--input_genes",
genes_str,
]
print(
f"Running component with Geary's C on {input_path} for subset of genes: {genes_str}"
)
run_component(cmd)
assert output_path.exists()
mdata = mu.read_h5mu(output_path)
adata = mdata.mod["rna"]
assert "gearyC" in adata.uns
df = adata.uns["gearyC"]
assert len(df) == 5, f"Expected results for 5 genes, got {len(df)}"
assert all(g in df.index for g in genes), (
"Not all requested genes are in output index"
)
assert "C" in df.columns
def test_calculate_spatial_autocorrelation_obs(run_component, tmp_path):
input_path = meta["resources_dir"] + "/xenium_tiny.qc.neighbors.h5mu"
output_path = tmp_path / "output_obs.h5mu"
features = "total_counts,cell_area,nucleus_area"
print(
f"Running component with Moran's I on {input_path} for obs features: {features}"
)
run_component(
[
"--input",
str(input_path),
"--output",
str(output_path),
"--modality",
"rna",
"--obsp_neighborhood_graph",
"spatial_connectivities",
"--mode",
"moran",
"--attr",
"obs",
"--input_genes",
features,
"--n_perms",
"10",
]
)
assert output_path.exists()
mdata = mu.read_h5mu(output_path)
adata = mdata.mod["rna"]
assert "moranI" in adata.uns
df = adata.uns["moranI"]
assert len(df) == 3, f"Expected results for 3 features, got {len(df)}"
# When attr='obs', the index contains the column names
for feature in features.split(","):
assert feature in df.index, f"Feature {feature} missing from index: {df.index}"
def test_calculate_spatial_autocorrelation_use_all_genes(run_component, tmp_path):
input_path = meta["resources_dir"] + "/xenium_tiny.qc.neighbors.h5mu"
temp_input_path = tmp_path / "xenium_tiny_hvg.h5mu"
output_path_hvg = tmp_path / "output_hvg.h5mu"
output_path_all = tmp_path / "output_all.h5mu"
# Create dataset with highly variable genes
mdata = mu.read_h5mu(input_path)
adata = mdata.mod["rna"]
# Mark first 5 genes as highly variable
adata.var["highly_variable"] = False
genes = list(adata.var_names)
for g in genes[:5]:
adata.var.loc[g, "highly_variable"] = True
mdata.write_h5mu(temp_input_path)
# Test 1: Default behavior (should use only HVG)
print("Running component with default settings (expecting HVG usage)")
run_component(
[
"--input",
str(temp_input_path),
"--output",
str(output_path_hvg),
"--modality",
"rna",
"--obsp_neighborhood_graph",
"spatial_connectivities",
"--mode",
"moran",
"--n_perms",
"10",
]
)
assert output_path_hvg.exists()
mdata_hvg = mu.read_h5mu(output_path_hvg)
df_hvg = mdata_hvg.mod["rna"].uns["moranI"]
assert len(df_hvg) == 5, f"Expected 5 genes (HVG), got {len(df_hvg)}"
# Test 2: Override to use all genes
print("Running component with --use_all_genes (expecting all genes)")
run_component(
[
"--input",
str(temp_input_path),
"--output",
str(output_path_all),
"--modality",
"rna",
"--obsp_neighborhood_graph",
"spatial_connectivities",
"--mode",
"moran",
"--n_perms",
"10",
"--use_all_genes",
"true",
]
)
assert output_path_all.exists()
mdata_all = mu.read_h5mu(output_path_all)
df_all = mdata_all.mod["rna"].uns["moranI"]
assert len(df_all) == len(genes), (
f"Expected all {len(genes)} genes, got {len(df_all)}"
)
if __name__ == "__main__":
sys.exit(pytest.main([__file__]))

View File

@@ -0,0 +1,109 @@
name: xenium_spatial_statistics
namespace: feature_annotation
label: Xenium Spatial Statistics
description: |
Calculate various spatial statistics from Xenium data including cell morphology
ratios, position-based features, local density metrics, and global spatial patterns.
This component expects a MuData object with a pre-computed spatial neighborhood graph
in `.obsp`.
argument_groups:
- name: Inputs
arguments:
- name: --input
type: file
required: true
example: input.h5mu
description: |
A MuData file containing spatial transcriptomics data and a
pre-computed spatial neighborhood graph in `.obsp`.
- name: --modality
type: string
required: true
default: "rna"
description: |
The name of the modality to use from the MuData object.
This specifies which AnnData object contains the spatial data.
- name: --obsm_spatial_coordinates
type: string
default: "spatial"
description: |
The key in `.obsm` where spatial coordinates are stored.
Expected shape is (n_cells, 2) for 2D coordinates.
- name: Outputs
arguments:
- name: --output
type: file
direction: output
default: output.h5mu
description: |
The output MuData file with calculated spatial statistics.
Per-cell metrics are stored in `.obs` and global statistics in `.uns`.
- name: --output_prefix
type: string
default: "spatial_"
description: |
Prefix to add to all generated column names in `.obs`.
- name: Parameters
arguments:
- name: --density_bandwidth
type: double
default: 50.0
description: |
Bandwidth parameter for Gaussian kernel density estimation in spatial units
(typically microns). Larger values create smoother density estimates.
- name: "--calculate_ripley_l"
type: boolean
default: false
description: |
Whether to calculate Ripley's L statistic.
Warning: This is an O(N^2) operation and can be very slow for large datasets (>5000 cells).
- name: "--n_subsample_ripley"
type: integer
default: -1
description: |
Number of cells to subsample for Ripley's L calculation.
If -1, use all cells. Recommended to keep this below 5000 for performance.
resources:
- type: python_script
path: script.py
test_resources:
- type: python_script
path: test.py
- path: /resources_test/xenium/xenium_tiny.qc.neighbors.h5mu
engines:
- type: docker
image: python:3.13-slim
setup:
- type: apt
packages:
- procps
- type: python
__merge__:
- /src/base/requirements/anndata_mudata.yaml
- /src/base/requirements/scanpy.yaml
- /src/base/requirements/squidpy.yaml
packages:
- scikit-learn
test_setup:
- type: python
packages:
- pytest
- viashpy
- type: native
runners:
- type: executable
- type: nextflow
directives:
label: [singlecpu, midmem, lowdisk]

View File

@@ -0,0 +1,315 @@
import sys
import warnings
import mudata as mu
import numpy as np
import squidpy as sq
from scipy.spatial import ConvexHull, Voronoi, distance_matrix
from sklearn.neighbors import KernelDensity
## VIASH START
par = {
"input": "resources_test/xenium/xenium_tiny_qc.h5mu",
"output": "output.h5mu",
"modality": "rna",
"obsm_spatial_coordinates": "spatial",
"density_bandwidth": 50.0,
"calculate_ripley_l": False,
"n_subsample_ripley": -1,
"output_prefix": "spatial_",
}
## VIASH END
def calculate_morphology_metrics(adata, prefix):
"""Calculate cell morphology ratios and features."""
print(" Calculating morphology metrics...", flush=True)
if "cell_area" not in adata.obs or "nucleus_area" not in adata.obs:
warnings.warn(
"cell_area and/or nucleus_area not found in .obs. "
"Skipping morphology metrics."
)
return
# Nucleus to cell area ratio - can be removed once https://github.com/openpipelines-bio/openpipeline_qc/issues/18 is fixed.
adata.obs[f"{prefix}nucleus_cell_ratio"] = (
adata.obs["nucleus_area"] / adata.obs["cell_area"]
)
# Cell area percentile (relative size)
adata.obs[f"{prefix}cell_area_percentile"] = (
adata.obs["cell_area"].rank(pct=True) * 100
)
print(
f" Added: {prefix}nucleus_cell_ratio, {prefix}cell_area_percentile",
flush=True,
)
def calculate_position_features(adata, spatial_coords, prefix):
"""Calculate position-based features."""
print(" Calculating position-based features...", flush=True)
# Tissue centroid
centroid = spatial_coords.mean(axis=0)
# Distance to centroid
distances_to_centroid = np.linalg.norm(spatial_coords - centroid, axis=1)
adata.obs[f"{prefix}distance_to_centroid"] = distances_to_centroid
# Normalized coordinates (0-1 scale)
min_coords = spatial_coords.min(axis=0)
max_coords = spatial_coords.max(axis=0)
coord_range = max_coords - min_coords
normalized_coords = (spatial_coords - min_coords) / coord_range
adata.obs[f"{prefix}norm_x"] = normalized_coords[:, 0]
adata.obs[f"{prefix}norm_y"] = normalized_coords[:, 1]
# Distance to convex hull boundary
try:
hull = ConvexHull(spatial_coords)
hull_points = spatial_coords[hull.vertices]
# For each point, find distance to nearest hull vertex (approximation)
distances_to_boundary = np.min(
distance_matrix(spatial_coords, hull_points), axis=1
)
adata.obs[f"{prefix}distance_to_boundary"] = distances_to_boundary
print(
" Added: distance_to_centroid, norm_x, norm_y, distance_to_boundary",
flush=True,
)
except Exception as e:
warnings.warn(f"Could not calculate convex hull: {e}")
print(" Added: distance_to_centroid, norm_x, norm_y", flush=True)
def calculate_density_metrics(adata, spatial_coords, bandwidth, prefix):
"""Calculate local density metrics."""
print(" Calculating density metrics...", flush=True)
# Kernel density estimation
kde = KernelDensity(bandwidth=bandwidth, kernel="gaussian")
kde.fit(spatial_coords)
log_density = kde.score_samples(spatial_coords)
adata.obs[f"{prefix}kernel_density"] = np.exp(log_density)
# Calculate degree centrality (as a proxy for local density / number of neighbors)
# This assumes spatial_connectivities is already present in .obsp (from build_spatial_graph)
if "spatial_connectivities" in adata.obsp:
spatial_connectivities = adata.obsp["spatial_connectivities"]
degrees = spatial_connectivities.sum(axis=1)
# If sparse matrix, it returns matrix object, need to convert to array
if hasattr(degrees, "A1"):
degrees = degrees.A1
adata.obs[f"{prefix}graph_degree"] = degrees
print(" Added: kernel_density, graph_degree", flush=True)
else:
print(
" Warning: 'spatial_connectivities' not found in .obsp. Skipping graph_degree.",
flush=True,
)
print(" Added: kernel_density", flush=True)
def calculate_voronoi_metrics(adata, spatial_coords, prefix):
"""Calculate Voronoi tessellation statistics."""
print(" Calculating Voronoi tessellation...", flush=True)
try:
vor = Voronoi(spatial_coords)
polygon_areas = []
neighbor_counts = []
for point_idx in range(len(spatial_coords)):
region_idx = vor.point_region[point_idx]
region = vor.regions[region_idx]
# Skip infinite regions
if -1 in region or len(region) == 0:
polygon_areas.append(np.nan)
neighbor_counts.append(np.nan)
continue
# Calculate polygon area using shoelace formula
vertices = vor.vertices[region]
x = vertices[:, 0]
y = vertices[:, 1]
area = 0.5 * np.abs(np.dot(x, np.roll(y, 1)) - np.dot(y, np.roll(x, 1)))
polygon_areas.append(area)
# Count neighbors (shared vertices)
neighbor_counts.append(len(region))
adata.obs[f"{prefix}voronoi_area"] = polygon_areas
adata.obs[f"{prefix}voronoi_neighbors"] = neighbor_counts
print(" Added: voronoi_area, voronoi_neighbors", flush=True)
except Exception as e:
warnings.warn(f"Could not calculate Voronoi tessellation: {e}")
def calculate_global_statistics(adata, spatial_coords, par):
"""Calculate global spatial pattern statistics."""
print(" Calculating global spatial statistics...", flush=True)
stats = {}
# Global density
try:
hull = ConvexHull(spatial_coords)
area = hull.volume # In 2D, volume of convex hull is the area
stats["area_calculation_method"] = "convex_hull"
stats["cell_density"] = len(spatial_coords) / area
stats["total_area"] = area
stats["n_cells"] = len(spatial_coords)
except Exception as e:
print(f" Error: Could not calculate convex hull area ({e})", flush=True)
# Ripley's L (using squidpy)
if par["calculate_ripley_l"]:
print(" Computing Ripley's L function (Squidpy)...", flush=True)
n_subsample = par["n_subsample_ripley"]
try:
# Create a working AnnData for Ripley's
if n_subsample > 0 and len(adata) > n_subsample:
print(f" Subsampling to {n_subsample} random cells...", flush=True)
# Use numpy to generate random indices
indices = np.random.choice(len(adata), n_subsample, replace=False)
adata_ripley = adata[indices].copy()
stats["ripley_l_subsampled"] = True
else:
adata_ripley = adata.copy()
stats["ripley_l_subsampled"] = False
# Squidpy requires a cluster key. We create a dummy one for "global" context.
adata_ripley.obs["_temp_global"] = "all"
adata_ripley.obs["_temp_global"] = adata_ripley.obs["_temp_global"].astype(
"category"
)
# Calculate Ripley's L statistic
# This stores the result in adata.uns['all_L']
sq.gr.ripley(
adata_ripley,
cluster_key="_temp_global",
mode="L",
spatial_key=par["obsm_spatial_coordinates"],
n_simulations=50,
)
# Extract basic stats from the results
if "all_L" in adata_ripley.uns and "L_stat" in adata_ripley.uns["all_L"]:
l_stat_df = adata_ripley.uns["all_L"]["L_stat"]
stats["ripley_l_max"] = float(l_stat_df.max().max())
stats["ripley_l_mean"] = float(l_stat_df.mean().mean())
# Clean up
if "all_L" in adata_ripley.uns:
del adata_ripley.uns["all_L"]
except Exception as e:
print(f" Error calculating Ripley's L: {e}", flush=True)
import traceback
traceback.print_exc()
else:
print(" Skipping Ripley's L (disabled in config)...", flush=True)
# Spatial extent
min_coords = spatial_coords.min(axis=0)
max_coords = spatial_coords.max(axis=0)
stats["spatial_extent_x"] = float(max_coords[0] - min_coords[0])
stats["spatial_extent_y"] = float(max_coords[1] - min_coords[1])
stats["centroid_x"] = float(spatial_coords[:, 0].mean())
stats["centroid_y"] = float(spatial_coords[:, 1].mean())
if "cell_density" in stats:
print(
f" Global stats: cell_density={stats['cell_density']:.4f}",
flush=True,
)
return stats
def main(par):
print(f"\n>>> Reading MuData from '{par['input']}'...", flush=True)
mdata = mu.read_h5mu(par["input"])
print(mdata, flush=True)
print(f"\n>>> Extracting modality '{par['modality']}'...", flush=True)
if par["modality"] not in mdata.mod:
raise KeyError(
f"Modality '{par['modality']}' not found in MuData. "
f"Available modalities: {list(mdata.mod.keys())}"
)
adata = mdata[par["modality"]]
print(adata, flush=True)
print(
f"\n>>> Extracting spatial coordinates from .obsm['{par['obsm_spatial_coordinates']}']...",
flush=True,
)
if par["obsm_spatial_coordinates"] not in adata.obsm:
raise KeyError(
f"Spatial key '{par['obsm_spatial_coordinates']}' not found in .obsm. "
f"Available keys: {list(adata.obsm.keys())}"
)
spatial_coords = adata.obsm[par["obsm_spatial_coordinates"]]
if spatial_coords.shape[1] != 2:
raise ValueError(
f"Expected 2D spatial coordinates, got shape {spatial_coords.shape}"
)
print(f" Shape: {spatial_coords.shape} (n_cells × 2)", flush=True)
prefix = par["output_prefix"]
# Calculate morphology metrics
print("\n>>> Calculating morphology metrics...", flush=True)
calculate_morphology_metrics(adata, prefix)
# Calculate position features
print("\n>>> Calculating position-based features...", flush=True)
calculate_position_features(adata, spatial_coords, prefix)
# Calculate density metrics
print("\n>>> Calculating density metrics...", flush=True)
calculate_density_metrics(
adata,
spatial_coords,
par["density_bandwidth"],
prefix,
)
# Calculate Voronoi tessellation
print("\n>>> Calculating Voronoi tessellation...", flush=True)
calculate_voronoi_metrics(adata, spatial_coords, prefix)
# Calculate global statistics
print("\n>>> Calculating global spatial statistics...", flush=True)
global_stats = calculate_global_statistics(adata, spatial_coords, par)
# Store in uns
if "spatial_stats" not in adata.uns:
adata.uns["spatial_stats"] = {}
adata.uns["spatial_stats"].update(global_stats)
print(f"\n>>> Writing output to '{par['output']}'...", flush=True)
mdata.write_h5mu(par["output"])
print("\n>>> Done!\n", flush=True)
if __name__ == "__main__":
sys.exit(main(par))

View File

@@ -0,0 +1,75 @@
import mudata as mu
import sys
import pytest
## VIASH START
meta = {
"resources_dir": "resources_test/xenium",
"executable": "./xenium_spatial_statistics",
}
## VIASH END
def test_calculate_spatial_statistics(run_component, tmp_path):
input_path = meta["resources_dir"] + "/xenium_tiny.qc.neighbors.h5mu"
output_path = tmp_path / "output.h5mu"
# Run the component directly on the input file
run_component(
[
"--input",
str(input_path),
"--output",
str(output_path),
"--modality",
"rna",
"--obsm_spatial_coordinates",
"spatial",
"--density_bandwidth",
"50.0",
"--calculate_ripley_l",
"false",
]
)
assert output_path.exists(), "Output file not created"
mdata_out = mu.read_h5mu(output_path)
adata_out = mdata_out.mod["rna"]
# Check for expected columns in .obs
expected_cols = [
"spatial_nucleus_cell_ratio",
"spatial_cell_area_percentile",
"spatial_distance_to_centroid",
"spatial_norm_x",
"spatial_norm_y",
"spatial_kernel_density",
"spatial_graph_degree",
"spatial_voronoi_area",
"spatial_voronoi_neighbors",
]
for col in expected_cols:
assert col in adata_out.obs.columns, f"Column {col} missing from output .obs"
# Check for expected metrics in .uns['spatial_stats']
assert "spatial_stats" in adata_out.uns, "spatial_stats missing from .uns"
stats = adata_out.uns["spatial_stats"]
expected_stats = [
"cell_density",
"total_area",
"n_cells",
"spatial_extent_x",
"spatial_extent_y",
"centroid_x",
"centroid_y",
]
for stat in expected_stats:
assert stat in stats, f"Stat {stat} missing from spatial_stats"
if __name__ == "__main__":
sys.exit(pytest.main([__file__]))

View File

@@ -0,0 +1,91 @@
name: join_graphs
namespace: neighbors
description: |
Combine spatial and expression neighborhood graphs into a single graph for
use in downstream clustering or trajectory analysis.
The fusion is a linear combination of the expression connectivities
and spatial connectivities matrices, weighted by `alpha`.
$C_{joint} = (1 - \alpha) \cdot C_{expression} + \alpha \cdot C_{spatial}$
authors:
- __merge__: /src/authors/jakub_majercik.yaml
roles: [ maintainer ]
argument_groups:
- name: "Inputs"
arguments:
- name: "--input"
type: file
required: true
description: Input H5MU file with pre-computed expression and spatial neighborhood graphs.
- name: "--modality"
type: string
default: "rna"
required: false
description: Modality from the input MuData file to process.
- name: "--input_obsp_expression_graph"
type: string
default: "connectivities"
description: |
Key in `adata.obsp` containing the expression connectivity matrix.
- name: "--input_obsp_spatial_graph"
type: string
default: "spatial_connectivities"
description: |
Key in `adata.obsp` containing the spatial connectivity matrix.
- name: "Parameters"
arguments:
- name: "--alpha"
type: double
default: 0.5
min: 0.0
max: 1.0
description: |
Weight of the spatial graph in the connection fusion.
A value of 0 results in the original expression graph;
a value of 1 results in the spatial graph only.
- name: Outputs
arguments:
- name: "--output"
type: file
direction: output
required: true
description: Output H5MU file path.
example: output.h5mu
- name: "--output_obsp_graph"
type: string
default: "spatial_expression_connectivities"
description: |
Key under which to store the fused connectivity matrix in `adata.obsp`.
__merge__: [., /src/base/h5_compression_argument.yaml]
resources:
- type: python_script
path: script.py
- path: /src/utils/setup_logger.py
test_resources:
- type: python_script
path: test.py
- path: /resources_test/xenium/xenium_tiny.qc.all_neighbors.pca.h5mu
engines:
- type: docker
image: python:3.12-slim
setup:
- type: apt
packages:
- procps
- type: python
__merge__: [ /src/base/requirements/scanpy.yaml, /src/base/requirements/anndata_mudata.yaml, . ]
__merge__: [ /src/base/requirements/python_test_setup.yaml, .]
runners:
- type: executable
- type: nextflow
directives:
label: [midcpu, midmem, middisk]

View File

@@ -0,0 +1,63 @@
import sys
import mudata as mu
## VIASH START
par = {
# Inputs
"input": "resources_test/xenium/xenium_tiny.spatial_expression_neighbors.h5mu",
"modality": "rna",
"input_obsp_expression_graph": "connectivities",
"input_obsp_spatial_graph": "spatial_connectivities",
# Fusion options
"alpha": 0.2,
# Outputs
"output": "foo.h5mu",
"output_compression": None,
"output_obsp_graph": "spatial_expression_connectivities",
}
meta = {"resources_dir": "src/utils/"}
## VIASH END
sys.path.append(meta["resources_dir"])
from setup_logger import setup_logger
logger = setup_logger()
## Read data
logger.info("Reading input data...")
adata = mu.read_h5ad(par["input"], mod=par["modality"])
## Validate inputs
spatial_key = par["input_obsp_spatial_graph"]
if spatial_key not in adata.obsp:
raise ValueError(f"Spatial graph key '{spatial_key}' not found in .obsp.")
expr_key = par["input_obsp_expression_graph"]
if expr_key not in adata.obsp:
raise ValueError(f"Expression graph key '{expr_key}' not found in .obsp.")
nn_graph_genes = adata.obsp[expr_key]
nn_graph_space = adata.obsp[spatial_key]
## Combine graphs
alpha = par["alpha"]
logger.info(
f"Combining graphs (alpha={alpha}: spatial weight, "
f"{1 - alpha:.2f}: expression weight)..."
)
joint_graph = (1 - alpha) * nn_graph_genes + alpha * nn_graph_space
out_key = par["output_obsp_graph"]
logger.info(f"Storing result in .obsp['{out_key}']...")
adata.obsp[out_key] = joint_graph
adata.uns[out_key] = {
"params": {"alpha": alpha},
"inputs": {
"expression_graph": expr_key,
"spatial_graph": spatial_key,
},
}
## Write output
logger.info("Saving output data...")
mdata = mu.MuData({par["modality"]: adata})
mdata.write_h5mu(par["output"], compression=par["output_compression"])

View File

@@ -0,0 +1,103 @@
import pytest
import mudata as mu
import sys
## VIASH START
meta = {
"executable": "./target/executable/neighbors/join_graphs/join_graphs",
"resources_dir": "resources_test/xenium/",
}
## VIASH END
input_file = f"{meta['resources_dir']}/xenium_tiny.qc.all_neighbors.pca.h5mu"
def test_default_execution(run_component, tmp_path):
output = tmp_path / "fused_neighbors.h5mu"
run_component(
[
"--input",
input_file,
"--output",
str(output),
"--output_obsp_graph",
"fused_conn",
"--alpha",
"0.2",
"--output_compression",
"gzip",
]
)
assert output.is_file(), "Output file was not created."
mdata = mu.read_h5mu(output)
assert "rna" in mdata.mod, "Expected 'rna' modality in output."
adata = mdata.mod["rna"]
assert "fused_conn" in adata.obsp.keys(), (
"Expected output obsp connectivities key to be present."
)
assert "fused_conn" in adata.uns.keys(), "Expected metadata for fusion in .uns."
assert adata.uns["fused_conn"]["params"]["alpha"] == 0.2, (
"Expected alpha parameter to be stored in .uns."
)
# Check graph properties (should be combination of input graphs)
fused = adata.obsp["fused_conn"]
spatial = adata.obsp["spatial_connectivities"]
expr = adata.obsp["connectivities"]
assert fused.shape == expr.shape == spatial.shape, (
"Fused graph should have same shape as input graphs."
)
def test_alpha_zero_equals_expression(run_component, tmp_path):
output = tmp_path / "alpha_zero.h5mu"
run_component(
[
"--input",
input_file,
"--output",
str(output),
"--alpha",
"0.0",
"--output_obsp_graph",
"fused_zero",
]
)
mdata = mu.read_h5mu(output)
adata = mdata.mod["rna"]
fused = adata.obsp["fused_zero"]
# Should equal expression graph exactly (dense check might be heavy, check nnz or sum)
expr = adata.obsp["connectivities"]
assert abs(fused.sum() - expr.sum()) < 1e-6
def test_alpha_one_equals_spatial(run_component, tmp_path):
output = tmp_path / "alpha_one.h5mu"
run_component(
[
"--input",
input_file,
"--output",
str(output),
"--alpha",
"1.0",
"--output_obsp_graph",
"fused_one",
]
)
mdata = mu.read_h5mu(output)
adata = mdata.mod["rna"]
fused = adata.obsp["fused_one"]
# Should equal spatial graph exactly
spatial = adata.obsp["spatial_connectivities"]
assert abs(fused.sum() - spatial.sum()) < 1e-6
if __name__ == "__main__":
sys.exit(pytest.main([__file__]))

View File

@@ -33,6 +33,12 @@ argument_groups:
type: string
required: false
description: "Input layer to use. If None, X is used"
- name: "--var_input"
type: string
default: "filter_with_hvg"
description: |
Key in adata.var that indicates which features to include as input for the NicheCompass model.
If not provided, all features will be included.
- name: "--input_obsp_spatial_connectivities"
type: string
default: "spatial_connectivities"
@@ -429,6 +435,7 @@ resources:
- type: python_script
path: script.py
- path: /src/utils/setup_logger.py
- path: /src/utils/subset_vars.py
test_resources:
- type: python_script

View File

@@ -15,6 +15,7 @@ par = {
"input_gp_mask": "resources_test/niche/prior_knowledge_gp_mask.json",
"input_obs_covariates": None,
"input_obsp_spatial_connectivities": "spatial_connectivities",
"var_input": "filter_with_hvg",
## GP Mask
"min_genes_per_gp": 2,
"min_source_genes_per_gp": 1,
@@ -89,6 +90,7 @@ meta = {"resources_dir": "src/utils/"}
sys.path.append(meta["resources_dir"])
from setup_logger import setup_logger
from subset_vars import subset_vars
logger = setup_logger()
@@ -101,6 +103,11 @@ logger.info(f"GPU count: {torch.cuda.device_count()}")
## Read in data
adata = mu.read_h5ad(par["input"], mod=par["modality"])
# Subset to HVG
if par["var_input"]:
# Subset to HVG
adata = subset_vars(adata, subset_col=par["var_input"]).copy()
# Counts need to be float32 to be processed by nichecompass model
# See https://discuss.pytorch.org/t/runtimeerror-mat1-and-mat2-must-have-the-same-dtype/166759
counts_dtype = (

View File

@@ -1,5 +1,6 @@
import pytest
import mudata as mu
import numpy as np
import sys
## VIASH START
@@ -8,21 +9,38 @@ meta = {
}
## VIASH END
input_xenium = f"{meta['resources_dir']}/xenium_tiny.h5mu"
input_cosmx = f"{meta['resources_dir']}/Lung5_Rep2_tiny.h5mu"
input_path_xenium = f"{meta['resources_dir']}/xenium_tiny.h5mu"
input_path_cosmx = f"{meta['resources_dir']}/Lung5_Rep2_tiny.h5mu"
gp_mask = f"{meta['resources_dir']}/prior_knowledge_gp_mask.json"
def test_simple_execution_xenium(run_component, tmp_path):
@pytest.fixture
def input_xenium_with_hvg_filter(tmp_path):
mdata = mu.read_h5mu(input_path_xenium)
adata = mdata.mod["rna"]
np.random.seed(42)
n_select = min(1000, adata.n_vars)
selected = np.random.choice(adata.n_vars, size=n_select, replace=False)
mask = np.zeros(adata.n_vars, dtype=bool)
mask[selected] = True
adata.var["filter_with_hvg"] = mask
output = tmp_path / "xenium_with_hvg_filter.h5mu"
mdata.write_h5mu(output)
return str(output)
def test_simple_execution_xenium(run_component, tmp_path, input_xenium_with_hvg_filter):
output = tmp_path / "nc_xenium.h5mu"
# run component
run_component(
[
"--input",
input_xenium,
input_xenium_with_hvg_filter,
"--input_gp_mask",
gp_mask,
"--var_input",
"filter_with_hvg",
"--n_epochs",
"1",
"--n_epochs_all_gps",
@@ -84,5 +102,48 @@ def test_simple_execution_xenium(run_component, tmp_path):
), "Expected GP targets and sources varm to have same shape"
def test_no_var_input(run_component, tmp_path, input_xenium_with_hvg_filter):
output = tmp_path / "nc_xenium_no_var_input.h5mu"
# run component without var_input (all genes are used)
run_component(
[
"--input",
input_xenium_with_hvg_filter,
"--input_gp_mask",
gp_mask,
"--var_input",
"",
"--n_epochs",
"1",
"--n_epochs_all_gps",
"0",
"--n_epochs_no_edge_recon",
"0",
"--n_epochs_no_cat_covariates_contrastive",
"0",
"--output",
str(output),
"--output_model",
"test_model_no_var_input",
"--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"]
expected_uns_keys = [
"nichecompass_gp_names",
"nichecompass_active_gp_names",
]
assert all([uns in adata.uns.keys() for uns in expected_uns_keys]), (
f"Expected uns keys: {expected_uns_keys}, found: {list(adata.uns.keys())}"
)
if __name__ == "__main__":
sys.exit(pytest.main([__file__]))

49
src/utils/subset_vars.py Normal file
View File

@@ -0,0 +1,49 @@
def subset_vars(adata, subset_col):
"""
Subset AnnData object on highly variable genes or a boolean mask.
Parameters
----------
adata : AnnData
Annotated data object
subset_col : str, pd.Series, pd.Index, or np.ndarray
Name of the boolean column in `adata.var` that contains the information if features should be used or not,
or a boolean mask (same length as adata.var)
Returns
-------
AnnData
Copy of `adata` with subsetted features
"""
import pandas as pd
import numpy as np
# Convert all input types to a pandas Series
if isinstance(subset_col, str):
if subset_col not in adata.var.columns:
raise ValueError(
f"Requested to use .var column '{subset_col}' as a selection of genes, but the column is not available."
)
mask = adata.var[subset_col]
elif isinstance(subset_col, pd.Series):
mask = subset_col
elif isinstance(subset_col, (pd.Index, np.ndarray, list)):
mask = pd.Series(subset_col, index=adata.var.index)
else:
raise TypeError(
"subset_col must be a string (column name) or a boolean mask (Series, Index, ndarray, or list)."
)
# Validate mask
if not pd.api.types.is_bool_dtype(mask):
raise ValueError(
f"Expected mask to be boolean, but found {mask.dtype}. Can not subset data."
)
if mask.isna().sum() > 0:
raise ValueError("Mask contains NaN values. Can not subset data.")
if len(mask) != adata.n_vars:
raise ValueError(
f"Mask length {len(mask)} does not match number of variables {adata.n_vars}."
)
return adata[:, mask].copy()

View File

@@ -57,18 +57,18 @@ argument_groups:
type: string
default: "spatial"
description: "Key in adata.obsm where spatial coordinates are stored"
- name: "--var_input"
type: string
default: "filter_with_hvg"
description: |
Key in adata.var that indicates which features to include as input for the NicheCompass model.
If not provided, all features will be included.
- name: "Sample ID options"
description: |
Options for adding the id to .obs on the MuData object. Having a sample
id present in a requirement of several components for this pipeline.
arguments:
- name: "--include_sample_as_covariate"
description: |
Whether to include the sample information as a categorical covariate for the
NicheCompass model.
type: boolean
default: true
- name: "--add_id_to_obs"
description: "Add the value passed with --id to .obs."
type: boolean
@@ -357,6 +357,7 @@ dependencies:
- name: neighbors/spatial_neighborhood_graph
- name: nichecompass/nichecompass
- name: dataflow/split_h5mu
repository: openpipeline
- name: workflows/multiomics/neighbors_leiden_umap
repository: openpipeline

View File

@@ -117,6 +117,7 @@ workflow run_wf {
"input": state.input,
"input_gp_mask": state.input_gp_mask,
"input_obs_covariates": state.input_obs_covariates,
"var_input": state.var_input,
"modality": state.modality,
"layer": state.layer,
"min_genes_per_gp": state.min_genes_per_gp,

View File

@@ -19,7 +19,8 @@ workflow test_wf {
n_epochs_all_gps: 0,
n_epochs_no_edge_recon: 0,
n_epochs_no_cat_covariates_contrastive_loss: 0,
output_model: "simple_execution_test_model"
output_model: "simple_execution_test_model",
var_input: null
]
])
| map { state -> [state.id, state] }

View File

@@ -112,7 +112,7 @@ repositories:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
docker_registry: "ghcr.io"
@@ -227,7 +227,7 @@ build_info:
output: "target/_private/executable/filter/subset_cosmx"
executable: "target/_private/executable/filter/subset_cosmx/subset_cosmx"
viash_version: "0.9.4"
git_commit: "ad19aba349736848d99a9646870d8e7868eb6515"
git_commit: "87e62605aafd706d539bf2978ef47ede6fe41926"
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
package_config:
name: "openpipeline_spatial"
@@ -241,7 +241,7 @@ package_config:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
viash_version: "0.9.4"
source: "src"
target: "target"

View File

@@ -458,9 +458,9 @@ 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="2026-02-17T11:00:57Z"
LABEL org.opencontainers.image.created="2026-03-25T10:11:21Z"
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
LABEL org.opencontainers.image.revision="ad19aba349736848d99a9646870d8e7868eb6515"
LABEL org.opencontainers.image.revision="87e62605aafd706d539bf2978ef47ede6fe41926"
LABEL org.opencontainers.image.version="niche-compass"
VIASHDOCKER

View File

@@ -112,7 +112,7 @@ repositories:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
docker_registry: "ghcr.io"
@@ -227,7 +227,7 @@ build_info:
output: "target/_private/nextflow/filter/subset_cosmx"
executable: "target/_private/nextflow/filter/subset_cosmx/main.nf"
viash_version: "0.9.4"
git_commit: "ad19aba349736848d99a9646870d8e7868eb6515"
git_commit: "87e62605aafd706d539bf2978ef47ede6fe41926"
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
package_config:
name: "openpipeline_spatial"
@@ -241,7 +241,7 @@ package_config:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
viash_version: "0.9.4"
source: "src"
target: "target"

View File

@@ -3187,7 +3187,7 @@ meta = [
"type" : "vsh",
"name" : "openpipeline",
"repo" : "openpipeline",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
}
],
"links" : {
@@ -3333,7 +3333,7 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/_private/nextflow/filter/subset_cosmx",
"viash_version" : "0.9.4",
"git_commit" : "ad19aba349736848d99a9646870d8e7868eb6515",
"git_commit" : "87e62605aafd706d539bf2978ef47ede6fe41926",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
},
"package_config" : {
@@ -3353,7 +3353,7 @@ meta = [
"type" : "vsh",
"name" : "openpipeline",
"repo" : "openpipeline",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
}
],
"viash_version" : "0.9.4",

View File

@@ -48,7 +48,7 @@ repositories:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
docker_registry: "ghcr.io"
@@ -157,7 +157,7 @@ build_info:
output: "target/_test/executable/test_workflows/ingestion/spaceranger_mapping_test"
executable: "target/_test/executable/test_workflows/ingestion/spaceranger_mapping_test/spaceranger_mapping_test"
viash_version: "0.9.4"
git_commit: "ad19aba349736848d99a9646870d8e7868eb6515"
git_commit: "87e62605aafd706d539bf2978ef47ede6fe41926"
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
package_config:
name: "openpipeline_spatial"
@@ -171,7 +171,7 @@ package_config:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
viash_version: "0.9.4"
source: "src"
target: "target"

View File

@@ -459,9 +459,9 @@ RUN pip install --upgrade pip && \
LABEL org.opencontainers.image.authors="Dorien Roosen"
LABEL org.opencontainers.image.description="Companion container for running component test_workflows/ingestion spaceranger_mapping_test"
LABEL org.opencontainers.image.created="2026-02-17T11:00:59Z"
LABEL org.opencontainers.image.created="2026-03-25T10:11:23Z"
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
LABEL org.opencontainers.image.revision="ad19aba349736848d99a9646870d8e7868eb6515"
LABEL org.opencontainers.image.revision="87e62605aafd706d539bf2978ef47ede6fe41926"
LABEL org.opencontainers.image.version="niche-compass"
VIASHDOCKER

View File

@@ -47,7 +47,7 @@ repositories:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
docker_registry: "ghcr.io"
@@ -156,7 +156,7 @@ build_info:
output: "target/_test/executable/test_workflows/niche/nichecompass_leiden_test"
executable: "target/_test/executable/test_workflows/niche/nichecompass_leiden_test/nichecompass_leiden_test"
viash_version: "0.9.4"
git_commit: "ad19aba349736848d99a9646870d8e7868eb6515"
git_commit: "87e62605aafd706d539bf2978ef47ede6fe41926"
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
package_config:
name: "openpipeline_spatial"
@@ -170,7 +170,7 @@ package_config:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
viash_version: "0.9.4"
source: "src"
target: "target"

View File

@@ -459,9 +459,9 @@ RUN pip install --upgrade pip && \
LABEL org.opencontainers.image.authors="Dorien Roosen"
LABEL org.opencontainers.image.description="Companion container for running component test_workflows/niche nichecompass_leiden_test"
LABEL org.opencontainers.image.created="2026-02-17T11:00:59Z"
LABEL org.opencontainers.image.created="2026-03-25T10:11:23Z"
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
LABEL org.opencontainers.image.revision="ad19aba349736848d99a9646870d8e7868eb6515"
LABEL org.opencontainers.image.revision="87e62605aafd706d539bf2978ef47ede6fe41926"
LABEL org.opencontainers.image.version="niche-compass"
VIASHDOCKER

View File

@@ -48,7 +48,7 @@ repositories:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
docker_registry: "ghcr.io"
@@ -157,7 +157,7 @@ build_info:
output: "target/_test/nextflow/test_workflows/ingestion/spaceranger_mapping_test"
executable: "target/_test/nextflow/test_workflows/ingestion/spaceranger_mapping_test/main.nf"
viash_version: "0.9.4"
git_commit: "ad19aba349736848d99a9646870d8e7868eb6515"
git_commit: "87e62605aafd706d539bf2978ef47ede6fe41926"
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
package_config:
name: "openpipeline_spatial"
@@ -171,7 +171,7 @@ package_config:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
viash_version: "0.9.4"
source: "src"
target: "target"

View File

@@ -3104,7 +3104,7 @@ meta = [
"type" : "vsh",
"name" : "openpipeline",
"repo" : "openpipeline",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
}
],
"links" : {
@@ -3235,7 +3235,7 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/_test/nextflow/test_workflows/ingestion/spaceranger_mapping_test",
"viash_version" : "0.9.4",
"git_commit" : "ad19aba349736848d99a9646870d8e7868eb6515",
"git_commit" : "87e62605aafd706d539bf2978ef47ede6fe41926",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
},
"package_config" : {
@@ -3255,7 +3255,7 @@ meta = [
"type" : "vsh",
"name" : "openpipeline",
"repo" : "openpipeline",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
}
],
"viash_version" : "0.9.4",

View File

@@ -47,7 +47,7 @@ repositories:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
docker_registry: "ghcr.io"
@@ -156,7 +156,7 @@ build_info:
output: "target/_test/nextflow/test_workflows/niche/nichecompass_leiden_test"
executable: "target/_test/nextflow/test_workflows/niche/nichecompass_leiden_test/main.nf"
viash_version: "0.9.4"
git_commit: "ad19aba349736848d99a9646870d8e7868eb6515"
git_commit: "87e62605aafd706d539bf2978ef47ede6fe41926"
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
package_config:
name: "openpipeline_spatial"
@@ -170,7 +170,7 @@ package_config:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
tag: "v4.0.3"
viash_version: "0.9.4"
source: "src"
target: "target"

View File

@@ -3104,7 +3104,7 @@ meta = [
"type" : "vsh",
"name" : "openpipeline",
"repo" : "openpipeline",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
}
],
"links" : {
@@ -3235,7 +3235,7 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/_test/nextflow/test_workflows/niche/nichecompass_leiden_test",
"viash_version" : "0.9.4",
"git_commit" : "ad19aba349736848d99a9646870d8e7868eb6515",
"git_commit" : "87e62605aafd706d539bf2978ef47ede6fe41926",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
},
"package_config" : {
@@ -3255,7 +3255,7 @@ meta = [
"type" : "vsh",
"name" : "openpipeline",
"repo" : "openpipeline",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
}
],
"viash_version" : "0.9.4",

View File

@@ -1,6 +1,6 @@
name: "split_modalities"
namespace: "workflows/multiomics"
version: "v4.0.2"
version: "v4.0.3"
authors:
- name: "Dries Schaumont"
roles:
@@ -183,13 +183,13 @@ build_info:
output: "target/_private/nextflow/workflows/multiomics/split_modalities"
executable: "target/_private/nextflow/workflows/multiomics/split_modalities/main.nf"
viash_version: "0.9.4"
git_commit: "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62"
git_commit: "7bfad4ea12f87eca59213be3ab08deff67cc4206"
git_remote: "https://github.com/openpipelines-bio/openpipeline"
dependencies:
- "target/nextflow/dataflow/split_modalities"
package_config:
name: "openpipeline"
version: "v4.0.2"
version: "v4.0.3"
summary: "Best-practice workflows for single-cell multi-omics analyses.\n"
description: "OpenPipelines are extensible single cell analysis pipelines for reproducible\
\ and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\
@@ -219,7 +219,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.2'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.3'"
keywords:
- "single-cell"
- "multimodal"

View File

@@ -1,4 +1,4 @@
// split_modalities v4.0.2
// split_modalities v4.0.3
//
// 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" : "split_modalities",
"namespace" : "workflows/multiomics",
"version" : "v4.0.2",
"version" : "v4.0.3",
"authors" : [
{
"name" : "Dries Schaumont",
@@ -3274,12 +3274,12 @@ meta = [
"engine" : "native",
"output" : "/workdir/root/repo/target/_private/nextflow/workflows/multiomics/split_modalities",
"viash_version" : "0.9.4",
"git_commit" : "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62",
"git_commit" : "7bfad4ea12f87eca59213be3ab08deff67cc4206",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline"
},
"package_config" : {
"name" : "openpipeline",
"version" : "v4.0.2",
"version" : "v4.0.3",
"summary" : "Best-practice workflows for single-cell multi-omics analyses.\n",
"description" : "OpenPipelines are extensible single cell analysis pipelines for reproducible and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\nIn terms of workflows, the following has been made available, but keep in mind that\nindividual tools and functionality can be executed as standalone components as well.\n\n * Demultiplexing: conversion of raw sequencing data to FASTQ objects.\n * Ingestion: Read mapping and generating a count matrix.\n * Single sample processing: cell filtering and doublet detection.\n * Multisample processing: Count transformation, normalization, QC metric calulations.\n * Integration: Clustering, integration and batch correction using single and multimodal methods.\n * Downstream analysis workflows\n",
"info" : {
@@ -3304,7 +3304,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 := 'v4.0.2'"
".engines[.type == 'docker'].target_tag := 'v4.0.3'"
],
"keywords" : [
"single-cell",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'workflows/multiomics/split_modalities'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v4.0.2'
version = 'v4.0.3'
description = 'A pipeline to split a multimodal mudata files into several unimodal mudata files.'
author = 'Dries Schaumont'
}

View File

@@ -1,6 +1,6 @@
name: "log_normalize"
namespace: "workflows/rna"
version: "v4.0.2"
version: "v4.0.3"
authors:
- name: "Dries Schaumont"
roles:
@@ -198,7 +198,7 @@ build_info:
output: "target/_private/nextflow/workflows/rna/log_normalize"
executable: "target/_private/nextflow/workflows/rna/log_normalize/main.nf"
viash_version: "0.9.4"
git_commit: "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62"
git_commit: "7bfad4ea12f87eca59213be3ab08deff67cc4206"
git_remote: "https://github.com/openpipelines-bio/openpipeline"
dependencies:
- "target/nextflow/transform/normalize_total"
@@ -206,7 +206,7 @@ build_info:
- "target/nextflow/transform/delete_layer"
package_config:
name: "openpipeline"
version: "v4.0.2"
version: "v4.0.3"
summary: "Best-practice workflows for single-cell multi-omics analyses.\n"
description: "OpenPipelines are extensible single cell analysis pipelines for reproducible\
\ and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\
@@ -236,7 +236,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.2'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.3'"
keywords:
- "single-cell"
- "multimodal"

View File

@@ -1,4 +1,4 @@
// log_normalize v4.0.2
// log_normalize v4.0.3
//
// 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" : "log_normalize",
"namespace" : "workflows/rna",
"version" : "v4.0.2",
"version" : "v4.0.3",
"authors" : [
{
"name" : "Dries Schaumont",
@@ -3294,12 +3294,12 @@ meta = [
"engine" : "native",
"output" : "/workdir/root/repo/target/_private/nextflow/workflows/rna/log_normalize",
"viash_version" : "0.9.4",
"git_commit" : "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62",
"git_commit" : "7bfad4ea12f87eca59213be3ab08deff67cc4206",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline"
},
"package_config" : {
"name" : "openpipeline",
"version" : "v4.0.2",
"version" : "v4.0.3",
"summary" : "Best-practice workflows for single-cell multi-omics analyses.\n",
"description" : "OpenPipelines are extensible single cell analysis pipelines for reproducible and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\nIn terms of workflows, the following has been made available, but keep in mind that\nindividual tools and functionality can be executed as standalone components as well.\n\n * Demultiplexing: conversion of raw sequencing data to FASTQ objects.\n * Ingestion: Read mapping and generating a count matrix.\n * Single sample processing: cell filtering and doublet detection.\n * Multisample processing: Count transformation, normalization, QC metric calulations.\n * Integration: Clustering, integration and batch correction using single and multimodal methods.\n * Downstream analysis workflows\n",
"info" : {
@@ -3324,7 +3324,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 := 'v4.0.2'"
".engines[.type == 'docker'].target_tag := 'v4.0.3'"
],
"keywords" : [
"single-cell",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'workflows/rna/log_normalize'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v4.0.2'
version = 'v4.0.3'
description = 'Performs normalization and subsequent log-transformation of raw count data.'
author = 'Dries Schaumont'
}

View File

@@ -1,6 +1,6 @@
name: "leiden"
namespace: "cluster"
version: "v4.0.2"
version: "v4.0.3"
authors:
- name: "Dries De Maeyer"
roles:
@@ -215,7 +215,7 @@ engines:
id: "docker"
image: "python:3.13-slim"
target_registry: "images.viash-hub.com"
target_tag: "v4.0.2"
target_tag: "v4.0.3"
namespace_separator: "/"
setup:
- type: "apt"
@@ -258,11 +258,11 @@ build_info:
output: "target/nextflow/cluster/leiden"
executable: "target/nextflow/cluster/leiden/main.nf"
viash_version: "0.9.4"
git_commit: "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62"
git_commit: "7bfad4ea12f87eca59213be3ab08deff67cc4206"
git_remote: "https://github.com/openpipelines-bio/openpipeline"
package_config:
name: "openpipeline"
version: "v4.0.2"
version: "v4.0.3"
summary: "Best-practice workflows for single-cell multi-omics analyses.\n"
description: "OpenPipelines are extensible single cell analysis pipelines for reproducible\
\ and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\
@@ -292,7 +292,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.2'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.3'"
keywords:
- "single-cell"
- "multimodal"

View File

@@ -1,4 +1,4 @@
// leiden v4.0.2
// leiden v4.0.3
//
// 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" : "leiden",
"namespace" : "cluster",
"version" : "v4.0.2",
"version" : "v4.0.3",
"authors" : [
{
"name" : "Dries De Maeyer",
@@ -3294,7 +3294,7 @@ meta = [
"id" : "docker",
"image" : "python:3.13-slim",
"target_registry" : "images.viash-hub.com",
"target_tag" : "v4.0.2",
"target_tag" : "v4.0.3",
"namespace_separator" : "/",
"setup" : [
{
@@ -3352,12 +3352,12 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/nextflow/cluster/leiden",
"viash_version" : "0.9.4",
"git_commit" : "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62",
"git_commit" : "7bfad4ea12f87eca59213be3ab08deff67cc4206",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline"
},
"package_config" : {
"name" : "openpipeline",
"version" : "v4.0.2",
"version" : "v4.0.3",
"summary" : "Best-practice workflows for single-cell multi-omics analyses.\n",
"description" : "OpenPipelines are extensible single cell analysis pipelines for reproducible and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\nIn terms of workflows, the following has been made available, but keep in mind that\nindividual tools and functionality can be executed as standalone components as well.\n\n * Demultiplexing: conversion of raw sequencing data to FASTQ objects.\n * Ingestion: Read mapping and generating a count matrix.\n * Single sample processing: cell filtering and doublet detection.\n * Multisample processing: Count transformation, normalization, QC metric calulations.\n * Integration: Clustering, integration and batch correction using single and multimodal methods.\n * Downstream analysis workflows\n",
"info" : {
@@ -3382,7 +3382,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 := 'v4.0.2'"
".engines[.type == 'docker'].target_tag := 'v4.0.3'"
],
"keywords" : [
"single-cell",
@@ -4147,7 +4147,7 @@ meta["defaults"] = [
"container" : {
"registry" : "images.viash-hub.com",
"image" : "vsh/openpipeline/cluster/leiden",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
},
"label" : [
"highcpu",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'cluster/leiden'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v4.0.2'
version = 'v4.0.3'
description = 'Cluster cells using the [Leiden algorithm] [Traag18] implemented in the [Scanpy framework] [Wolf18]. \nLeiden is an improved version of the [Louvain algorithm] [Blondel08]. \nIt has been proposed for single-cell analysis by [Levine15] [Levine15]. \nThis requires having ran `neighbors/find_neighbors` or `neighbors/bbknn` first.\n\n[Blondel08]: Blondel et al. (2008), Fast unfolding of communities in large networks, J. Stat. Mech. \n[Levine15]: Levine et al. (2015), Data-Driven Phenotypic Dissection of AML Reveals Progenitor-like Cells that Correlate with Prognosis, Cell. \n[Traag18]: Traag et al. (2018), From Louvain to Leiden: guaranteeing well-connected communities arXiv. \n[Wolf18]: Wolf et al. (2018), Scanpy: large-scale single-cell gene expression data analysis, Genome Biology. \n'
author = 'Dries De Maeyer'
}

View File

@@ -1,6 +1,6 @@
name: "concatenate_h5mu"
namespace: "dataflow"
version: "v4.0.2"
version: "v4.0.3"
authors:
- name: "Dries Schaumont"
roles:
@@ -253,7 +253,7 @@ engines:
id: "docker"
image: "python:3.13-slim"
target_registry: "images.viash-hub.com"
target_tag: "v4.0.2"
target_tag: "v4.0.3"
namespace_separator: "/"
setup:
- type: "apt"
@@ -300,11 +300,11 @@ build_info:
output: "target/nextflow/dataflow/concatenate_h5mu"
executable: "target/nextflow/dataflow/concatenate_h5mu/main.nf"
viash_version: "0.9.4"
git_commit: "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62"
git_commit: "7bfad4ea12f87eca59213be3ab08deff67cc4206"
git_remote: "https://github.com/openpipelines-bio/openpipeline"
package_config:
name: "openpipeline"
version: "v4.0.2"
version: "v4.0.3"
summary: "Best-practice workflows for single-cell multi-omics analyses.\n"
description: "OpenPipelines are extensible single cell analysis pipelines for reproducible\
\ and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\
@@ -334,7 +334,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.2'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.3'"
keywords:
- "single-cell"
- "multimodal"

View File

@@ -1,4 +1,4 @@
// concatenate_h5mu v4.0.2
// concatenate_h5mu v4.0.3
//
// 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" : "concatenate_h5mu",
"namespace" : "dataflow",
"version" : "v4.0.2",
"version" : "v4.0.3",
"authors" : [
{
"name" : "Dries Schaumont",
@@ -3328,7 +3328,7 @@ meta = [
"id" : "docker",
"image" : "python:3.13-slim",
"target_registry" : "images.viash-hub.com",
"target_tag" : "v4.0.2",
"target_tag" : "v4.0.3",
"namespace_separator" : "/",
"setup" : [
{
@@ -3393,12 +3393,12 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/nextflow/dataflow/concatenate_h5mu",
"viash_version" : "0.9.4",
"git_commit" : "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62",
"git_commit" : "7bfad4ea12f87eca59213be3ab08deff67cc4206",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline"
},
"package_config" : {
"name" : "openpipeline",
"version" : "v4.0.2",
"version" : "v4.0.3",
"summary" : "Best-practice workflows for single-cell multi-omics analyses.\n",
"description" : "OpenPipelines are extensible single cell analysis pipelines for reproducible and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\nIn terms of workflows, the following has been made available, but keep in mind that\nindividual tools and functionality can be executed as standalone components as well.\n\n * Demultiplexing: conversion of raw sequencing data to FASTQ objects.\n * Ingestion: Read mapping and generating a count matrix.\n * Single sample processing: cell filtering and doublet detection.\n * Multisample processing: Count transformation, normalization, QC metric calulations.\n * Integration: Clustering, integration and batch correction using single and multimodal methods.\n * Downstream analysis workflows\n",
"info" : {
@@ -3423,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 := 'v4.0.2'"
".engines[.type == 'docker'].target_tag := 'v4.0.3'"
],
"keywords" : [
"single-cell",
@@ -4266,7 +4266,7 @@ meta["defaults"] = [
"container" : {
"registry" : "images.viash-hub.com",
"image" : "vsh/openpipeline/dataflow/concatenate_h5mu",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
},
"label" : [
"midcpu",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'dataflow/concatenate_h5mu'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v4.0.2'
version = 'v4.0.3'
description = 'Concatenate observations from samples in several (uni- and/or multi-modal) MuData files into a single file.\n'
author = 'Dries Schaumont'
}

View File

@@ -1,6 +1,6 @@
name: "merge"
namespace: "dataflow"
version: "v4.0.2"
version: "v4.0.3"
authors:
- name: "Dries Schaumont"
roles:
@@ -163,7 +163,7 @@ engines:
id: "docker"
image: "python:3.12-slim"
target_registry: "images.viash-hub.com"
target_tag: "v4.0.2"
target_tag: "v4.0.3"
namespace_separator: "/"
setup:
- type: "apt"
@@ -204,11 +204,11 @@ build_info:
output: "target/nextflow/dataflow/merge"
executable: "target/nextflow/dataflow/merge/main.nf"
viash_version: "0.9.4"
git_commit: "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62"
git_commit: "7bfad4ea12f87eca59213be3ab08deff67cc4206"
git_remote: "https://github.com/openpipelines-bio/openpipeline"
package_config:
name: "openpipeline"
version: "v4.0.2"
version: "v4.0.3"
summary: "Best-practice workflows for single-cell multi-omics analyses.\n"
description: "OpenPipelines are extensible single cell analysis pipelines for reproducible\
\ and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\
@@ -238,7 +238,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.2'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.3'"
keywords:
- "single-cell"
- "multimodal"

View File

@@ -1,4 +1,4 @@
// merge v4.0.2
// merge v4.0.3
//
// 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" : "merge",
"namespace" : "dataflow",
"version" : "v4.0.2",
"version" : "v4.0.3",
"authors" : [
{
"name" : "Dries Schaumont",
@@ -3246,7 +3246,7 @@ meta = [
"id" : "docker",
"image" : "python:3.12-slim",
"target_registry" : "images.viash-hub.com",
"target_tag" : "v4.0.2",
"target_tag" : "v4.0.3",
"namespace_separator" : "/",
"setup" : [
{
@@ -3302,12 +3302,12 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/nextflow/dataflow/merge",
"viash_version" : "0.9.4",
"git_commit" : "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62",
"git_commit" : "7bfad4ea12f87eca59213be3ab08deff67cc4206",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline"
},
"package_config" : {
"name" : "openpipeline",
"version" : "v4.0.2",
"version" : "v4.0.3",
"summary" : "Best-practice workflows for single-cell multi-omics analyses.\n",
"description" : "OpenPipelines are extensible single cell analysis pipelines for reproducible and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\nIn terms of workflows, the following has been made available, but keep in mind that\nindividual tools and functionality can be executed as standalone components as well.\n\n * Demultiplexing: conversion of raw sequencing data to FASTQ objects.\n * Ingestion: Read mapping and generating a count matrix.\n * Single sample processing: cell filtering and doublet detection.\n * Multisample processing: Count transformation, normalization, QC metric calulations.\n * Integration: Clustering, integration and batch correction using single and multimodal methods.\n * Downstream analysis workflows\n",
"info" : {
@@ -3332,7 +3332,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 := 'v4.0.2'"
".engines[.type == 'docker'].target_tag := 'v4.0.3'"
],
"keywords" : [
"single-cell",
@@ -3847,7 +3847,7 @@ meta["defaults"] = [
"container" : {
"registry" : "images.viash-hub.com",
"image" : "vsh/openpipeline/dataflow/merge",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
},
"label" : [
"singlecpu",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'dataflow/merge'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v4.0.2'
version = 'v4.0.3'
description = 'Combine one or more single-modality .h5mu files together into one .h5mu file.\n'
author = 'Dries Schaumont'
}

View File

@@ -1,6 +1,6 @@
name: "split_h5mu"
namespace: "dataflow"
version: "niche-compass"
version: "v4.0.3"
authors:
- name: "Dorien Roosen"
roles:
@@ -123,13 +123,9 @@ status: "enabled"
scope:
image: "public"
target: "public"
repositories:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
license: "MIT"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
repository: "https://github.com/openpipelines-bio/openpipeline"
docker_registry: "ghcr.io"
runners:
- type: "executable"
@@ -207,7 +203,7 @@ engines:
id: "docker"
image: "python:3.12-slim"
target_registry: "images.viash-hub.com"
target_tag: "niche-compass"
target_tag: "v4.0.3"
namespace_separator: "/"
setup:
- type: "apt"
@@ -233,7 +229,7 @@ engines:
- type: "python"
user: false
packages:
- "viashpy==0.9.0"
- "viashpy==0.8.0"
github:
- "openpipelines-bio/core#subdirectory=packages/python/openpipeline_testutils"
upgrade: true
@@ -248,21 +244,31 @@ build_info:
output: "target/nextflow/dataflow/split_h5mu"
executable: "target/nextflow/dataflow/split_h5mu/main.nf"
viash_version: "0.9.4"
git_commit: "ad19aba349736848d99a9646870d8e7868eb6515"
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
git_commit: "7bfad4ea12f87eca59213be3ab08deff67cc4206"
git_remote: "https://github.com/openpipelines-bio/openpipeline"
package_config:
name: "openpipeline_spatial"
version: "niche-compass"
name: "openpipeline"
version: "v4.0.3"
summary: "Best-practice workflows for single-cell multi-omics analyses.\n"
description: "OpenPipelines are extensible single cell analysis pipelines for reproducible\
\ and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\
\nIn terms of workflows, the following has been made available, but keep in mind\
\ that\nindividual tools and functionality can be executed as standalone components\
\ as well.\n\n * Demultiplexing: conversion of raw sequencing data to FASTQ objects.\n\
\ * Ingestion: Read mapping and generating a count matrix.\n * Single sample\
\ processing: cell filtering and doublet detection.\n * Multisample processing:\
\ Count transformation, normalization, QC metric calulations.\n * Integration:\
\ Clustering, integration and batch correction using single and multimodal methods.\n\
\ * Downstream analysis workflows\n"
info:
test_resources:
- type: "s3"
path: "s3://openpipelines-bio/openpipeline_spatial/resources_test"
path: "s3://openpipelines-data"
dest: "resources_test"
repositories:
- type: "vsh"
name: "openpipeline"
repo: "openpipeline"
tag: "v4.0.2"
nextflow_labels_ci:
- path: "src/workflows/utils/labels_ci.config"
description: "Adds the correct memory and CPU labels when running on the Viash\
\ Hub CI."
viash_version: "0.9.4"
source: "src"
target: "target"
@@ -272,8 +278,15 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'niche-compass'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.3'"
keywords:
- "single-cell"
- "multimodal"
license: "MIT"
organization: "vsh"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"
repository: "https://github.com/openpipelines-bio/openpipeline"
docker_registry: "ghcr.io"
homepage: "https://openpipelines.bio"
documentation: "https://openpipelines.bio/fundamentals"
issue_tracker: "https://github.com/openpipelines-bio/openpipeline/issues"

View File

@@ -1,4 +1,4 @@
// split_h5mu niche-compass
// split_h5mu v4.0.3
//
// 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" : "split_h5mu",
"namespace" : "dataflow",
"version" : "niche-compass",
"version" : "v4.0.3",
"authors" : [
{
"name" : "Dorien Roosen",
@@ -3192,16 +3192,9 @@ meta = [
"image" : "public",
"target" : "public"
},
"repositories" : [
{
"type" : "vsh",
"name" : "openpipeline",
"repo" : "openpipeline",
"tag" : "v4.0.2"
}
],
"license" : "MIT",
"links" : {
"repository" : "https://github.com/openpipelines-bio/openpipeline_spatial",
"repository" : "https://github.com/openpipelines-bio/openpipeline",
"docker_registry" : "ghcr.io"
},
"runners" : [
@@ -3292,7 +3285,7 @@ meta = [
"id" : "docker",
"image" : "python:3.12-slim",
"target_registry" : "images.viash-hub.com",
"target_tag" : "niche-compass",
"target_tag" : "v4.0.3",
"namespace_separator" : "/",
"setup" : [
{
@@ -3328,7 +3321,7 @@ meta = [
"type" : "python",
"user" : false,
"packages" : [
"viashpy==0.9.0"
"viashpy==0.8.0"
],
"github" : [
"openpipelines-bio/core#subdirectory=packages/python/openpipeline_testutils"
@@ -3348,29 +3341,29 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/nextflow/dataflow/split_h5mu",
"viash_version" : "0.9.4",
"git_commit" : "ad19aba349736848d99a9646870d8e7868eb6515",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_spatial"
"git_commit" : "7bfad4ea12f87eca59213be3ab08deff67cc4206",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline"
},
"package_config" : {
"name" : "openpipeline_spatial",
"version" : "niche-compass",
"name" : "openpipeline",
"version" : "v4.0.3",
"summary" : "Best-practice workflows for single-cell multi-omics analyses.\n",
"description" : "OpenPipelines are extensible single cell analysis pipelines for reproducible and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\nIn terms of workflows, the following has been made available, but keep in mind that\nindividual tools and functionality can be executed as standalone components as well.\n\n * Demultiplexing: conversion of raw sequencing data to FASTQ objects.\n * Ingestion: Read mapping and generating a count matrix.\n * Single sample processing: cell filtering and doublet detection.\n * Multisample processing: Count transformation, normalization, QC metric calulations.\n * Integration: Clustering, integration and batch correction using single and multimodal methods.\n * Downstream analysis workflows\n",
"info" : {
"test_resources" : [
{
"type" : "s3",
"path" : "s3://openpipelines-bio/openpipeline_spatial/resources_test",
"path" : "s3://openpipelines-data",
"dest" : "resources_test"
}
],
"nextflow_labels_ci" : [
{
"path" : "src/workflows/utils/labels_ci.config",
"description" : "Adds the correct memory and CPU labels when running on the Viash Hub CI."
}
]
},
"repositories" : [
{
"type" : "vsh",
"name" : "openpipeline",
"repo" : "openpipeline",
"tag" : "v4.0.2"
}
],
"viash_version" : "0.9.4",
"source" : "/workdir/root/repo/src",
"target" : "/workdir/root/repo/target",
@@ -3378,12 +3371,20 @@ 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 := 'niche-compass'"
".engines[.type == 'docker'].target_tag := 'v4.0.3'"
],
"keywords" : [
"single-cell",
"multimodal"
],
"license" : "MIT",
"organization" : "vsh",
"links" : {
"repository" : "https://github.com/openpipelines-bio/openpipeline_spatial",
"docker_registry" : "ghcr.io"
"repository" : "https://github.com/openpipelines-bio/openpipeline",
"docker_registry" : "ghcr.io",
"homepage" : "https://openpipelines.bio",
"documentation" : "https://openpipelines.bio/fundamentals",
"issue_tracker" : "https://github.com/openpipelines-bio/openpipeline/issues"
}
}
}'''))
@@ -3908,8 +3909,8 @@ meta["defaults"] = [
directives: readJsonBlob('''{
"container" : {
"registry" : "images.viash-hub.com",
"image" : "vsh/openpipeline_spatial/dataflow/split_h5mu",
"tag" : "niche-compass"
"image" : "vsh/openpipeline/dataflow/split_h5mu",
"tag" : "v4.0.3"
},
"label" : [
"lowcpu",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'dataflow/split_h5mu'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'niche-compass'
version = 'v4.0.3'
description = 'Split the samples of a single modality from a .h5mu (multimodal) sample into seperate .h5mu files based on the values of an .obs column of this modality. \n'
author = 'Dorien Roosen'
}

View File

@@ -1,6 +1,6 @@
name: "split_modalities"
namespace: "dataflow"
version: "v4.0.2"
version: "v4.0.3"
authors:
- name: "Dries Schaumont"
roles:
@@ -190,7 +190,7 @@ engines:
id: "docker"
image: "python:3.12-slim"
target_registry: "images.viash-hub.com"
target_tag: "v4.0.2"
target_tag: "v4.0.3"
namespace_separator: "/"
setup:
- type: "apt"
@@ -231,11 +231,11 @@ build_info:
output: "target/nextflow/dataflow/split_modalities"
executable: "target/nextflow/dataflow/split_modalities/main.nf"
viash_version: "0.9.4"
git_commit: "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62"
git_commit: "7bfad4ea12f87eca59213be3ab08deff67cc4206"
git_remote: "https://github.com/openpipelines-bio/openpipeline"
package_config:
name: "openpipeline"
version: "v4.0.2"
version: "v4.0.3"
summary: "Best-practice workflows for single-cell multi-omics analyses.\n"
description: "OpenPipelines are extensible single cell analysis pipelines for reproducible\
\ and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\
@@ -265,7 +265,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.2'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.3'"
keywords:
- "single-cell"
- "multimodal"

View File

@@ -1,4 +1,4 @@
// split_modalities v4.0.2
// split_modalities v4.0.3
//
// 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" : "split_modalities",
"namespace" : "dataflow",
"version" : "v4.0.2",
"version" : "v4.0.3",
"authors" : [
{
"name" : "Dries Schaumont",
@@ -3280,7 +3280,7 @@ meta = [
"id" : "docker",
"image" : "python:3.12-slim",
"target_registry" : "images.viash-hub.com",
"target_tag" : "v4.0.2",
"target_tag" : "v4.0.3",
"namespace_separator" : "/",
"setup" : [
{
@@ -3336,12 +3336,12 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/nextflow/dataflow/split_modalities",
"viash_version" : "0.9.4",
"git_commit" : "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62",
"git_commit" : "7bfad4ea12f87eca59213be3ab08deff67cc4206",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline"
},
"package_config" : {
"name" : "openpipeline",
"version" : "v4.0.2",
"version" : "v4.0.3",
"summary" : "Best-practice workflows for single-cell multi-omics analyses.\n",
"description" : "OpenPipelines are extensible single cell analysis pipelines for reproducible and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\nIn terms of workflows, the following has been made available, but keep in mind that\nindividual tools and functionality can be executed as standalone components as well.\n\n * Demultiplexing: conversion of raw sequencing data to FASTQ objects.\n * Ingestion: Read mapping and generating a count matrix.\n * Single sample processing: cell filtering and doublet detection.\n * Multisample processing: Count transformation, normalization, QC metric calulations.\n * Integration: Clustering, integration and batch correction using single and multimodal methods.\n * Downstream analysis workflows\n",
"info" : {
@@ -3366,7 +3366,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 := 'v4.0.2'"
".engines[.type == 'docker'].target_tag := 'v4.0.3'"
],
"keywords" : [
"single-cell",
@@ -3865,7 +3865,7 @@ meta["defaults"] = [
"container" : {
"registry" : "images.viash-hub.com",
"image" : "vsh/openpipeline/dataflow/split_modalities",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
},
"label" : [
"singlecpu",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'dataflow/split_modalities'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v4.0.2'
version = 'v4.0.3'
description = 'Split the modalities from a single .h5mu multimodal sample into seperate .h5mu files. \n'
author = 'Dries Schaumont, Robrecht Cannoodt'
}

View File

@@ -1,6 +1,6 @@
name: "pca"
namespace: "dimred"
version: "v4.0.2"
version: "v4.0.3"
authors:
- name: "Dries De Maeyer"
roles:
@@ -240,7 +240,7 @@ engines:
id: "docker"
image: "python:3.12-slim"
target_registry: "images.viash-hub.com"
target_tag: "v4.0.2"
target_tag: "v4.0.3"
namespace_separator: "/"
setup:
- type: "apt"
@@ -276,11 +276,11 @@ build_info:
output: "target/nextflow/dimred/pca"
executable: "target/nextflow/dimred/pca/main.nf"
viash_version: "0.9.4"
git_commit: "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62"
git_commit: "7bfad4ea12f87eca59213be3ab08deff67cc4206"
git_remote: "https://github.com/openpipelines-bio/openpipeline"
package_config:
name: "openpipeline"
version: "v4.0.2"
version: "v4.0.3"
summary: "Best-practice workflows for single-cell multi-omics analyses.\n"
description: "OpenPipelines are extensible single cell analysis pipelines for reproducible\
\ and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\
@@ -310,7 +310,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.2'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.3'"
keywords:
- "single-cell"
- "multimodal"

View File

@@ -1,4 +1,4 @@
// pca v4.0.2
// pca v4.0.3
//
// 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" : "pca",
"namespace" : "dimred",
"version" : "v4.0.2",
"version" : "v4.0.3",
"authors" : [
{
"name" : "Dries De Maeyer",
@@ -3333,7 +3333,7 @@ meta = [
"id" : "docker",
"image" : "python:3.12-slim",
"target_registry" : "images.viash-hub.com",
"target_tag" : "v4.0.2",
"target_tag" : "v4.0.3",
"namespace_separator" : "/",
"setup" : [
{
@@ -3380,12 +3380,12 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/nextflow/dimred/pca",
"viash_version" : "0.9.4",
"git_commit" : "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62",
"git_commit" : "7bfad4ea12f87eca59213be3ab08deff67cc4206",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline"
},
"package_config" : {
"name" : "openpipeline",
"version" : "v4.0.2",
"version" : "v4.0.3",
"summary" : "Best-practice workflows for single-cell multi-omics analyses.\n",
"description" : "OpenPipelines are extensible single cell analysis pipelines for reproducible and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\nIn terms of workflows, the following has been made available, but keep in mind that\nindividual tools and functionality can be executed as standalone components as well.\n\n * Demultiplexing: conversion of raw sequencing data to FASTQ objects.\n * Ingestion: Read mapping and generating a count matrix.\n * Single sample processing: cell filtering and doublet detection.\n * Multisample processing: Count transformation, normalization, QC metric calulations.\n * Integration: Clustering, integration and batch correction using single and multimodal methods.\n * Downstream analysis workflows\n",
"info" : {
@@ -3410,7 +3410,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 := 'v4.0.2'"
".engines[.type == 'docker'].target_tag := 'v4.0.3'"
],
"keywords" : [
"single-cell",
@@ -3933,7 +3933,7 @@ meta["defaults"] = [
"container" : {
"registry" : "images.viash-hub.com",
"image" : "vsh/openpipeline/dimred/pca",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
},
"label" : [
"highcpu",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'dimred/pca'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v4.0.2'
version = 'v4.0.3'
description = 'Computes PCA coordinates, loadings and variance decomposition. Uses the implementation of scikit-learn [Pedregosa11].\n'
author = 'Dries De Maeyer'
}

View File

@@ -1,6 +1,6 @@
name: "umap"
namespace: "dimred"
version: "v4.0.2"
version: "v4.0.3"
authors:
- name: "Dries De Maeyer"
roles:
@@ -294,7 +294,7 @@ engines:
id: "docker"
image: "python:3.12-slim"
target_registry: "images.viash-hub.com"
target_tag: "v4.0.2"
target_tag: "v4.0.3"
namespace_separator: "/"
setup:
- type: "apt"
@@ -330,11 +330,11 @@ build_info:
output: "target/nextflow/dimred/umap"
executable: "target/nextflow/dimred/umap/main.nf"
viash_version: "0.9.4"
git_commit: "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62"
git_commit: "7bfad4ea12f87eca59213be3ab08deff67cc4206"
git_remote: "https://github.com/openpipelines-bio/openpipeline"
package_config:
name: "openpipeline"
version: "v4.0.2"
version: "v4.0.3"
summary: "Best-practice workflows for single-cell multi-omics analyses.\n"
description: "OpenPipelines are extensible single cell analysis pipelines for reproducible\
\ and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\
@@ -364,7 +364,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.2'"
- ".engines[.type == 'docker'].target_tag := 'v4.0.3'"
keywords:
- "single-cell"
- "multimodal"

View File

@@ -1,4 +1,4 @@
// umap v4.0.2
// umap v4.0.3
//
// 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" : "umap",
"namespace" : "dimred",
"version" : "v4.0.2",
"version" : "v4.0.3",
"authors" : [
{
"name" : "Dries De Maeyer",
@@ -3382,7 +3382,7 @@ meta = [
"id" : "docker",
"image" : "python:3.12-slim",
"target_registry" : "images.viash-hub.com",
"target_tag" : "v4.0.2",
"target_tag" : "v4.0.3",
"namespace_separator" : "/",
"setup" : [
{
@@ -3429,12 +3429,12 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/nextflow/dimred/umap",
"viash_version" : "0.9.4",
"git_commit" : "cd7beddfa85b60b543399a9e2554b8e7b8eaaf62",
"git_commit" : "7bfad4ea12f87eca59213be3ab08deff67cc4206",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline"
},
"package_config" : {
"name" : "openpipeline",
"version" : "v4.0.2",
"version" : "v4.0.3",
"summary" : "Best-practice workflows for single-cell multi-omics analyses.\n",
"description" : "OpenPipelines are extensible single cell analysis pipelines for reproducible and large-scale single cell processing using [Viash](https://viash.io) and [Nextflow](https://www.nextflow.io/).\n\nIn terms of workflows, the following has been made available, but keep in mind that\nindividual tools and functionality can be executed as standalone components as well.\n\n * Demultiplexing: conversion of raw sequencing data to FASTQ objects.\n * Ingestion: Read mapping and generating a count matrix.\n * Single sample processing: cell filtering and doublet detection.\n * Multisample processing: Count transformation, normalization, QC metric calulations.\n * Integration: Clustering, integration and batch correction using single and multimodal methods.\n * Downstream analysis workflows\n",
"info" : {
@@ -3459,7 +3459,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 := 'v4.0.2'"
".engines[.type == 'docker'].target_tag := 'v4.0.3'"
],
"keywords" : [
"single-cell",
@@ -3971,7 +3971,7 @@ meta["defaults"] = [
"container" : {
"registry" : "images.viash-hub.com",
"image" : "vsh/openpipeline/dimred/umap",
"tag" : "v4.0.2"
"tag" : "v4.0.3"
},
"label" : [
"highcpu",

Some files were not shown because too many files have changed in this diff Show More