2 Commits

Author SHA1 Message Date
CI
0724a8177b Build branch openpipeline_qc/v0.2 with version v0.2.2 to openpipeline_qc on branch v0.2 (9b81d31)
Build pipeline: openpipelines-bio.openpipeline-qc.v0.2.2-vcq67

Source commit: 9b81d310d0

Source message: update version
2026-02-03 16:53:29 +00:00
CI
4ec1652337 Build branch openpipeline_qc/v0.2 with version v0.2.1 to openpipeline_qc on branch v0.2 (240a6de)
Build pipeline: openpipelines-bio.openpipeline-qc.v0.2.1-nspxk

Source commit: 240a6de624

Source message: update changelog
2026-02-02 17:37:37 +00:00
33 changed files with 1758 additions and 276 deletions

View File

@@ -1,5 +1,21 @@
# openpipeline_qc 0.2.1
## BUG FIX
* Surface updated CosMx and Visium features.
# openpipeline_qc 0.2.2
## BUG FIX
* `src/ingestion_qc/h5mu_to_qc_json`: Use float32 instead of float16 for CosMx staining metrics to prevent overflow to infinity (PR #17).
# openpipeline_qc 0.2.0
## NEW FEATURES
* Add support for CosMx data in the QC Reporting workflow (PR #12).
## MINOR CHANGES
* Added support for Visium data ingestion and QC reporting (PR #16).

View File

@@ -1,5 +1,5 @@
viash_version: 0.9.4
version: v0.2.0
version: v0.2.2
source: src
target: target
name: openpipeline_qc

22
inspect_visium.py Normal file
View File

@@ -0,0 +1,22 @@
import mudata as mu
import pandas as pd
def inspect_h5mu(filepath, name):
print(f"--- Inspecting {name} ({filepath}) ---")
try:
mdata = mu.read_h5mu(filepath)
rna = mdata.mod['rna']
print(f"Obs columns ({len(rna.obs.columns)}):")
print(rna.obs.columns.tolist())
print(f"\nObs head:")
print(rna.obs.head())
print(f"\nObsm keys: {list(rna.obsm.keys())}")
except Exception as e:
print(f"Error reading {filepath}: {e}")
print("\n")
inspect_h5mu("resources_test/spatial_qc_sample_data/visium_tiny.qc.h5mu", "Visium")

View File

@@ -147,6 +147,14 @@ viash run src/ingestion_qc/h5mu_to_qc_json/config.vsh.yaml --engine docker -- \
--output "$OUT_DIR_SPATIAL"/xenium_dataset.json \
--output_reporting_json "$OUT_DIR_SPATIAL"/xenium_report_structure.json
viash run src/ingestion_qc/h5mu_to_qc_json/config.vsh.yaml --engine docker -- \
--input "$OUT_DIR_SPATIAL"/Lung5_Rep2_tiny.qc.h5mu \
--input "$OUT_DIR_SPATIAL"/Lung5_Rep2_tiny.qc.h5mu \
--ingestion_method cosmx \
--min_num_nonzero_vars 1 \
--output "$OUT_DIR_SPATIAL"/cosmx_dataset.json \
--output_reporting_json "$OUT_DIR_SPATIAL"/cosmx_report_structure.json
viash run src/ingestion_qc/h5mu_to_qc_json/config.vsh.yaml --engine docker -- \
--input "$OUT_DIR_SPATIAL"/visium_tiny.qc.h5mu \
--input "$OUT_DIR_SPATIAL"/visium_tiny.qc.h5mu \

View File

@@ -34,6 +34,7 @@ argument_groups:
choices:
- cellranger_multi
- xenium
- cosmx
- visium
description: Method that was used to ingest the data - this will define the structure of the report that is generated.
- name: --obs_sample_id
@@ -133,7 +134,41 @@ argument_groups:
description: The key in the h5mu .obs field that contains the number of control codewords.
default: control_codeword_counts
# - name: Options for CosMx reports
- name: Options for CosMx reports
arguments:
- name: --obs_area
type: string
description: The key in the h5mu .obs field that contains the cell area.
default: Area
- name: --obs_aspect_ratio
type: string
description: The key in the h5mu .obs field that contains the aspect ratio.
default: AspectRatio
- name: --obs_dapi_stain
type: string
multiple: true
description: The keys in the h5mu .obs field that contains the DAPI stain intensity.
default: [Mean.DAPI, Max.DAPI]
- name: --obs_membrane_stain
type: string
multiple: true
description: The keys in the h5mu .obs field that contains the membrane stain intensity.
default: [Mean.MembraneStain, Max.MembraneStain]
- name: --obs_panck_stain
type: string
multiple: true
description: The keys in the h5mu .obs field that contains the PanCK stain intensity.
default: [Mean.PanCK, Max.PanCK]
- name: --obs_cd45_stain
type: string
multiple: true
description: The keys in the h5mu .obs field that contains the CD45 stain intensity.
default: [Mean.CD45, Max.CD45]
- name: --obs_cd3_stain
type: string
multiple: true
description: The keys in the h5mu .obs field that contains the CD3 stain intensity.
default: [Mean.CD3, Max.CD3]
resources:
- type: python_script

View File

@@ -0,0 +1,211 @@
{
"categories": [
{
"name": "Sample QC",
"key": "sample_summary_stats",
"additionalAxes": false,
"defaultFilters": []
},
{
"name": "Cell RNA QC",
"key": "cell_rna_stats",
"additionalAxes": true,
"defaultFilters": [
{
"type": "histogram",
"visualizationType": "histogram",
"field": "total_counts",
"label": "Total UMI per cell",
"description": "Total number of RNA molecules detected per cell. Low values typically indicate empty droplets or low-quality cells that should be filtered out.",
"cutoffMin": null,
"cutoffMax": null,
"zoomMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "num_nonzero_vars",
"label": "Number of non-zero genes per cell",
"description": "Count of unique genes detected in each cell. Low gene counts often indicate poor-quality cells.",
"cutoffMin": null,
"cutoffMax": null,
"zoomMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "fraction_mitochondrial",
"label": "Fraction UMI of mitochondrial genes per cell",
"description": "Proportion of cell's RNA from mitochondrial genes.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "fraction_ribosomal",
"label": "Fraction UMI of ribosomal genes per cell",
"description": "Proportion of cell's RNA from ribosomal protein genes. Extreme values may indicate stress responses or cell cycle abnormalities.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Area",
"label": "Cell Area",
"description": "Area of the segmented cells.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "AspectRatio",
"label": "Aspect Ratio",
"description": "Aspect ratio of the segmented cells.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.DAPI",
"label": "Mean DAPI Intensity",
"description": "Mean intensity of DAPI stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.MembraneStain",
"label": "Mean Membrane Stain Intensity",
"description": "Mean intensity of Membrane stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.PanCK",
"label": "Mean PanCK Intensity",
"description": "Mean intensity of PanCK stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.CD45",
"label": "Mean CD45 Intensity",
"description": "Mean intensity of CD45 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.CD3",
"label": "Mean CD3 Intensity",
"description": "Mean intensity of CD3 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.DAPI",
"label": "Max DAPI Intensity",
"description": "Maximum intensity of DAPI stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.MembraneStain",
"label": "Max Membrane Stain Intensity",
"description": "Maximum intensity of Membrane stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.PanCK",
"label": "Max PanCK Intensity",
"description": "Maximum intensity of PanCK stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.CD45",
"label": "Max CD45 Intensity",
"description": "Maximum intensity of CD45 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.CD3",
"label": "Max CD3 Intensity",
"description": "Maximum intensity of CD3 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
}
]
}
]
}

View File

@@ -39,7 +39,14 @@ par = {
"obs_x_coord": "x_coord",
"obs_y_coord": "y_coord",
"obs_control_probe_counts": "control_probe_counts",
"obs_control_codeword_counts": "control_codeword_counts"
"obs_control_codeword_counts": "control_codeword_counts",
"obs_area": "Area",
"obs_aspect_ratio": "AspectRatio",
"obs_dapi_stain": ["Mean.DAPI", "Max.DAPI"],
"obs_membrane_stain": ["Mean.MembraneStain", "Max.MembraneStain"],
"obs_panck_stain": ["Mean.PanCK", "Max.PanCK"],
"obs_cd45_stain": ["Mean.CD45", "Max.CD45"],
"obs_cd3_stain": ["Mean.CD3", "Max.CD3"],
}
meta = {
"resources_dir": os.path.abspath("src/ingestion_qc/h5mu_to_qc_json"),
@@ -56,6 +63,11 @@ from setup_logger import setup_logger
logger = setup_logger()
par["obs_cellbender"] = {} if not par["obs_cellbender"] else par["obs_cellbender"]
par["obs_dapi_stain"] = [] if not par["obs_dapi_stain"] else par["obs_dapi_stain"]
par["obs_membrane_stain"] = [] if not par["obs_membrane_stain"] else par["obs_membrane_stain"]
par["obs_panck_stain"] = [] if not par["obs_panck_stain"] else par["obs_panck_stain"]
par["obs_cd45_stain"] = [] if not par["obs_cd45_stain"] else par["obs_cd45_stain"]
par["obs_cd3_stain"] = [] if not par["obs_cd3_stain"] else par["obs_cd3_stain"]
def transform_df(df):
@@ -272,6 +284,60 @@ def generate_visium_stats(mod_obs, sample_id, required_keys):
return cell_rna_stats
def format_cosmx_columns(mod_obs):
cosmx_obs_keys = [par["obs_area"], par["obs_aspect_ratio"]]
# Add multiple keys
for key_list in [par["obs_dapi_stain"], par["obs_membrane_stain"], par["obs_panck_stain"],
par["obs_cd45_stain"], par["obs_cd3_stain"]]:
if key_list:
cosmx_obs_keys.extend(key_list)
# Check if keys are present
check_optional_obs_keys(mod_obs, cosmx_obs_keys, "CosMx metrics.")
# Filter only existing keys
cosmx_formatted_columns = [key for key in cosmx_obs_keys if key in mod_obs]
# Add coordinates
cosmx_formatted_columns.extend(["x_coord", "y_coord"])
for key in cosmx_formatted_columns:
if key in mod_obs:
if not pd.api.types.is_float_dtype(mod_obs[key]):
try:
mod_obs[key] = mod_obs[key].astype("float32")
except ValueError:
logger.warning(f"Could not convert column {key} to a float dtype.")
return mod_obs, cosmx_formatted_columns
def generate_cosmx_stats(mod_obs, sample_id, required_keys):
# Format required columns
mod_obs = format_required_columns(required_keys, mod_obs)
# Format cosmx-specific columns
mod_obs, cosmx_formatted_columns = format_cosmx_columns(mod_obs)
# Fetch and format all categorical columns for grouping
metadata_obs_keys, mod_obs = format_categorical_columns(mod_obs)
# Create cell RNA stats dataframe
cell_rna_stats = pd.DataFrame(
{
"sample_id": pd.Categorical(sample_id),
**{key: mod_obs[key] for key in required_keys},
**{key: mod_obs[key] for key in cosmx_formatted_columns},
**{key: mod_obs[key] for key in metadata_obs_keys}
}
)
return cell_rna_stats
def concatenate_dataframes(dfs):
'''Concatenates a list of dataframes into a single dataframe, preserving categorical columns.'''
df = pd.concat(dfs, ignore_index=True)
@@ -311,7 +377,7 @@ def main(par):
barcodes_original_count = mod_obs.shape[0]
# Add coordinates to obs before filtering
if par["ingestion_method"] == "xenium" or par["ingestion_method"] == "visium":
if par["ingestion_method"] == "xenium" or par["ingestion_method"] == "visium" or par["ingestion_method"] == "cosmx":
mod_obs["x_coord"] = mod_obsm["spatial"][:, 0]
mod_obs["y_coord"] = mod_obsm["spatial"][:, 1]
@@ -368,6 +434,9 @@ def main(par):
if par["ingestion_method"] == "visium":
cell_rna_stats = generate_visium_stats(mod_obs, sample_id, required_keys)
if par["ingestion_method"] == "cosmx":
cell_rna_stats = generate_cosmx_stats(mod_obs, sample_id, required_keys)
cell_stats_dfs.append(cell_rna_stats)
sample_stats_dfs.append(sample_summary_stats)
@@ -403,7 +472,8 @@ def main(par):
report_structures = {
"cellranger_multi": os.path.join(meta["resources_dir"], "report_structure/cellranger.json"),
"xenium": os.path.join(meta["resources_dir"], "report_structure/xenium.json"),
"visium": os.path.join(meta["resources_dir"], "report_structure/visium.json")
"visium": os.path.join(meta["resources_dir"], "report_structure/visium.json"),
"cosmx": os.path.join(meta["resources_dir"], "report_structure/cosmx.json")
}
logger.info(f"Writing output report structure json to {par['output_reporting_json']}")

View File

@@ -140,5 +140,43 @@ def test_xenium_execution(run_component, tmp_path):
assert {"name", "dtype", "data"}.issubset(col.keys())
def test_cosmx_execution(run_component, tmp_path):
output_json_path = tmp_path / "output.json"
output_reporting_json_path = tmp_path / "output_reporting.json"
run_component(
[
"--input", meta["resources_dir"] + "/resources_test/spatial_qc_sample_data/Lung5_Rep2_tiny.qc.h5mu",
"--ingestion_method", "cosmx",
"--min_num_nonzero_vars", "1",
"--output", output_json_path,
"--output_reporting_json", output_reporting_json_path
]
)
assert os.path.exists(output_json_path), "Output file was not created"
with open(output_json_path, "r") as f:
output_json_dict = json.load(f)
assert output_json_dict.keys() == {"cell_rna_stats", "sample_summary_stats"}
assert "metrics_cellranger_stats" not in output_json_dict.keys()
column_names_cell = [col["name"] for col in output_json_dict["cell_rna_stats"]["columns"]]
expected_column_names = [
"sample_id", "total_counts", "num_nonzero_vars",
"fraction_mitochondrial", "fraction_ribosomal",
"Area", "AspectRatio",
"Mean.DAPI", "Mean.MembraneStain",
"x_coord", "y_coord", "fov"
]
assert np.all([column in column_names_cell for column in expected_column_names])
for key in output_json_dict.keys():
assert output_json_dict[key].keys() == {"num_rows", "num_cols", "min_total_counts", "min_num_nonzero_vars", "columns"}
for col in output_json_dict[key]["columns"]:
assert {"name", "dtype", "data"}.issubset(col.keys())
if __name__ == "__main__":
sys.exit(pytest.main([__file__]))

View File

@@ -35,6 +35,7 @@ argument_groups:
choices:
- cellranger_multi
- xenium
- cosmx
- visium
- name: --sample_metadata
type: file
@@ -103,6 +104,42 @@ argument_groups:
required: false
description: Number of epochs to train cellbender.
default: 150
- name: Options for CosMx reports
arguments:
- name: --obs_area
type: string
description: The key in the h5mu .obs field that contains the cell area.
default: Area
- name: --obs_aspect_ratio
type: string
description: The key in the h5mu .obs field that contains the aspect ratio.
default: AspectRatio
- name: --obs_dapi_stain
type: string
multiple: true
description: The keys in the h5mu .obs field that contains the DAPI stain intensity.
default: [Mean.DAPI, Max.DAPI]
- name: --obs_membrane_stain
type: string
multiple: true
description: The keys in the h5mu .obs field that contains the membrane stain intensity.
default: [Mean.MembraneStain, Max.MembraneStain]
- name: --obs_panck_stain
type: string
multiple: true
description: The keys in the h5mu .obs field that contains the PanCK stain intensity.
default: [Mean.PanCK, Max.PanCK]
- name: --obs_cd45_stain
type: string
multiple: true
description: The keys in the h5mu .obs field that contains the CD45 stain intensity.
default: [Mean.CD45, Max.CD45]
- name: --obs_cd3_stain
type: string
multiple: true
description: The keys in the h5mu .obs field that contains the CD3 stain intensity.
default: [Mean.CD3, Max.CD3]
- name: Outputs
arguments:
@@ -137,6 +174,7 @@ test_resources:
entrypoint: test_xenium
- type: nextflow_script
path: test.nf
entrypoint: test_cosmx
entrypoint: test_visium
dependencies:

View File

@@ -35,10 +35,16 @@ nextflow run . \
-entry test_multiple_reports \
-c src/configs/labels_ci.config \
-resume
nextflow run . \
-main-script src/workflows/generate_qc_report/test.nf \
-profile docker,no_publish,local \
-entry test_visium \
-c src/configs/labels_ci.config \
-resume
nextflow run . \
-main-script src/workflows/generate_qc_report/test.nf \
-profile docker,no_publish,local \
-entry test_cosmx \
-c src/configs/labels_ci.config \
-resume

View File

@@ -154,7 +154,14 @@ workflow run_wf {
ingestion_method: "ingestion_method",
obs_metadata: "obs_metadata",
min_total_counts: "min_total_counts",
min_num_nonzero_vars: "min_num_nonzero_vars"
min_num_nonzero_vars: "min_num_nonzero_vars",
obs_area: "obs_area",
obs_aspect_ratio: "obs_aspect_ratio",
obs_dapi_stain: "obs_dapi_stain",
obs_membrane_stain: "obs_membrane_stain",
obs_panck_stain: "obs_panck_stain",
obs_cd45_stain: "obs_cd45_stain",
obs_cd3_stain: "obs_cd3_stain",
],
args: [
obs_sample_id: "sample_id",

View File

@@ -266,3 +266,48 @@ workflow test_visium {
"Output: $output"
}
}
workflow test_cosmx {
resources_test_file = file(params.resources_test)
output_ch = Channel.fromList([
[
id: "sample_one",
input: resources_test_file.resolve("spatial_qc_sample_data/Lung5_Rep2_tiny.qc.h5mu"),
run_cellbender: false,
ingestion_method: "cosmx",
min_num_nonzero_vars: "1",
output_html: "report.html",
publish_dir: "test_out"
],
[
id: "sample_two",
input: resources_test_file.resolve("spatial_qc_sample_data/Lung5_Rep2_tiny.qc.h5mu"),
ingestion_method: "cosmx",
min_num_nonzero_vars: "1",
run_cellbender: false,
output_html: "report.html",
publish_dir: "test_out"
]
])
| map{ state -> [state.id, state] }
| generate_qc_report
| view { output ->
assert output.size() == 2 : "Outputs should contain two elements; [id, state]"
def id = output[0]
def state = output [1]
assert id == "combined": "Output ID should be `combined`"
assert state instanceof Map : "State should be a map. Found: ${state}"
assert state.containsKey("output_qc_report"): "Output should contain key `output_qc_report`"
assert state.containsKey("output_processed_h5mu"): "Output should contain key `output_processed_h5mu`"
assert state.output_qc_report.size() == 1 : "Expected exactly one output HTML file to be generated"
assert state.output_qc_report.every { it.isFile()} : "All output HTML report files should exist"
assert state.output_processed_h5mu.isDirectory() : "Output directory should exist"
def files = state.output_processed_h5mu.listFiles().findAll { it.isFile() }
assert files.size() == 2 : "Output directory should contain exactly 2 files, but found ${files.size()} files"
"Output: $output"
}
}

View File

@@ -1,6 +1,6 @@
name: "h5mu_to_qc_json"
namespace: "ingestion_qc"
version: "v0.2.0"
version: "v0.2.2"
authors:
- name: "Jakub Majercik"
roles:
@@ -87,6 +87,7 @@ argument_groups:
choices:
- "cellranger_multi"
- "xenium"
- "cosmx"
- "visium"
direction: "input"
multiple: false
@@ -293,6 +294,84 @@ argument_groups:
direction: "input"
multiple: false
multiple_sep: ";"
- name: "Options for CosMx reports"
arguments:
- type: "string"
name: "--obs_area"
description: "The key in the h5mu .obs field that contains the cell area."
info: null
default:
- "Area"
required: false
direction: "input"
multiple: false
multiple_sep: ";"
- type: "string"
name: "--obs_aspect_ratio"
description: "The key in the h5mu .obs field that contains the aspect ratio."
info: null
default:
- "AspectRatio"
required: false
direction: "input"
multiple: false
multiple_sep: ";"
- type: "string"
name: "--obs_dapi_stain"
description: "The keys in the h5mu .obs field that contains the DAPI stain intensity."
info: null
default:
- "Mean.DAPI"
- "Max.DAPI"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_membrane_stain"
description: "The keys in the h5mu .obs field that contains the membrane stain\
\ intensity."
info: null
default:
- "Mean.MembraneStain"
- "Max.MembraneStain"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_panck_stain"
description: "The keys in the h5mu .obs field that contains the PanCK stain intensity."
info: null
default:
- "Mean.PanCK"
- "Max.PanCK"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_cd45_stain"
description: "The keys in the h5mu .obs field that contains the CD45 stain intensity."
info: null
default:
- "Mean.CD45"
- "Max.CD45"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_cd3_stain"
description: "The keys in the h5mu .obs field that contains the CD3 stain intensity."
info: null
default:
- "Mean.CD3"
- "Max.CD3"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
resources:
- type: "python_script"
path: "script.py"
@@ -409,7 +488,7 @@ engines:
id: "docker"
image: "python:3.12-slim"
target_registry: "images.viash-hub.com"
target_tag: "v0.2.0"
target_tag: "v0.2.2"
namespace_separator: "/"
setup:
- type: "apt"
@@ -448,11 +527,11 @@ build_info:
output: "target/_private/executable/ingestion_qc/h5mu_to_qc_json"
executable: "target/_private/executable/ingestion_qc/h5mu_to_qc_json/h5mu_to_qc_json"
viash_version: "0.9.4"
git_commit: "a4ab5f509f731422ffc79b739a89b9d11fb4e440"
git_commit: "9b81d310d031b120755e39001cc40f8ec51bc7c2"
git_remote: "https://github.com/openpipelines-bio/openpipeline_qc"
package_config:
name: "openpipeline_qc"
version: "v0.2.0"
version: "v0.2.2"
info:
test_resources:
- type: "s3"
@@ -477,7 +556,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.0'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.2'"
organization: "vsh"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_qc"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# h5mu_to_qc_json v0.2.0
# h5mu_to_qc_json v0.2.2
#
# 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
@@ -461,10 +461,10 @@ RUN pip install --upgrade pip && \
LABEL org.opencontainers.image.authors="Jakub Majercik, Dorien Roosen, Robrecht Cannoodt, Weiwei Schultz"
LABEL org.opencontainers.image.description="Companion container for running component ingestion_qc h5mu_to_qc_json"
LABEL org.opencontainers.image.created="2026-02-02T16:26:04Z"
LABEL org.opencontainers.image.created="2026-02-03T16:37:26Z"
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_qc"
LABEL org.opencontainers.image.revision="a4ab5f509f731422ffc79b739a89b9d11fb4e440"
LABEL org.opencontainers.image.version="v0.2.0"
LABEL org.opencontainers.image.revision="9b81d310d031b120755e39001cc40f8ec51bc7c2"
LABEL org.opencontainers.image.version="v0.2.2"
VIASHDOCKER
fi
@@ -581,7 +581,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
# ViashHelp: Display helpful explanation about this executable
function ViashHelp {
echo "h5mu_to_qc_json v0.2.0"
echo "h5mu_to_qc_json v0.2.2"
echo ""
echo "Takes H5MU files that have been ingested by CellRanger, Xenium or CosMx and"
echo "processed by the QC workflow, and generates:"
@@ -601,7 +601,7 @@ function ViashHelp {
echo ""
echo " --ingestion_method"
echo " type: string, required parameter"
echo " choices: [ cellranger_multi, xenium, visium ]"
echo " choices: [ cellranger_multi, xenium, cosmx, visium ]"
echo " Method that was used to ingest the data - this will define the structure"
echo " of the report that is generated."
echo ""
@@ -705,6 +705,43 @@ function ViashHelp {
echo " The key in the h5mu .obs field that contains the number of control"
echo " codewords."
echo ""
echo "Options for CosMx reports:"
echo " --obs_area"
echo " type: string"
echo " default: Area"
echo " The key in the h5mu .obs field that contains the cell area."
echo ""
echo " --obs_aspect_ratio"
echo " type: string"
echo " default: AspectRatio"
echo " The key in the h5mu .obs field that contains the aspect ratio."
echo ""
echo " --obs_dapi_stain"
echo " type: string, multiple values allowed"
echo " default: Mean.DAPI;Max.DAPI"
echo " The keys in the h5mu .obs field that contains the DAPI stain intensity."
echo ""
echo " --obs_membrane_stain"
echo " type: string, multiple values allowed"
echo " default: Mean.MembraneStain;Max.MembraneStain"
echo " The keys in the h5mu .obs field that contains the membrane stain"
echo " intensity."
echo ""
echo " --obs_panck_stain"
echo " type: string, multiple values allowed"
echo " default: Mean.PanCK;Max.PanCK"
echo " The keys in the h5mu .obs field that contains the PanCK stain intensity."
echo ""
echo " --obs_cd45_stain"
echo " type: string, multiple values allowed"
echo " default: Mean.CD45;Max.CD45"
echo " The keys in the h5mu .obs field that contains the CD45 stain intensity."
echo ""
echo " --obs_cd3_stain"
echo " type: string, multiple values allowed"
echo " default: Mean.CD3;Max.CD3"
echo " The keys in the h5mu .obs field that contains the CD3 stain intensity."
echo ""
echo "Viash built in Computational Requirements:"
echo " ---cpus=INT"
echo " Number of CPUs to use"
@@ -752,7 +789,7 @@ while [[ $# -gt 0 ]]; do
shift 1
;;
--version)
echo "h5mu_to_qc_json v0.2.0"
echo "h5mu_to_qc_json v0.2.2"
exit
;;
--input)
@@ -1004,6 +1041,113 @@ while [[ $# -gt 0 ]]; do
VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS=$(ViashRemoveFlags "$1")
shift 1
;;
--obs_area)
[ -n "$VIASH_PAR_OBS_AREA" ] && ViashError Bad arguments for option \'--obs_area\': \'$VIASH_PAR_OBS_AREA\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
VIASH_PAR_OBS_AREA="$2"
[ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_area. Use "--help" to get more information on the parameters. && exit 1
shift 2
;;
--obs_area=*)
[ -n "$VIASH_PAR_OBS_AREA" ] && ViashError Bad arguments for option \'--obs_area=*\': \'$VIASH_PAR_OBS_AREA\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
VIASH_PAR_OBS_AREA=$(ViashRemoveFlags "$1")
shift 1
;;
--obs_aspect_ratio)
[ -n "$VIASH_PAR_OBS_ASPECT_RATIO" ] && ViashError Bad arguments for option \'--obs_aspect_ratio\': \'$VIASH_PAR_OBS_ASPECT_RATIO\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
VIASH_PAR_OBS_ASPECT_RATIO="$2"
[ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_aspect_ratio. Use "--help" to get more information on the parameters. && exit 1
shift 2
;;
--obs_aspect_ratio=*)
[ -n "$VIASH_PAR_OBS_ASPECT_RATIO" ] && ViashError Bad arguments for option \'--obs_aspect_ratio=*\': \'$VIASH_PAR_OBS_ASPECT_RATIO\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
VIASH_PAR_OBS_ASPECT_RATIO=$(ViashRemoveFlags "$1")
shift 1
;;
--obs_dapi_stain)
if [ -z "$VIASH_PAR_OBS_DAPI_STAIN" ]; then
VIASH_PAR_OBS_DAPI_STAIN="$2"
else
VIASH_PAR_OBS_DAPI_STAIN="$VIASH_PAR_OBS_DAPI_STAIN;""$2"
fi
[ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_dapi_stain. Use "--help" to get more information on the parameters. && exit 1
shift 2
;;
--obs_dapi_stain=*)
if [ -z "$VIASH_PAR_OBS_DAPI_STAIN" ]; then
VIASH_PAR_OBS_DAPI_STAIN=$(ViashRemoveFlags "$1")
else
VIASH_PAR_OBS_DAPI_STAIN="$VIASH_PAR_OBS_DAPI_STAIN;"$(ViashRemoveFlags "$1")
fi
shift 1
;;
--obs_membrane_stain)
if [ -z "$VIASH_PAR_OBS_MEMBRANE_STAIN" ]; then
VIASH_PAR_OBS_MEMBRANE_STAIN="$2"
else
VIASH_PAR_OBS_MEMBRANE_STAIN="$VIASH_PAR_OBS_MEMBRANE_STAIN;""$2"
fi
[ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_membrane_stain. Use "--help" to get more information on the parameters. && exit 1
shift 2
;;
--obs_membrane_stain=*)
if [ -z "$VIASH_PAR_OBS_MEMBRANE_STAIN" ]; then
VIASH_PAR_OBS_MEMBRANE_STAIN=$(ViashRemoveFlags "$1")
else
VIASH_PAR_OBS_MEMBRANE_STAIN="$VIASH_PAR_OBS_MEMBRANE_STAIN;"$(ViashRemoveFlags "$1")
fi
shift 1
;;
--obs_panck_stain)
if [ -z "$VIASH_PAR_OBS_PANCK_STAIN" ]; then
VIASH_PAR_OBS_PANCK_STAIN="$2"
else
VIASH_PAR_OBS_PANCK_STAIN="$VIASH_PAR_OBS_PANCK_STAIN;""$2"
fi
[ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_panck_stain. Use "--help" to get more information on the parameters. && exit 1
shift 2
;;
--obs_panck_stain=*)
if [ -z "$VIASH_PAR_OBS_PANCK_STAIN" ]; then
VIASH_PAR_OBS_PANCK_STAIN=$(ViashRemoveFlags "$1")
else
VIASH_PAR_OBS_PANCK_STAIN="$VIASH_PAR_OBS_PANCK_STAIN;"$(ViashRemoveFlags "$1")
fi
shift 1
;;
--obs_cd45_stain)
if [ -z "$VIASH_PAR_OBS_CD45_STAIN" ]; then
VIASH_PAR_OBS_CD45_STAIN="$2"
else
VIASH_PAR_OBS_CD45_STAIN="$VIASH_PAR_OBS_CD45_STAIN;""$2"
fi
[ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_cd45_stain. Use "--help" to get more information on the parameters. && exit 1
shift 2
;;
--obs_cd45_stain=*)
if [ -z "$VIASH_PAR_OBS_CD45_STAIN" ]; then
VIASH_PAR_OBS_CD45_STAIN=$(ViashRemoveFlags "$1")
else
VIASH_PAR_OBS_CD45_STAIN="$VIASH_PAR_OBS_CD45_STAIN;"$(ViashRemoveFlags "$1")
fi
shift 1
;;
--obs_cd3_stain)
if [ -z "$VIASH_PAR_OBS_CD3_STAIN" ]; then
VIASH_PAR_OBS_CD3_STAIN="$2"
else
VIASH_PAR_OBS_CD3_STAIN="$VIASH_PAR_OBS_CD3_STAIN;""$2"
fi
[ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_cd3_stain. Use "--help" to get more information on the parameters. && exit 1
shift 2
;;
--obs_cd3_stain=*)
if [ -z "$VIASH_PAR_OBS_CD3_STAIN" ]; then
VIASH_PAR_OBS_CD3_STAIN=$(ViashRemoveFlags "$1")
else
VIASH_PAR_OBS_CD3_STAIN="$VIASH_PAR_OBS_CD3_STAIN;"$(ViashRemoveFlags "$1")
fi
shift 1
;;
---engine)
VIASH_ENGINE_ID="$2"
shift 2
@@ -1092,7 +1236,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_qc/ingestion_qc/h5mu_to_qc_json:v0.2.0'
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_qc/ingestion_qc/h5mu_to_qc_json:v0.2.2'
fi
# print dockerfile
@@ -1266,6 +1410,27 @@ fi
if [ -z ${VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS+x} ]; then
VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS="control_codeword_counts"
fi
if [ -z ${VIASH_PAR_OBS_AREA+x} ]; then
VIASH_PAR_OBS_AREA="Area"
fi
if [ -z ${VIASH_PAR_OBS_ASPECT_RATIO+x} ]; then
VIASH_PAR_OBS_ASPECT_RATIO="AspectRatio"
fi
if [ -z ${VIASH_PAR_OBS_DAPI_STAIN+x} ]; then
VIASH_PAR_OBS_DAPI_STAIN="Mean.DAPI;Max.DAPI"
fi
if [ -z ${VIASH_PAR_OBS_MEMBRANE_STAIN+x} ]; then
VIASH_PAR_OBS_MEMBRANE_STAIN="Mean.MembraneStain;Max.MembraneStain"
fi
if [ -z ${VIASH_PAR_OBS_PANCK_STAIN+x} ]; then
VIASH_PAR_OBS_PANCK_STAIN="Mean.PanCK;Max.PanCK"
fi
if [ -z ${VIASH_PAR_OBS_CD45_STAIN+x} ]; then
VIASH_PAR_OBS_CD45_STAIN="Mean.CD45;Max.CD45"
fi
if [ -z ${VIASH_PAR_OBS_CD3_STAIN+x} ]; then
VIASH_PAR_OBS_CD3_STAIN="Mean.CD3;Max.CD3"
fi
# check whether required files exist
if [ ! -z "$VIASH_PAR_INPUT" ]; then
@@ -1369,7 +1534,7 @@ fi
# check whether value is belongs to a set of choices
if [ ! -z "$VIASH_PAR_INGESTION_METHOD" ]; then
VIASH_PAR_INGESTION_METHOD_CHOICES=("cellranger_multi;xenium;visium")
VIASH_PAR_INGESTION_METHOD_CHOICES=("cellranger_multi;xenium;cosmx;visium")
IFS=';'
set -f
if ! [[ ";${VIASH_PAR_INGESTION_METHOD_CHOICES[*]};" =~ ";$VIASH_PAR_INGESTION_METHOD;" ]]; then
@@ -1520,7 +1685,14 @@ par = {
'obs_x_coord': $( if [ ! -z ${VIASH_PAR_OBS_X_COORD+x} ]; then echo "r'${VIASH_PAR_OBS_X_COORD//\'/\'\"\'\"r\'}'"; else echo None; fi ),
'obs_y_coord': $( if [ ! -z ${VIASH_PAR_OBS_Y_COORD+x} ]; then echo "r'${VIASH_PAR_OBS_Y_COORD//\'/\'\"\'\"r\'}'"; else echo None; fi ),
'obs_control_probe_counts': $( if [ ! -z ${VIASH_PAR_OBS_CONTROL_PROBE_COUNTS+x} ]; then echo "r'${VIASH_PAR_OBS_CONTROL_PROBE_COUNTS//\'/\'\"\'\"r\'}'"; else echo None; fi ),
'obs_control_codeword_counts': $( if [ ! -z ${VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS+x} ]; then echo "r'${VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS//\'/\'\"\'\"r\'}'"; else echo None; fi )
'obs_control_codeword_counts': $( if [ ! -z ${VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS+x} ]; then echo "r'${VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS//\'/\'\"\'\"r\'}'"; else echo None; fi ),
'obs_area': $( if [ ! -z ${VIASH_PAR_OBS_AREA+x} ]; then echo "r'${VIASH_PAR_OBS_AREA//\'/\'\"\'\"r\'}'"; else echo None; fi ),
'obs_aspect_ratio': $( if [ ! -z ${VIASH_PAR_OBS_ASPECT_RATIO+x} ]; then echo "r'${VIASH_PAR_OBS_ASPECT_RATIO//\'/\'\"\'\"r\'}'"; else echo None; fi ),
'obs_dapi_stain': $( if [ ! -z ${VIASH_PAR_OBS_DAPI_STAIN+x} ]; then echo "r'${VIASH_PAR_OBS_DAPI_STAIN//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
'obs_membrane_stain': $( if [ ! -z ${VIASH_PAR_OBS_MEMBRANE_STAIN+x} ]; then echo "r'${VIASH_PAR_OBS_MEMBRANE_STAIN//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
'obs_panck_stain': $( if [ ! -z ${VIASH_PAR_OBS_PANCK_STAIN+x} ]; then echo "r'${VIASH_PAR_OBS_PANCK_STAIN//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
'obs_cd45_stain': $( if [ ! -z ${VIASH_PAR_OBS_CD45_STAIN+x} ]; then echo "r'${VIASH_PAR_OBS_CD45_STAIN//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
'obs_cd3_stain': $( if [ ! -z ${VIASH_PAR_OBS_CD3_STAIN+x} ]; then echo "r'${VIASH_PAR_OBS_CD3_STAIN//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi )
}
meta = {
'name': $( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "r'${VIASH_META_NAME//\'/\'\"\'\"r\'}'"; else echo None; fi ),
@@ -1554,6 +1726,11 @@ from setup_logger import setup_logger
logger = setup_logger()
par["obs_cellbender"] = {} if not par["obs_cellbender"] else par["obs_cellbender"]
par["obs_dapi_stain"] = [] if not par["obs_dapi_stain"] else par["obs_dapi_stain"]
par["obs_membrane_stain"] = [] if not par["obs_membrane_stain"] else par["obs_membrane_stain"]
par["obs_panck_stain"] = [] if not par["obs_panck_stain"] else par["obs_panck_stain"]
par["obs_cd45_stain"] = [] if not par["obs_cd45_stain"] else par["obs_cd45_stain"]
par["obs_cd3_stain"] = [] if not par["obs_cd3_stain"] else par["obs_cd3_stain"]
def transform_df(df):
@@ -1770,6 +1947,60 @@ def generate_visium_stats(mod_obs, sample_id, required_keys):
return cell_rna_stats
def format_cosmx_columns(mod_obs):
cosmx_obs_keys = [par["obs_area"], par["obs_aspect_ratio"]]
# Add multiple keys
for key_list in [par["obs_dapi_stain"], par["obs_membrane_stain"], par["obs_panck_stain"],
par["obs_cd45_stain"], par["obs_cd3_stain"]]:
if key_list:
cosmx_obs_keys.extend(key_list)
# Check if keys are present
check_optional_obs_keys(mod_obs, cosmx_obs_keys, "CosMx metrics.")
# Filter only existing keys
cosmx_formatted_columns = [key for key in cosmx_obs_keys if key in mod_obs]
# Add coordinates
cosmx_formatted_columns.extend(["x_coord", "y_coord"])
for key in cosmx_formatted_columns:
if key in mod_obs:
if not pd.api.types.is_float_dtype(mod_obs[key]):
try:
mod_obs[key] = mod_obs[key].astype("float32")
except ValueError:
logger.warning(f"Could not convert column {key} to a float dtype.")
return mod_obs, cosmx_formatted_columns
def generate_cosmx_stats(mod_obs, sample_id, required_keys):
# Format required columns
mod_obs = format_required_columns(required_keys, mod_obs)
# Format cosmx-specific columns
mod_obs, cosmx_formatted_columns = format_cosmx_columns(mod_obs)
# Fetch and format all categorical columns for grouping
metadata_obs_keys, mod_obs = format_categorical_columns(mod_obs)
# Create cell RNA stats dataframe
cell_rna_stats = pd.DataFrame(
{
"sample_id": pd.Categorical(sample_id),
**{key: mod_obs[key] for key in required_keys},
**{key: mod_obs[key] for key in cosmx_formatted_columns},
**{key: mod_obs[key] for key in metadata_obs_keys}
}
)
return cell_rna_stats
def concatenate_dataframes(dfs):
'''Concatenates a list of dataframes into a single dataframe, preserving categorical columns.'''
df = pd.concat(dfs, ignore_index=True)
@@ -1809,7 +2040,7 @@ def main(par):
barcodes_original_count = mod_obs.shape[0]
# Add coordinates to obs before filtering
if par["ingestion_method"] == "xenium" or par["ingestion_method"] == "visium":
if par["ingestion_method"] == "xenium" or par["ingestion_method"] == "visium" or par["ingestion_method"] == "cosmx":
mod_obs["x_coord"] = mod_obsm["spatial"][:, 0]
mod_obs["y_coord"] = mod_obsm["spatial"][:, 1]
@@ -1866,6 +2097,9 @@ def main(par):
if par["ingestion_method"] == "visium":
cell_rna_stats = generate_visium_stats(mod_obs, sample_id, required_keys)
if par["ingestion_method"] == "cosmx":
cell_rna_stats = generate_cosmx_stats(mod_obs, sample_id, required_keys)
cell_stats_dfs.append(cell_rna_stats)
sample_stats_dfs.append(sample_summary_stats)
@@ -1901,7 +2135,8 @@ def main(par):
report_structures = {
"cellranger_multi": os.path.join(meta["resources_dir"], "report_structure/cellranger.json"),
"xenium": os.path.join(meta["resources_dir"], "report_structure/xenium.json"),
"visium": os.path.join(meta["resources_dir"], "report_structure/visium.json")
"visium": os.path.join(meta["resources_dir"], "report_structure/visium.json"),
"cosmx": os.path.join(meta["resources_dir"], "report_structure/cosmx.json")
}
logger.info(f"Writing output report structure json to {par['output_reporting_json']}")

View File

@@ -0,0 +1,211 @@
{
"categories": [
{
"name": "Sample QC",
"key": "sample_summary_stats",
"additionalAxes": false,
"defaultFilters": []
},
{
"name": "Cell RNA QC",
"key": "cell_rna_stats",
"additionalAxes": true,
"defaultFilters": [
{
"type": "histogram",
"visualizationType": "histogram",
"field": "total_counts",
"label": "Total UMI per cell",
"description": "Total number of RNA molecules detected per cell. Low values typically indicate empty droplets or low-quality cells that should be filtered out.",
"cutoffMin": null,
"cutoffMax": null,
"zoomMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "num_nonzero_vars",
"label": "Number of non-zero genes per cell",
"description": "Count of unique genes detected in each cell. Low gene counts often indicate poor-quality cells.",
"cutoffMin": null,
"cutoffMax": null,
"zoomMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "fraction_mitochondrial",
"label": "Fraction UMI of mitochondrial genes per cell",
"description": "Proportion of cell's RNA from mitochondrial genes.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "fraction_ribosomal",
"label": "Fraction UMI of ribosomal genes per cell",
"description": "Proportion of cell's RNA from ribosomal protein genes. Extreme values may indicate stress responses or cell cycle abnormalities.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Area",
"label": "Cell Area",
"description": "Area of the segmented cells.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "AspectRatio",
"label": "Aspect Ratio",
"description": "Aspect ratio of the segmented cells.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.DAPI",
"label": "Mean DAPI Intensity",
"description": "Mean intensity of DAPI stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.MembraneStain",
"label": "Mean Membrane Stain Intensity",
"description": "Mean intensity of Membrane stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.PanCK",
"label": "Mean PanCK Intensity",
"description": "Mean intensity of PanCK stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.CD45",
"label": "Mean CD45 Intensity",
"description": "Mean intensity of CD45 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.CD3",
"label": "Mean CD3 Intensity",
"description": "Mean intensity of CD3 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.DAPI",
"label": "Max DAPI Intensity",
"description": "Maximum intensity of DAPI stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.MembraneStain",
"label": "Max Membrane Stain Intensity",
"description": "Maximum intensity of Membrane stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.PanCK",
"label": "Max PanCK Intensity",
"description": "Maximum intensity of PanCK stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.CD45",
"label": "Max CD45 Intensity",
"description": "Maximum intensity of CD45 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.CD3",
"label": "Max CD3 Intensity",
"description": "Maximum intensity of CD3 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
}
]
}
]
}

View File

@@ -1,6 +1,6 @@
name: "h5mu_to_qc_json"
namespace: "ingestion_qc"
version: "v0.2.0"
version: "v0.2.2"
authors:
- name: "Jakub Majercik"
roles:
@@ -87,6 +87,7 @@ argument_groups:
choices:
- "cellranger_multi"
- "xenium"
- "cosmx"
- "visium"
direction: "input"
multiple: false
@@ -293,6 +294,84 @@ argument_groups:
direction: "input"
multiple: false
multiple_sep: ";"
- name: "Options for CosMx reports"
arguments:
- type: "string"
name: "--obs_area"
description: "The key in the h5mu .obs field that contains the cell area."
info: null
default:
- "Area"
required: false
direction: "input"
multiple: false
multiple_sep: ";"
- type: "string"
name: "--obs_aspect_ratio"
description: "The key in the h5mu .obs field that contains the aspect ratio."
info: null
default:
- "AspectRatio"
required: false
direction: "input"
multiple: false
multiple_sep: ";"
- type: "string"
name: "--obs_dapi_stain"
description: "The keys in the h5mu .obs field that contains the DAPI stain intensity."
info: null
default:
- "Mean.DAPI"
- "Max.DAPI"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_membrane_stain"
description: "The keys in the h5mu .obs field that contains the membrane stain\
\ intensity."
info: null
default:
- "Mean.MembraneStain"
- "Max.MembraneStain"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_panck_stain"
description: "The keys in the h5mu .obs field that contains the PanCK stain intensity."
info: null
default:
- "Mean.PanCK"
- "Max.PanCK"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_cd45_stain"
description: "The keys in the h5mu .obs field that contains the CD45 stain intensity."
info: null
default:
- "Mean.CD45"
- "Max.CD45"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_cd3_stain"
description: "The keys in the h5mu .obs field that contains the CD3 stain intensity."
info: null
default:
- "Mean.CD3"
- "Max.CD3"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
resources:
- type: "python_script"
path: "script.py"
@@ -409,7 +488,7 @@ engines:
id: "docker"
image: "python:3.12-slim"
target_registry: "images.viash-hub.com"
target_tag: "v0.2.0"
target_tag: "v0.2.2"
namespace_separator: "/"
setup:
- type: "apt"
@@ -448,11 +527,11 @@ build_info:
output: "target/_private/nextflow/ingestion_qc/h5mu_to_qc_json"
executable: "target/_private/nextflow/ingestion_qc/h5mu_to_qc_json/main.nf"
viash_version: "0.9.4"
git_commit: "a4ab5f509f731422ffc79b739a89b9d11fb4e440"
git_commit: "9b81d310d031b120755e39001cc40f8ec51bc7c2"
git_remote: "https://github.com/openpipelines-bio/openpipeline_qc"
package_config:
name: "openpipeline_qc"
version: "v0.2.0"
version: "v0.2.2"
info:
test_resources:
- type: "s3"
@@ -477,7 +556,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.0'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.2'"
organization: "vsh"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_qc"

View File

@@ -1,4 +1,4 @@
// h5mu_to_qc_json v0.2.0
// h5mu_to_qc_json v0.2.2
//
// 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
@@ -3038,7 +3038,7 @@ meta = [
"config": processConfig(readJsonBlob('''{
"name" : "h5mu_to_qc_json",
"namespace" : "ingestion_qc",
"version" : "v0.2.0",
"version" : "v0.2.2",
"authors" : [
{
"name" : "Jakub Majercik",
@@ -3163,6 +3163,7 @@ meta = [
"choices" : [
"cellranger_multi",
"xenium",
"cosmx",
"visium"
],
"direction" : "input",
@@ -3413,6 +3414,100 @@ meta = [
"multiple_sep" : ";"
}
]
},
{
"name" : "Options for CosMx reports",
"arguments" : [
{
"type" : "string",
"name" : "--obs_area",
"description" : "The key in the h5mu .obs field that contains the cell area.",
"default" : [
"Area"
],
"required" : false,
"direction" : "input",
"multiple" : false,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_aspect_ratio",
"description" : "The key in the h5mu .obs field that contains the aspect ratio.",
"default" : [
"AspectRatio"
],
"required" : false,
"direction" : "input",
"multiple" : false,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_dapi_stain",
"description" : "The keys in the h5mu .obs field that contains the DAPI stain intensity.",
"default" : [
"Mean.DAPI",
"Max.DAPI"
],
"required" : false,
"direction" : "input",
"multiple" : true,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_membrane_stain",
"description" : "The keys in the h5mu .obs field that contains the membrane stain intensity.",
"default" : [
"Mean.MembraneStain",
"Max.MembraneStain"
],
"required" : false,
"direction" : "input",
"multiple" : true,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_panck_stain",
"description" : "The keys in the h5mu .obs field that contains the PanCK stain intensity.",
"default" : [
"Mean.PanCK",
"Max.PanCK"
],
"required" : false,
"direction" : "input",
"multiple" : true,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_cd45_stain",
"description" : "The keys in the h5mu .obs field that contains the CD45 stain intensity.",
"default" : [
"Mean.CD45",
"Max.CD45"
],
"required" : false,
"direction" : "input",
"multiple" : true,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_cd3_stain",
"description" : "The keys in the h5mu .obs field that contains the CD3 stain intensity.",
"default" : [
"Mean.CD3",
"Max.CD3"
],
"required" : false,
"direction" : "input",
"multiple" : true,
"multiple_sep" : ";"
}
]
}
],
"resources" : [
@@ -3562,7 +3657,7 @@ meta = [
"id" : "docker",
"image" : "python:3.12-slim",
"target_registry" : "images.viash-hub.com",
"target_tag" : "v0.2.0",
"target_tag" : "v0.2.2",
"namespace_separator" : "/",
"setup" : [
{
@@ -3617,12 +3712,12 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/_private/nextflow/ingestion_qc/h5mu_to_qc_json",
"viash_version" : "0.9.4",
"git_commit" : "a4ab5f509f731422ffc79b739a89b9d11fb4e440",
"git_commit" : "9b81d310d031b120755e39001cc40f8ec51bc7c2",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_qc"
},
"package_config" : {
"name" : "openpipeline_qc",
"version" : "v0.2.0",
"version" : "v0.2.2",
"info" : {
"test_resources" : [
{
@@ -3653,7 +3748,7 @@ meta = [
".requirements.commands := ['ps']\n.runners[.type == 'nextflow'].directives.tag := '$id'\n.resources += {path: '/src/configs/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
".engines += { type: \\"native\\" }",
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
".engines[.type == 'docker'].target_tag := 'v0.2.0'"
".engines[.type == 'docker'].target_tag := 'v0.2.2'"
],
"organization" : "vsh",
"links" : {
@@ -3705,7 +3800,14 @@ par = {
'obs_x_coord': $( if [ ! -z ${VIASH_PAR_OBS_X_COORD+x} ]; then echo "r'${VIASH_PAR_OBS_X_COORD//\\'/\\'\\"\\'\\"r\\'}'"; else echo None; fi ),
'obs_y_coord': $( if [ ! -z ${VIASH_PAR_OBS_Y_COORD+x} ]; then echo "r'${VIASH_PAR_OBS_Y_COORD//\\'/\\'\\"\\'\\"r\\'}'"; else echo None; fi ),
'obs_control_probe_counts': $( if [ ! -z ${VIASH_PAR_OBS_CONTROL_PROBE_COUNTS+x} ]; then echo "r'${VIASH_PAR_OBS_CONTROL_PROBE_COUNTS//\\'/\\'\\"\\'\\"r\\'}'"; else echo None; fi ),
'obs_control_codeword_counts': $( if [ ! -z ${VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS+x} ]; then echo "r'${VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS//\\'/\\'\\"\\'\\"r\\'}'"; else echo None; fi )
'obs_control_codeword_counts': $( if [ ! -z ${VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS+x} ]; then echo "r'${VIASH_PAR_OBS_CONTROL_CODEWORD_COUNTS//\\'/\\'\\"\\'\\"r\\'}'"; else echo None; fi ),
'obs_area': $( if [ ! -z ${VIASH_PAR_OBS_AREA+x} ]; then echo "r'${VIASH_PAR_OBS_AREA//\\'/\\'\\"\\'\\"r\\'}'"; else echo None; fi ),
'obs_aspect_ratio': $( if [ ! -z ${VIASH_PAR_OBS_ASPECT_RATIO+x} ]; then echo "r'${VIASH_PAR_OBS_ASPECT_RATIO//\\'/\\'\\"\\'\\"r\\'}'"; else echo None; fi ),
'obs_dapi_stain': $( if [ ! -z ${VIASH_PAR_OBS_DAPI_STAIN+x} ]; then echo "r'${VIASH_PAR_OBS_DAPI_STAIN//\\'/\\'\\"\\'\\"r\\'}'.split(';')"; else echo None; fi ),
'obs_membrane_stain': $( if [ ! -z ${VIASH_PAR_OBS_MEMBRANE_STAIN+x} ]; then echo "r'${VIASH_PAR_OBS_MEMBRANE_STAIN//\\'/\\'\\"\\'\\"r\\'}'.split(';')"; else echo None; fi ),
'obs_panck_stain': $( if [ ! -z ${VIASH_PAR_OBS_PANCK_STAIN+x} ]; then echo "r'${VIASH_PAR_OBS_PANCK_STAIN//\\'/\\'\\"\\'\\"r\\'}'.split(';')"; else echo None; fi ),
'obs_cd45_stain': $( if [ ! -z ${VIASH_PAR_OBS_CD45_STAIN+x} ]; then echo "r'${VIASH_PAR_OBS_CD45_STAIN//\\'/\\'\\"\\'\\"r\\'}'.split(';')"; else echo None; fi ),
'obs_cd3_stain': $( if [ ! -z ${VIASH_PAR_OBS_CD3_STAIN+x} ]; then echo "r'${VIASH_PAR_OBS_CD3_STAIN//\\'/\\'\\"\\'\\"r\\'}'.split(';')"; else echo None; fi )
}
meta = {
'name': $( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "r'${VIASH_META_NAME//\\'/\\'\\"\\'\\"r\\'}'"; else echo None; fi ),
@@ -3739,6 +3841,11 @@ from setup_logger import setup_logger
logger = setup_logger()
par["obs_cellbender"] = {} if not par["obs_cellbender"] else par["obs_cellbender"]
par["obs_dapi_stain"] = [] if not par["obs_dapi_stain"] else par["obs_dapi_stain"]
par["obs_membrane_stain"] = [] if not par["obs_membrane_stain"] else par["obs_membrane_stain"]
par["obs_panck_stain"] = [] if not par["obs_panck_stain"] else par["obs_panck_stain"]
par["obs_cd45_stain"] = [] if not par["obs_cd45_stain"] else par["obs_cd45_stain"]
par["obs_cd3_stain"] = [] if not par["obs_cd3_stain"] else par["obs_cd3_stain"]
def transform_df(df):
@@ -3955,6 +4062,60 @@ def generate_visium_stats(mod_obs, sample_id, required_keys):
return cell_rna_stats
def format_cosmx_columns(mod_obs):
cosmx_obs_keys = [par["obs_area"], par["obs_aspect_ratio"]]
# Add multiple keys
for key_list in [par["obs_dapi_stain"], par["obs_membrane_stain"], par["obs_panck_stain"],
par["obs_cd45_stain"], par["obs_cd3_stain"]]:
if key_list:
cosmx_obs_keys.extend(key_list)
# Check if keys are present
check_optional_obs_keys(mod_obs, cosmx_obs_keys, "CosMx metrics.")
# Filter only existing keys
cosmx_formatted_columns = [key for key in cosmx_obs_keys if key in mod_obs]
# Add coordinates
cosmx_formatted_columns.extend(["x_coord", "y_coord"])
for key in cosmx_formatted_columns:
if key in mod_obs:
if not pd.api.types.is_float_dtype(mod_obs[key]):
try:
mod_obs[key] = mod_obs[key].astype("float32")
except ValueError:
logger.warning(f"Could not convert column {key} to a float dtype.")
return mod_obs, cosmx_formatted_columns
def generate_cosmx_stats(mod_obs, sample_id, required_keys):
# Format required columns
mod_obs = format_required_columns(required_keys, mod_obs)
# Format cosmx-specific columns
mod_obs, cosmx_formatted_columns = format_cosmx_columns(mod_obs)
# Fetch and format all categorical columns for grouping
metadata_obs_keys, mod_obs = format_categorical_columns(mod_obs)
# Create cell RNA stats dataframe
cell_rna_stats = pd.DataFrame(
{
"sample_id": pd.Categorical(sample_id),
**{key: mod_obs[key] for key in required_keys},
**{key: mod_obs[key] for key in cosmx_formatted_columns},
**{key: mod_obs[key] for key in metadata_obs_keys}
}
)
return cell_rna_stats
def concatenate_dataframes(dfs):
\'\'\'Concatenates a list of dataframes into a single dataframe, preserving categorical columns.\'\'\'
df = pd.concat(dfs, ignore_index=True)
@@ -3994,7 +4155,7 @@ def main(par):
barcodes_original_count = mod_obs.shape[0]
# Add coordinates to obs before filtering
if par["ingestion_method"] == "xenium" or par["ingestion_method"] == "visium":
if par["ingestion_method"] == "xenium" or par["ingestion_method"] == "visium" or par["ingestion_method"] == "cosmx":
mod_obs["x_coord"] = mod_obsm["spatial"][:, 0]
mod_obs["y_coord"] = mod_obsm["spatial"][:, 1]
@@ -4051,6 +4212,9 @@ def main(par):
if par["ingestion_method"] == "visium":
cell_rna_stats = generate_visium_stats(mod_obs, sample_id, required_keys)
if par["ingestion_method"] == "cosmx":
cell_rna_stats = generate_cosmx_stats(mod_obs, sample_id, required_keys)
cell_stats_dfs.append(cell_rna_stats)
sample_stats_dfs.append(sample_summary_stats)
@@ -4086,7 +4250,8 @@ def main(par):
report_structures = {
"cellranger_multi": os.path.join(meta["resources_dir"], "report_structure/cellranger.json"),
"xenium": os.path.join(meta["resources_dir"], "report_structure/xenium.json"),
"visium": os.path.join(meta["resources_dir"], "report_structure/visium.json")
"visium": os.path.join(meta["resources_dir"], "report_structure/visium.json"),
"cosmx": os.path.join(meta["resources_dir"], "report_structure/cosmx.json")
}
logger.info(f"Writing output report structure json to {par['output_reporting_json']}")
@@ -4477,7 +4642,7 @@ meta["defaults"] = [
"container" : {
"registry" : "images.viash-hub.com",
"image" : "vsh/openpipeline_qc/ingestion_qc/h5mu_to_qc_json",
"tag" : "v0.2.0"
"tag" : "v0.2.2"
},
"label" : [
"midmem",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'ingestion_qc/h5mu_to_qc_json'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v0.2.0'
version = 'v0.2.2'
description = 'Takes H5MU files that have been ingested by CellRanger, Xenium or CosMx and processed by the QC workflow, and generates:\n- A JSON file that contains the combined data for the QC report\n- A JSON file that defines the layout and structure of the QC report\n'
author = 'Jakub Majercik, Dorien Roosen, Robrecht Cannoodt, Weiwei Schultz'
}

View File

@@ -0,0 +1,211 @@
{
"categories": [
{
"name": "Sample QC",
"key": "sample_summary_stats",
"additionalAxes": false,
"defaultFilters": []
},
{
"name": "Cell RNA QC",
"key": "cell_rna_stats",
"additionalAxes": true,
"defaultFilters": [
{
"type": "histogram",
"visualizationType": "histogram",
"field": "total_counts",
"label": "Total UMI per cell",
"description": "Total number of RNA molecules detected per cell. Low values typically indicate empty droplets or low-quality cells that should be filtered out.",
"cutoffMin": null,
"cutoffMax": null,
"zoomMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "num_nonzero_vars",
"label": "Number of non-zero genes per cell",
"description": "Count of unique genes detected in each cell. Low gene counts often indicate poor-quality cells.",
"cutoffMin": null,
"cutoffMax": null,
"zoomMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "fraction_mitochondrial",
"label": "Fraction UMI of mitochondrial genes per cell",
"description": "Proportion of cell's RNA from mitochondrial genes.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "fraction_ribosomal",
"label": "Fraction UMI of ribosomal genes per cell",
"description": "Proportion of cell's RNA from ribosomal protein genes. Extreme values may indicate stress responses or cell cycle abnormalities.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Area",
"label": "Cell Area",
"description": "Area of the segmented cells.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "AspectRatio",
"label": "Aspect Ratio",
"description": "Aspect ratio of the segmented cells.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.DAPI",
"label": "Mean DAPI Intensity",
"description": "Mean intensity of DAPI stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.MembraneStain",
"label": "Mean Membrane Stain Intensity",
"description": "Mean intensity of Membrane stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.PanCK",
"label": "Mean PanCK Intensity",
"description": "Mean intensity of PanCK stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.CD45",
"label": "Mean CD45 Intensity",
"description": "Mean intensity of CD45 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Mean.CD3",
"label": "Mean CD3 Intensity",
"description": "Mean intensity of CD3 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.DAPI",
"label": "Max DAPI Intensity",
"description": "Maximum intensity of DAPI stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.MembraneStain",
"label": "Max Membrane Stain Intensity",
"description": "Maximum intensity of Membrane stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.PanCK",
"label": "Max PanCK Intensity",
"description": "Maximum intensity of PanCK stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.CD45",
"label": "Max CD45 Intensity",
"description": "Maximum intensity of CD45 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
},
{
"type": "histogram",
"visualizationType": "histogram",
"field": "Max.CD3",
"label": "Max CD3 Intensity",
"description": "Maximum intensity of CD3 stain.",
"cutoffMin": null,
"cutoffMax": null,
"nBins": 50,
"groupBy": "sample_id",
"yAxisType": "linear"
}
]
}
]
}

View File

@@ -1,6 +1,6 @@
name: "detect_ingestion_method"
namespace: "ingestion_qc"
version: "v0.2.0"
version: "v0.2.2"
authors:
- name: "Dorien Roosen"
roles:
@@ -190,7 +190,7 @@ engines:
id: "docker"
image: "python:3.12-slim"
target_registry: "images.viash-hub.com"
target_tag: "v0.2.0"
target_tag: "v0.2.2"
namespace_separator: "/"
setup:
- type: "apt"
@@ -229,11 +229,11 @@ build_info:
output: "target/executable/ingestion_qc/detect_ingestion_method"
executable: "target/executable/ingestion_qc/detect_ingestion_method/detect_ingestion_method"
viash_version: "0.9.4"
git_commit: "a4ab5f509f731422ffc79b739a89b9d11fb4e440"
git_commit: "9b81d310d031b120755e39001cc40f8ec51bc7c2"
git_remote: "https://github.com/openpipelines-bio/openpipeline_qc"
package_config:
name: "openpipeline_qc"
version: "v0.2.0"
version: "v0.2.2"
info:
test_resources:
- type: "s3"
@@ -258,7 +258,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.0'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.2'"
organization: "vsh"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_qc"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# detect_ingestion_method v0.2.0
# detect_ingestion_method v0.2.2
#
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
@@ -459,10 +459,10 @@ RUN pip install --upgrade pip && \
LABEL org.opencontainers.image.authors="Dorien Roosen, Weiwei Schultz"
LABEL org.opencontainers.image.description="Companion container for running component ingestion_qc detect_ingestion_method"
LABEL org.opencontainers.image.created="2026-02-02T16:26:05Z"
LABEL org.opencontainers.image.created="2026-02-03T16:37:27Z"
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_qc"
LABEL org.opencontainers.image.revision="a4ab5f509f731422ffc79b739a89b9d11fb4e440"
LABEL org.opencontainers.image.version="v0.2.0"
LABEL org.opencontainers.image.revision="9b81d310d031b120755e39001cc40f8ec51bc7c2"
LABEL org.opencontainers.image.version="v0.2.2"
VIASHDOCKER
fi
@@ -579,7 +579,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
# ViashHelp: Display helpful explanation about this executable
function ViashHelp {
echo "detect_ingestion_method v0.2.0"
echo "detect_ingestion_method v0.2.2"
echo ""
echo "Detects the ingestion method of a dataset."
echo "Currently detects either 10X CellRanger Multi, 10X Xenium or Nanostring CosMx,"
@@ -656,7 +656,7 @@ while [[ $# -gt 0 ]]; do
shift 1
;;
--version)
echo "detect_ingestion_method v0.2.0"
echo "detect_ingestion_method v0.2.2"
exit
;;
--input)
@@ -791,7 +791,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_qc/ingestion_qc/detect_ingestion_method:v0.2.0'
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_qc/ingestion_qc/detect_ingestion_method:v0.2.2'
fi
# print dockerfile

View File

@@ -1,6 +1,6 @@
name: "generate_html"
namespace: "ingestion_qc"
version: "v0.2.0"
version: "v0.2.2"
authors:
- name: "Jakub Majercik"
roles:
@@ -209,7 +209,7 @@ engines:
id: "docker"
image: "node:latest"
target_registry: "images.viash-hub.com"
target_tag: "v0.2.0"
target_tag: "v0.2.2"
namespace_separator: "/"
setup:
- type: "apt"
@@ -231,11 +231,11 @@ build_info:
output: "target/executable/ingestion_qc/generate_html"
executable: "target/executable/ingestion_qc/generate_html/generate_html"
viash_version: "0.9.4"
git_commit: "a4ab5f509f731422ffc79b739a89b9d11fb4e440"
git_commit: "9b81d310d031b120755e39001cc40f8ec51bc7c2"
git_remote: "https://github.com/openpipelines-bio/openpipeline_qc"
package_config:
name: "openpipeline_qc"
version: "v0.2.0"
version: "v0.2.2"
info:
test_resources:
- type: "s3"
@@ -260,7 +260,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.0'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.2'"
organization: "vsh"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_qc"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# generate_html v0.2.0
# generate_html v0.2.2
#
# 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
@@ -461,10 +461,10 @@ RUN cd /opt && git clone -b v0.2.1 https://github.com/openpipelines-bio/siqc.git
LABEL org.opencontainers.image.authors="Jakub Majercik, Dorien Roosen, Robrecht Cannoodt, Weiwei Schultz"
LABEL org.opencontainers.image.description="Companion container for running component ingestion_qc generate_html"
LABEL org.opencontainers.image.created="2026-02-02T16:26:04Z"
LABEL org.opencontainers.image.created="2026-02-03T16:37:27Z"
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline_qc"
LABEL org.opencontainers.image.revision="a4ab5f509f731422ffc79b739a89b9d11fb4e440"
LABEL org.opencontainers.image.version="v0.2.0"
LABEL org.opencontainers.image.revision="9b81d310d031b120755e39001cc40f8ec51bc7c2"
LABEL org.opencontainers.image.version="v0.2.2"
VIASHDOCKER
fi
@@ -581,7 +581,7 @@ VIASH_DOCKER_RUN_ARGS=(-i --rm)
# ViashHelp: Display helpful explanation about this executable
function ViashHelp {
echo "generate_html v0.2.0"
echo "generate_html v0.2.2"
echo ""
echo "Generate an HTML report from the QC metrics"
echo ""
@@ -649,7 +649,7 @@ while [[ $# -gt 0 ]]; do
shift 1
;;
--version)
echo "generate_html v0.2.0"
echo "generate_html v0.2.2"
exit
;;
--input_data)
@@ -773,7 +773,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_qc/ingestion_qc/generate_html:v0.2.0'
VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline_qc/ingestion_qc/generate_html:v0.2.2'
fi
# print dockerfile

View File

@@ -1,6 +1,6 @@
name: "detect_ingestion_method"
namespace: "ingestion_qc"
version: "v0.2.0"
version: "v0.2.2"
authors:
- name: "Dorien Roosen"
roles:
@@ -190,7 +190,7 @@ engines:
id: "docker"
image: "python:3.12-slim"
target_registry: "images.viash-hub.com"
target_tag: "v0.2.0"
target_tag: "v0.2.2"
namespace_separator: "/"
setup:
- type: "apt"
@@ -229,11 +229,11 @@ build_info:
output: "target/nextflow/ingestion_qc/detect_ingestion_method"
executable: "target/nextflow/ingestion_qc/detect_ingestion_method/main.nf"
viash_version: "0.9.4"
git_commit: "a4ab5f509f731422ffc79b739a89b9d11fb4e440"
git_commit: "9b81d310d031b120755e39001cc40f8ec51bc7c2"
git_remote: "https://github.com/openpipelines-bio/openpipeline_qc"
package_config:
name: "openpipeline_qc"
version: "v0.2.0"
version: "v0.2.2"
info:
test_resources:
- type: "s3"
@@ -258,7 +258,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.0'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.2'"
organization: "vsh"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_qc"

View File

@@ -1,4 +1,4 @@
// detect_ingestion_method v0.2.0
// detect_ingestion_method v0.2.2
//
// 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" : "detect_ingestion_method",
"namespace" : "ingestion_qc",
"version" : "v0.2.0",
"version" : "v0.2.2",
"authors" : [
{
"name" : "Dorien Roosen",
@@ -3290,7 +3290,7 @@ meta = [
"id" : "docker",
"image" : "python:3.12-slim",
"target_registry" : "images.viash-hub.com",
"target_tag" : "v0.2.0",
"target_tag" : "v0.2.2",
"namespace_separator" : "/",
"setup" : [
{
@@ -3345,12 +3345,12 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/nextflow/ingestion_qc/detect_ingestion_method",
"viash_version" : "0.9.4",
"git_commit" : "a4ab5f509f731422ffc79b739a89b9d11fb4e440",
"git_commit" : "9b81d310d031b120755e39001cc40f8ec51bc7c2",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_qc"
},
"package_config" : {
"name" : "openpipeline_qc",
"version" : "v0.2.0",
"version" : "v0.2.2",
"info" : {
"test_resources" : [
{
@@ -3381,7 +3381,7 @@ meta = [
".requirements.commands := ['ps']\n.runners[.type == 'nextflow'].directives.tag := '$id'\n.resources += {path: '/src/configs/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
".engines += { type: \\"native\\" }",
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
".engines[.type == 'docker'].target_tag := 'v0.2.0'"
".engines[.type == 'docker'].target_tag := 'v0.2.2'"
],
"organization" : "vsh",
"links" : {
@@ -3872,7 +3872,7 @@ meta["defaults"] = [
"container" : {
"registry" : "images.viash-hub.com",
"image" : "vsh/openpipeline_qc/ingestion_qc/detect_ingestion_method",
"tag" : "v0.2.0"
"tag" : "v0.2.2"
},
"label" : [
"lowmem",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'ingestion_qc/detect_ingestion_method'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v0.2.0'
version = 'v0.2.2'
description = 'Detects the ingestion method of a dataset.\nCurrently detects either 10X CellRanger Multi, 10X Xenium or Nanostring CosMx, but can be extended to other technologies upon request.\n'
author = 'Dorien Roosen, Weiwei Schultz'
}

View File

@@ -1,6 +1,6 @@
name: "generate_html"
namespace: "ingestion_qc"
version: "v0.2.0"
version: "v0.2.2"
authors:
- name: "Jakub Majercik"
roles:
@@ -209,7 +209,7 @@ engines:
id: "docker"
image: "node:latest"
target_registry: "images.viash-hub.com"
target_tag: "v0.2.0"
target_tag: "v0.2.2"
namespace_separator: "/"
setup:
- type: "apt"
@@ -231,11 +231,11 @@ build_info:
output: "target/nextflow/ingestion_qc/generate_html"
executable: "target/nextflow/ingestion_qc/generate_html/main.nf"
viash_version: "0.9.4"
git_commit: "a4ab5f509f731422ffc79b739a89b9d11fb4e440"
git_commit: "9b81d310d031b120755e39001cc40f8ec51bc7c2"
git_remote: "https://github.com/openpipelines-bio/openpipeline_qc"
package_config:
name: "openpipeline_qc"
version: "v0.2.0"
version: "v0.2.2"
info:
test_resources:
- type: "s3"
@@ -260,7 +260,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.0'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.2'"
organization: "vsh"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_qc"

View File

@@ -1,4 +1,4 @@
// generate_html v0.2.0
// generate_html v0.2.2
//
// 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
@@ -3038,7 +3038,7 @@ meta = [
"config": processConfig(readJsonBlob('''{
"name" : "generate_html",
"namespace" : "ingestion_qc",
"version" : "v0.2.0",
"version" : "v0.2.2",
"authors" : [
{
"name" : "Jakub Majercik",
@@ -3330,7 +3330,7 @@ meta = [
"id" : "docker",
"image" : "node:latest",
"target_registry" : "images.viash-hub.com",
"target_tag" : "v0.2.0",
"target_tag" : "v0.2.2",
"namespace_separator" : "/",
"setup" : [
{
@@ -3359,12 +3359,12 @@ meta = [
"engine" : "docker|native",
"output" : "/workdir/root/repo/target/nextflow/ingestion_qc/generate_html",
"viash_version" : "0.9.4",
"git_commit" : "a4ab5f509f731422ffc79b739a89b9d11fb4e440",
"git_commit" : "9b81d310d031b120755e39001cc40f8ec51bc7c2",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_qc"
},
"package_config" : {
"name" : "openpipeline_qc",
"version" : "v0.2.0",
"version" : "v0.2.2",
"info" : {
"test_resources" : [
{
@@ -3395,7 +3395,7 @@ meta = [
".requirements.commands := ['ps']\n.runners[.type == 'nextflow'].directives.tag := '$id'\n.resources += {path: '/src/configs/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
".engines += { type: \\"native\\" }",
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
".engines[.type == 'docker'].target_tag := 'v0.2.0'"
".engines[.type == 'docker'].target_tag := 'v0.2.2'"
],
"organization" : "vsh",
"links" : {
@@ -3830,7 +3830,7 @@ meta["defaults"] = [
"container" : {
"registry" : "images.viash-hub.com",
"image" : "vsh/openpipeline_qc/ingestion_qc/generate_html",
"tag" : "v0.2.0"
"tag" : "v0.2.2"
},
"label" : [
"lowmem",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'ingestion_qc/generate_html'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v0.2.0'
version = 'v0.2.2'
description = 'Generate an HTML report from the QC metrics'
author = 'Jakub Majercik, Dorien Roosen, Robrecht Cannoodt, Weiwei Schultz'
}

View File

@@ -1,6 +1,6 @@
name: "generate_qc_report"
namespace: "workflows"
version: "v0.2.0"
version: "v0.2.2"
authors:
- name: "Jakub Majercik"
roles:
@@ -86,6 +86,7 @@ argument_groups:
choices:
- "cellranger_multi"
- "xenium"
- "cosmx"
- "visium"
direction: "input"
multiple: false
@@ -212,6 +213,84 @@ argument_groups:
direction: "input"
multiple: false
multiple_sep: ";"
- name: "Options for CosMx reports"
arguments:
- type: "string"
name: "--obs_area"
description: "The key in the h5mu .obs field that contains the cell area."
info: null
default:
- "Area"
required: false
direction: "input"
multiple: false
multiple_sep: ";"
- type: "string"
name: "--obs_aspect_ratio"
description: "The key in the h5mu .obs field that contains the aspect ratio."
info: null
default:
- "AspectRatio"
required: false
direction: "input"
multiple: false
multiple_sep: ";"
- type: "string"
name: "--obs_dapi_stain"
description: "The keys in the h5mu .obs field that contains the DAPI stain intensity."
info: null
default:
- "Mean.DAPI"
- "Max.DAPI"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_membrane_stain"
description: "The keys in the h5mu .obs field that contains the membrane stain\
\ intensity."
info: null
default:
- "Mean.MembraneStain"
- "Max.MembraneStain"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_panck_stain"
description: "The keys in the h5mu .obs field that contains the PanCK stain intensity."
info: null
default:
- "Mean.PanCK"
- "Max.PanCK"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_cd45_stain"
description: "The keys in the h5mu .obs field that contains the CD45 stain intensity."
info: null
default:
- "Mean.CD45"
- "Max.CD45"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- type: "string"
name: "--obs_cd3_stain"
description: "The keys in the h5mu .obs field that contains the CD3 stain intensity."
info: null
default:
- "Mean.CD3"
- "Max.CD3"
required: false
direction: "input"
multiple: true
multiple_sep: ";"
- name: "Outputs"
arguments:
- type: "file"
@@ -386,7 +465,7 @@ build_info:
output: "target/nextflow/workflows/generate_qc_report"
executable: "target/nextflow/workflows/generate_qc_report/main.nf"
viash_version: "0.9.4"
git_commit: "a4ab5f509f731422ffc79b739a89b9d11fb4e440"
git_commit: "9b81d310d031b120755e39001cc40f8ec51bc7c2"
git_remote: "https://github.com/openpipelines-bio/openpipeline_qc"
dependencies:
- "target/dependencies/vsh/vsh/openpipeline/v4.0.0/nextflow/metadata/add_id"
@@ -397,7 +476,7 @@ build_info:
- "target/dependencies/vsh/vsh/craftbox/v0.2.0/nextflow/move_files_to_directory"
package_config:
name: "openpipeline_qc"
version: "v0.2.0"
version: "v0.2.2"
info:
test_resources:
- type: "s3"
@@ -422,7 +501,7 @@ package_config:
)'"
- ".engines += { type: \"native\" }"
- ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.0'"
- ".engines[.type == 'docker'].target_tag := 'v0.2.2'"
organization: "vsh"
links:
repository: "https://github.com/openpipelines-bio/openpipeline_qc"

View File

@@ -1,4 +1,4 @@
// generate_qc_report v0.2.0
// generate_qc_report v0.2.2
//
// 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
@@ -3038,7 +3038,7 @@ meta = [
"config": processConfig(readJsonBlob('''{
"name" : "generate_qc_report",
"namespace" : "workflows",
"version" : "v0.2.0",
"version" : "v0.2.2",
"authors" : [
{
"name" : "Jakub Majercik",
@@ -3162,6 +3162,7 @@ meta = [
"choices" : [
"cellranger_multi",
"xenium",
"cosmx",
"visium"
],
"direction" : "input",
@@ -3314,6 +3315,100 @@ meta = [
}
]
},
{
"name" : "Options for CosMx reports",
"arguments" : [
{
"type" : "string",
"name" : "--obs_area",
"description" : "The key in the h5mu .obs field that contains the cell area.",
"default" : [
"Area"
],
"required" : false,
"direction" : "input",
"multiple" : false,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_aspect_ratio",
"description" : "The key in the h5mu .obs field that contains the aspect ratio.",
"default" : [
"AspectRatio"
],
"required" : false,
"direction" : "input",
"multiple" : false,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_dapi_stain",
"description" : "The keys in the h5mu .obs field that contains the DAPI stain intensity.",
"default" : [
"Mean.DAPI",
"Max.DAPI"
],
"required" : false,
"direction" : "input",
"multiple" : true,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_membrane_stain",
"description" : "The keys in the h5mu .obs field that contains the membrane stain intensity.",
"default" : [
"Mean.MembraneStain",
"Max.MembraneStain"
],
"required" : false,
"direction" : "input",
"multiple" : true,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_panck_stain",
"description" : "The keys in the h5mu .obs field that contains the PanCK stain intensity.",
"default" : [
"Mean.PanCK",
"Max.PanCK"
],
"required" : false,
"direction" : "input",
"multiple" : true,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_cd45_stain",
"description" : "The keys in the h5mu .obs field that contains the CD45 stain intensity.",
"default" : [
"Mean.CD45",
"Max.CD45"
],
"required" : false,
"direction" : "input",
"multiple" : true,
"multiple_sep" : ";"
},
{
"type" : "string",
"name" : "--obs_cd3_stain",
"description" : "The keys in the h5mu .obs field that contains the CD3 stain intensity.",
"default" : [
"Mean.CD3",
"Max.CD3"
],
"required" : false,
"direction" : "input",
"multiple" : true,
"multiple_sep" : ";"
}
]
},
{
"name" : "Outputs",
"arguments" : [
@@ -3547,12 +3642,12 @@ meta = [
"engine" : "native",
"output" : "/workdir/root/repo/target/nextflow/workflows/generate_qc_report",
"viash_version" : "0.9.4",
"git_commit" : "a4ab5f509f731422ffc79b739a89b9d11fb4e440",
"git_commit" : "9b81d310d031b120755e39001cc40f8ec51bc7c2",
"git_remote" : "https://github.com/openpipelines-bio/openpipeline_qc"
},
"package_config" : {
"name" : "openpipeline_qc",
"version" : "v0.2.0",
"version" : "v0.2.2",
"info" : {
"test_resources" : [
{
@@ -3583,7 +3678,7 @@ meta = [
".requirements.commands := ['ps']\n.runners[.type == 'nextflow'].directives.tag := '$id'\n.resources += {path: '/src/configs/labels.config', dest: 'nextflow_labels.config'}\n.runners[.type == 'nextflow'].config.script := 'includeConfig(\\"nextflow_labels.config\\")'",
".engines += { type: \\"native\\" }",
".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'",
".engines[.type == 'docker'].target_tag := 'v0.2.0'"
".engines[.type == 'docker'].target_tag := 'v0.2.2'"
],
"organization" : "vsh",
"links" : {
@@ -3762,7 +3857,14 @@ workflow run_wf {
ingestion_method: "ingestion_method",
obs_metadata: "obs_metadata",
min_total_counts: "min_total_counts",
min_num_nonzero_vars: "min_num_nonzero_vars"
min_num_nonzero_vars: "min_num_nonzero_vars",
obs_area: "obs_area",
obs_aspect_ratio: "obs_aspect_ratio",
obs_dapi_stain: "obs_dapi_stain",
obs_membrane_stain: "obs_membrane_stain",
obs_panck_stain: "obs_panck_stain",
obs_cd45_stain: "obs_cd45_stain",
obs_cd3_stain: "obs_cd3_stain",
],
args: [
obs_sample_id: "sample_id",

View File

@@ -2,7 +2,7 @@ manifest {
name = 'workflows/generate_qc_report'
mainScript = 'main.nf'
nextflowVersion = '!>=20.12.1-edge'
version = 'v0.2.0'
version = 'v0.2.2'
description = 'Run the ingestion QC report generation'
author = 'Jakub Majercik, Dorien Roosen, Robrecht Cannoodt, Weiwei Schultz'
}

View File

@@ -1,175 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "generate_qc_report",
"description": "Run the ingestion QC report generation",
"type": "object",
"$defs": {
"inputs": {
"title": "Inputs",
"type": "object",
"description": "No description",
"properties": {
"id": {
"type": "string",
"description": "The sample IDs to include in the report",
"help_text": "Type: `string`, multiple: `False`, example: `\"sample1\"`. "
},
"input": {
"type": "string",
"format": "path",
"exists": true,
"description": "The input h5mu files.",
"help_text": "Type: `file`, multiple: `False`, required, direction: `input`, example: `\"path/to/file1.h5mu\"`. "
},
"ingestion_method": {
"type": "string",
"description": "",
"help_text": "Type: `string`, multiple: `False`, required, choices: ``cellranger_multi`, `xenium`, `visium``. ",
"enum": [
"cellranger_multi",
"xenium",
"visium"
]
},
"sample_metadata": {
"type": "string",
"format": "path",
"description": "The sample metadata file corresponding to .obs fields in the h5mu input files, to be used for grouping in the report.\n",
"help_text": "Type: `file`, multiple: `False`, direction: `input`, example: `\"path/to/file.csv\"`. "
},
"max_samples_per_report": {
"type": "integer",
"description": "The maximum number of samples to be included per report",
"help_text": "Type: `integer`, multiple: `False`, default: `20`. ",
"default": 20
}
}
},
"outputs": {
"title": "Outputs",
"type": "object",
"description": "No description",
"properties": {
"output_qc_report": {
"type": "array",
"items": {
"type": "string"
},
"format": "path",
"description": "The output HTML report",
"help_text": "Type: `file`, multiple: `True`, required, default: `\"$id.$key.output_qc_report_*.html\"`, direction: `output`, example: `[\"path/to/file.html\"]`. ",
"default": "$id.$key.output_qc_report_*.html"
},
"output_processed_h5mu": {
"type": "string",
"format": "path",
"description": "Folder containing the processed h5mu files.",
"help_text": "Type: `file`, multiple: `False`, required, default: `\"qc_h5mu\"`, direction: `output`. ",
"default": "qc_h5mu"
}
}
},
"options": {
"title": "Options",
"type": "object",
"description": "No description",
"properties": {
"var_gene_names": {
"type": "string",
"description": "The column name in the .var h5mu files that contains the gene names",
"help_text": "Type: `string`, multiple: `False`, example: `\"gene_symbol\"`. "
},
"obs_metadata": {
"type": "array",
"items": {
"type": "string"
},
"description": "The metadata keys in the h5mu .obs to include in the report.",
"help_text": "Type: `string`, multiple: `True`, example: `[\"donor_id\";\"cell_type\";\"batch\";\"condition\"]`. "
}
}
},
"qc options": {
"title": "QC options",
"type": "object",
"description": "No description",
"properties": {
"var_name_mitochondrial_genes": {
"type": "string",
"description": "In which .var slot to store a boolean array corresponding the mitochondrial genes.\n",
"help_text": "Type: `string`, multiple: `False`, default: `\"mitochondrial\"`. ",
"default": "mitochondrial"
},
"var_name_ribosomal_genes": {
"type": "string",
"description": "In which .var slot to store a boolean array corresponding the ribosomal genes.\n",
"help_text": "Type: `string`, multiple: `False`, default: `\"ribosomal\"`. ",
"default": "ribosomal"
},
"min_total_counts": {
"type": "integer",
"description": "Minimum total counts for a cell to be included in the output.\n",
"help_text": "Type: `integer`, multiple: `False`, default: `10`. ",
"default": 10
},
"min_num_nonzero_vars": {
"type": "integer",
"description": "Minimum number of nonzero vars for a cell to be included in the output.\n",
"help_text": "Type: `integer`, multiple: `False`, default: `10`. ",
"default": 10
}
}
},
"cellbender options": {
"title": "Cellbender options",
"type": "object",
"description": "No description",
"properties": {
"run_cellbender": {
"type": "boolean",
"description": "Whether to run cellbender or not.",
"help_text": "Type: `boolean`, multiple: `False`, default: `false`. ",
"default": false
},
"cellbender_epochs": {
"type": "integer",
"description": "Number of epochs to train cellbender.",
"help_text": "Type: `integer`, multiple: `False`, default: `150`. ",
"default": 150
}
}
},
"nextflow input-output arguments": {
"title": "Nextflow input-output arguments",
"type": "object",
"description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.",
"properties": {
"publish_dir": {
"type": "string",
"description": "Path to an output directory.",
"help_text": "Type: `string`, multiple: `False`, required, example: `\"output/\"`. "
}
}
}
},
"allOf": [
{
"$ref": "#/$defs/inputs"
},
{
"$ref": "#/$defs/outputs"
},
{
"$ref": "#/$defs/options"
},
{
"$ref": "#/$defs/qc options"
},
{
"$ref": "#/$defs/cellbender options"
},
{
"$ref": "#/$defs/nextflow input-output arguments"
}
]
}