Build branch openpipeline_spatial/v0.1 with version v0.1.1 to openpipeline_spatial on branch v0.1 (2baba3f)

Build pipeline: openpipelines-bio.openpipeline-spatial.0.1.1-5jtw5

Source commit: 2baba3fff0

Source message: merge main
This commit is contained in:
CI
2025-10-02 09:03:43 +00:00
parent 187fb7b5df
commit 15f459882d
93 changed files with 1974 additions and 430 deletions

View File

@@ -1,6 +1,6 @@
name: "from_xenium_to_h5mu"
namespace: "convert"
version: "v0.1.0"
version: "v0.1.1"
authors:
- name: "Dorien Roosen"
roles:
@@ -97,6 +97,8 @@ resources:
is_executable: true
- type: "file"
path: "setup_logger.py"
- type: "file"
path: "unzip_archived_folder.py"
- type: "file"
path: "nextflow_labels.config"
dest: "nextflow_labels.config"
@@ -198,7 +200,7 @@ engines:
id: "docker"
image: "python:3.12-slim"
target_registry: "images.viash-hub.com"
target_tag: "v0.1.0"
target_tag: "v0.1.1"
namespace_separator: "/"
setup:
- type: "apt"
@@ -217,6 +219,10 @@ engines:
nelse: exit(1)\")"
upgrade: true
test_setup:
- type: "apt"
packages:
- "zip"
interactive: false
- type: "python"
user: false
packages:
@@ -233,11 +239,11 @@ build_info:
output: "target/executable/convert/from_xenium_to_h5mu"
executable: "target/executable/convert/from_xenium_to_h5mu/from_xenium_to_h5mu"
viash_version: "0.9.4"
git_commit: "3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
git_commit: "2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
git_remote: "https://github.com/openpipelines-bio/openpipeline_spatial"
package_config:
name: "openpipeline_spatial"
version: "v0.1.0"
version: "v0.1.1"
info:
test_resources:
- type: "s3"
@@ -257,7 +263,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v0.1.0'"
- ".engines[.type == 'docker'].target_tag := 'v0.1.1'"
organization: "vsh"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_spatial"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# from_xenium_to_h5mu v0.1.0
# from_xenium_to_h5mu v0.1.1
#
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
@@ -458,10 +458,10 @@ RUN pip install --upgrade pip && \
LABEL org.opencontainers.image.authors="Dorien Roosen"
LABEL org.opencontainers.image.description="Companion container for running component convert from_xenium_to_h5mu"
LABEL org.opencontainers.image.created="2025-08-25T12:22:56Z"
LABEL org.opencontainers.image.created="2025-10-02T08:37:00Z"
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_spatial"
LABEL org.opencontainers.image.revision="3f8c1506dc59a8c9bb2a3fa6acb40e4e40291e36"
LABEL org.opencontainers.image.version="v0.1.0"
LABEL org.opencontainers.image.revision="2baba3fff0930478c26da7e1bd99b29ee5dd83b3"
LABEL org.opencontainers.image.version="v0.1.1"
VIASHDOCKER
fi
@@ -578,7 +578,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
# ViashHelp: Display helpful explanation about this executable
function ViashHelp {
echo "from_xenium_to_h5mu v0.1.0"
echo "from_xenium_to_h5mu v0.1.1"
echo ""
echo "Converts the output from Xenium to a single .h5mu file, where the count matrix"
echo "is written to the \`rna\` modality."
@@ -670,7 +670,7 @@ while [[ $# -gt 0 ]]; do
shift 1
;;
--version)
echo "from_xenium_to_h5mu v0.1.0"
echo "from_xenium_to_h5mu v0.1.1"
exit
;;
--input)
@@ -839,7 +839,7 @@ if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
# determine docker image id
if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_xenium_to_h5mu:v0.1.0'
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_spatial/convert/from_xenium_to_h5mu:v0.1.1'
fi
# print dockerfile
@@ -1154,7 +1154,9 @@ from pathlib import Path
import scanpy as sc
import pandas as pd
import mudata as mu
import zipfile
import json
import os
## VIASH START
# The following code has been auto-generated by Viash.
@@ -1194,21 +1196,46 @@ dep = {
sys.path.append(meta["resources_dir"])
from setup_logger import setup_logger
from unzip_archived_folder import extract_selected_files_from_zip
logger = setup_logger()
# Expected folder structure (showing only relevant files):
# ├── cell_feature_matrix.h5
# ├── cells.parquet
# ├── experiment.xenium
# ── metrics_summary.csv
input_dir = Path(par["input"])
input_data = {
"count_matrix": input_dir / "cell_feature_matrix.h5",
"cells_metadata": input_dir / "cells.parquet",
"experiment": input_dir / "experiment.xenium",
"metrics_summary": input_dir / "metrics_summary.csv",
}
def _retrieve_input_data(xenium_output_bundle):
# Expected folder structure (showing only relevant files):
# ├── cell_feature_matrix.h5
# ── cells.parquet
# ├── experiment.xenium
# └── metrics_summary.csv
required_file_patterns = {
"count_matrix": "**/cell_feature_matrix.h5",
"cells_metadata": "**/cells.parquet",
"experiment": "**/experiment.xenium",
"metrics_summary": "**/metrics_summary.csv",
}
if zipfile.is_zipfile(xenium_output_bundle):
xenium_output_bundle = extract_selected_files_from_zip(
xenium_output_bundle,
members=[pattern for pattern in required_file_patterns.values()],
)
else:
xenium_output_bundle = Path(xenium_output_bundle)
assert os.path.isdir(xenium_output_bundle), (
"Input is expected to be a (compressed) directory."
)
input_data = {}
for key, pattern in required_file_patterns.items():
file = list(xenium_output_bundle.glob(pattern))
assert len(file) == 1, (
f"Expected exactly one file matching pattern {pattern}, found {len(file)}."
)
input_data[key] = file[0]
return input_data
def _format_cell_id_column(cell_id_column: pd.Series) -> pd.Series:
@@ -1221,9 +1248,7 @@ def _format_cell_id_column(cell_id_column: pd.Series) -> pd.Series:
# Read data from Xenium output bundle
logger.info("Reading input data...")
assert all([file.exists() for file in input_data.values()]), (
f"Not all required input files are found. Make sure that {par['input']} contains {input_data.values()}."
)
input_data = _retrieve_input_data(par["input"])
adata = sc.read_10x_h5(input_data["count_matrix"])
metadata = pd.read_parquet(input_data["cells_metadata"], engine="pyarrow")

View File

@@ -0,0 +1,50 @@
import fnmatch
import zipfile
import tempfile
from pathlib import Path
from typing import Union
def unzip_archived_folder(archived_folder: Union[str, Path]) -> Union[str, Path]:
"""
Extracts a ZIP archive to a temporary directory and returns the path to the extracted folder.
Args:
zip_path (Union[str, Path]): Path to the ZIP archive.
Returns:
extracted_path (Union[str, Path]): Path to the extracted folder inside the temporary directory.
"""
temp_dir = Path(tempfile.TemporaryDirectory().name)
with zipfile.ZipFile(archived_folder, "r") as archive:
archive.extractall(temp_dir)
return temp_dir / Path(archived_folder).stem
def extract_selected_files_from_zip(
zip_path: Union[str, Path], members: list[Union[str, Path]]
) -> Union[str, Path]:
"""
Extracts selected files (supports glob patterns) from a ZIP archive to a temporary directory.
Args:
zip_path (Union[str, Path]): Path to the ZIP archive.
members (list[str]): List of file paths within the archive to extract.
Returns:
Path: Path to the extraction directory.
"""
temp_dir = Path(tempfile.TemporaryDirectory().name)
with zipfile.ZipFile(zip_path, "r") as archive:
all_files = archive.namelist()
selected = set()
for pattern in members:
selected.update(fnmatch.filter(all_files, str(pattern)))
for member in selected:
archive.extract(member, temp_dir)
return temp_dir