From e368384c53e4ee4814c8d8069c5043b0511e9ef6 Mon Sep 17 00:00:00 2001 From: Karen Fang Date: Fri, 31 Oct 2025 14:36:05 -0400 Subject: [PATCH 01/11] Select n_comps for PCA based on number of cells and genes --- docker/spatial_py/build.env | 2 +- docker/spatial_py/scripts/visium_process | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docker/spatial_py/build.env b/docker/spatial_py/build.env index 8c9703d..13ec4df 100644 --- a/docker/spatial_py/build.env +++ b/docker/spatial_py/build.env @@ -1,5 +1,5 @@ # Tool versions -SPATIAL_PY_VERSION=1.0.0 +SPATIAL_PY_VERSION=1.0.1 GCLOUD_CLI_VERSION=524.0.0-slim PYTHON3_VERSION=3.12.5 diff --git a/docker/spatial_py/scripts/visium_process b/docker/spatial_py/scripts/visium_process index a9d8246..8f02854 100755 --- a/docker/spatial_py/scripts/visium_process +++ b/docker/spatial_py/scripts/visium_process @@ -72,9 +72,17 @@ def main(args): ############################## ## DIMENSIONALITY REDUCTION ## ############################## + n_comps = args.n_comps + if hvg_adata.n_obs < n_comps or hvg_adata.n_vars < n_comps: + n_comps = min(n_comps, hvg_adata.n_obs - 1, hvg_adata.n_vars - 1) + print(f"[INFO] Detected small dimensions (n_obs={hvg_adata.n_obs}, n_vars={hvg_adata.n_vars}). Setting n_comps={n_comps}.") + print(f"[WARNING] PCA might not be meaningful since dataset is small (e.g., <30 cells) or check filters.") + else: + print(f"[INFO] Running PCA with default settings (n={n_comps}).") + sc.pp.pca( hvg_adata, - n_comps=args.n_comps, + n_comps=n_comps, svd_solver="arpack", ) From c188a0da6cd65445e74b38fc094f2f16a6b66baa Mon Sep 17 00:00:00 2001 From: Karen Fang Date: Fri, 31 Oct 2025 14:38:40 -0400 Subject: [PATCH 02/11] Bump patch for workflow version --- workflows/spatial_visium/cohort_analysis/cohort_analysis.wdl | 2 +- workflows/spatial_visium/main.wdl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/workflows/spatial_visium/cohort_analysis/cohort_analysis.wdl b/workflows/spatial_visium/cohort_analysis/cohort_analysis.wdl index c7f902c..5adb39c 100644 --- a/workflows/spatial_visium/cohort_analysis/cohort_analysis.wdl +++ b/workflows/spatial_visium/cohort_analysis/cohort_analysis.wdl @@ -39,7 +39,7 @@ workflow cohort_analysis { } String sub_workflow_name = "cohort_analysis" - String sub_workflow_version = "1.0.0" + String sub_workflow_version = "1.0.1" Array[Array[String]] workflow_info = [[run_timestamp, workflow_name, workflow_version, workflow_release]] diff --git a/workflows/spatial_visium/main.wdl b/workflows/spatial_visium/main.wdl index 190a37e..92cad4e 100644 --- a/workflows/spatial_visium/main.wdl +++ b/workflows/spatial_visium/main.wdl @@ -31,7 +31,7 @@ workflow spatial_visium_analysis { String workflow_execution_path = "workflow_execution" String workflow_name = "spatial_visium" - String workflow_version = "v1.0.0" + String workflow_version = "v1.0.1" String workflow_release = "https://github.com/ASAP-CRN/spatial-transcriptomics-wf/releases/tag/spatial_visium_analysis-~{workflow_version}" call GetWorkflowMetadata.get_workflow_metadata { From 7121aa81907275e3ac5839ed45fb43922175486e Mon Sep 17 00:00:00 2001 From: Karen Fang Date: Fri, 31 Oct 2025 14:42:32 -0400 Subject: [PATCH 03/11] Update spatial_py docker image version in workflow --- .../spatial_visium/cohort_analysis/cohort_analysis.wdl | 6 +++--- .../spatial_statistics/spatial_statistics.wdl | 2 +- workflows/spatial_visium/preprocess/preprocess.wdl | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/workflows/spatial_visium/cohort_analysis/cohort_analysis.wdl b/workflows/spatial_visium/cohort_analysis/cohort_analysis.wdl index 5adb39c..6a3e69c 100644 --- a/workflows/spatial_visium/cohort_analysis/cohort_analysis.wdl +++ b/workflows/spatial_visium/cohort_analysis/cohort_analysis.wdl @@ -273,7 +273,7 @@ task merge_and_plot_qc_metrics { } runtime { - docker: "~{container_registry}/spatial_py:1.0.0" + docker: "~{container_registry}/spatial_py:1.0.1" cpu: 2 memory: "~{mem_gb} GB" disks: "local-disk ~{disk_size} HDD" @@ -354,7 +354,7 @@ task filter_and_normalize { } runtime { - docker: "~{container_registry}/spatial_py:1.0.0" + docker: "~{container_registry}/spatial_py:1.0.1" cpu: 4 memory: "~{mem_gb} GB" disks: "local-disk ~{disk_size} HDD" @@ -420,7 +420,7 @@ task plot_spatial { } runtime { - docker: "~{container_registry}/spatial_py:1.0.0" + docker: "~{container_registry}/spatial_py:1.0.1" cpu: 2 memory: "~{mem_gb} GB" disks: "local-disk ~{disk_size} HDD" diff --git a/workflows/spatial_visium/cohort_analysis/spatial_statistics/spatial_statistics.wdl b/workflows/spatial_visium/cohort_analysis/spatial_statistics/spatial_statistics.wdl index 9bd2403..47c4b83 100644 --- a/workflows/spatial_visium/cohort_analysis/spatial_statistics/spatial_statistics.wdl +++ b/workflows/spatial_visium/cohort_analysis/spatial_statistics/spatial_statistics.wdl @@ -89,7 +89,7 @@ task spatially_variable_gene_analysis { } runtime { - docker: "~{container_registry}/spatial_py:1.0.0" + docker: "~{container_registry}/spatial_py:1.0.1" cpu: 2 memory: "~{mem_gb} GB" disks: "local-disk ~{disk_size} HDD" diff --git a/workflows/spatial_visium/preprocess/preprocess.wdl b/workflows/spatial_visium/preprocess/preprocess.wdl index 8550099..3dbb3f2 100644 --- a/workflows/spatial_visium/preprocess/preprocess.wdl +++ b/workflows/spatial_visium/preprocess/preprocess.wdl @@ -461,7 +461,7 @@ task counts_to_adata { } runtime { - docker: "~{container_registry}/spatial_py:1.0.0" + docker: "~{container_registry}/spatial_py:1.0.1" cpu: 2 memory: "4 GB" disks: "local-disk ~{disk_size} HDD" @@ -526,7 +526,7 @@ task qc { } runtime { - docker: "~{container_registry}/spatial_py:1.0.0" + docker: "~{container_registry}/spatial_py:1.0.1" cpu: threads memory: "~{mem_gb} GB" disks: "local-disk ~{disk_size} HDD" From 84227a2adb36a6d0674f2ba0d2e32f24bc402cfa Mon Sep 17 00:00:00 2001 From: Karen Fang Date: Fri, 31 Oct 2025 15:47:15 -0400 Subject: [PATCH 04/11] Determine n_comps with number of cells and genes when clustering --- docker/spatial_py/scripts/cluster | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docker/spatial_py/scripts/cluster b/docker/spatial_py/scripts/cluster index 996adbb..d29f7b8 100755 --- a/docker/spatial_py/scripts/cluster +++ b/docker/spatial_py/scripts/cluster @@ -14,9 +14,16 @@ def main(args): ########################## adata = sc.read_h5ad(args.adata_input) + n_comps = args.n_comps + if adata.n_obs < n_comps or adata.n_vars < n_comps: + n_comps = min(n_comps, adata.n_obs - 1, adata.n_vars - 1) + print(f"[INFO] Detected small dimensions (n_obs={adata.n_obs}, n_vars={adata.n_vars}). Setting n_comps={n_comps}.") + else: + print(f"[INFO] Computing the nearest neighbors distance matrix with default settings (n={n_comps}).") + sc.pp.neighbors( adata, - n_pcs=args.n_comps, + n_pcs=n_comps, ) sc.tl.umap(adata) From 023f63db9ee61ba85d335ee908eec697913f0180 Mon Sep 17 00:00:00 2001 From: Karen Fang Date: Fri, 31 Oct 2025 16:50:50 -0400 Subject: [PATCH 05/11] Update spatial_py docker image in integrate_data wdl --- workflows/integrate_data/integrate_data.wdl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/workflows/integrate_data/integrate_data.wdl b/workflows/integrate_data/integrate_data.wdl index 19235d9..89b3fe6 100644 --- a/workflows/integrate_data/integrate_data.wdl +++ b/workflows/integrate_data/integrate_data.wdl @@ -92,7 +92,7 @@ task integrate_sample_data { } runtime { - docker: "~{container_registry}/spatial_py:1.0.0" + docker: "~{container_registry}/spatial_py:1.0.1" cpu: 4 memory: "~{mem_gb} GB" disks: "local-disk ~{disk_size} HDD" @@ -155,7 +155,7 @@ task cluster { } runtime { - docker: "~{container_registry}/spatial_py:1.0.0" + docker: "~{container_registry}/spatial_py:1.0.1" cpu: 4 memory: "~{mem_gb} GB" disks: "local-disk ~{disk_size} HDD" From cc3079d8b04340f692cd32a44973563185c19f11 Mon Sep 17 00:00:00 2001 From: Karen Fang Date: Mon, 3 Nov 2025 13:34:19 -0500 Subject: [PATCH 06/11] Clean up adata.obs and .uns for plotting spatial image --- docker/spatial_py/scripts/visium_plot_spatial | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docker/spatial_py/scripts/visium_plot_spatial b/docker/spatial_py/scripts/visium_plot_spatial index 1211aeb..231d276 100755 --- a/docker/spatial_py/scripts/visium_plot_spatial +++ b/docker/spatial_py/scripts/visium_plot_spatial @@ -15,6 +15,13 @@ def main(args): colors = ["total_counts", "n_genes_by_counts", "batch", "leiden"] titles = [f"{slide} - {color}" for slide in slides for color in colors] + # Clean up + present_slides = adata.obs["visium_slide_ref"].unique() + all_slides = list(adata.uns["spatial"].keys()) + for slide in all_slides: + if slide not in present_slides: + del adata.uns["spatial"][slide] + sq.pl.spatial_scatter( adata, library_key="visium_slide_ref", From ce73e07ff6e0064a64302f5609ca7ddf0e9cbc3f Mon Sep 17 00:00:00 2001 From: Karen Fang Date: Mon, 3 Nov 2025 13:49:37 -0500 Subject: [PATCH 07/11] Filter spots on slides when computing spatially variable genes --- .../scripts/visium_spatially_variable_genes | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/docker/spatial_py/scripts/visium_spatially_variable_genes b/docker/spatial_py/scripts/visium_spatially_variable_genes index 98dafc0..4ec1e38 100755 --- a/docker/spatial_py/scripts/visium_spatially_variable_genes +++ b/docker/spatial_py/scripts/visium_spatially_variable_genes @@ -15,26 +15,42 @@ def main(args): adata = sc.read_h5ad(args.adata_input) genes = adata.var_names[adata.var["highly_variable"]].tolist() + + # Check spots per slide + spots_per_slide = adata.obs["visium_slide_ref"].value_counts() + print("Spots per slide:") + print(spots_per_slide) + slides_to_keep = spots_per_slide[spots_per_slide >= 4].index.tolist() + adata_filtered = adata[adata.obs["visium_slide_ref"].isin(slides_to_keep)].copy() + sq.gr.spatial_neighbors( - adata, + adata_filtered, library_key="visium_slide_ref", coord_type="generic", delaunay=True, ) sq.gr.spatial_autocorr( - adata, + adata_filtered, mode="moran", genes=genes, n_perms=100, n_jobs=1, ) - top_10_variable_genes = adata.uns["moranI"].head(10) + top_10_variable_genes = adata_filtered.uns["moranI"].head(10) - top_4_variable_gene_list = adata.uns["moranI"].head(4).index.tolist() - slides = adata.obs["visium_slide_ref"].unique().tolist() + top_4_variable_gene_list = adata_filtered.uns["moranI"].head(4).index.tolist() + slides = adata_filtered.obs["visium_slide_ref"].unique().tolist() titles = [f"{slide} - {color}" for slide in slides for color in top_4_variable_gene_list] + + # Clean up + present_slides = adata_filtered.obs["visium_slide_ref"].unique() + all_slides = list(adata_filtered.uns["spatial"].keys()) + for slide in all_slides: + if slide not in present_slides: + del adata_filtered.uns["spatial"][slide] + sq.pl.spatial_scatter( - adata, + adata_filtered, library_key="visium_slide_ref", color=top_4_variable_gene_list, title=titles, @@ -43,9 +59,9 @@ def main(args): # Save table and adata object top_10_variable_genes.to_csv(f"{args.cohort_id}.moran_top_10_variable_genes.csv") - metadata = adata.obs + metadata = adata_filtered.obs metadata.to_csv(f"{args.cohort_id}.final_metadata.csv") - adata.write_h5ad(filename=args.adata_output, compression="gzip") + adata_filtered.write_h5ad(filename=args.adata_output, compression="gzip") if __name__ == "__main__": From 8101792559713e0c7ec6de616897eb239ff8bb3c Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 18:30:34 +0000 Subject: [PATCH 08/11] update wdl-ci config file after successful tests --- wdl-ci.config.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/wdl-ci.config.json b/wdl-ci.config.json index 704c465..580c8b9 100644 --- a/wdl-ci.config.json +++ b/wdl-ci.config.json @@ -286,7 +286,7 @@ }, "cluster": { "key": "cluster", - "digest": "ibhtiot7sakpfyfuuvpxnqiqmsgzh4hj", + "digest": "frghkwauyalgin75nkrjs466t4vep5uk", "tests": [ { "inputs": { @@ -329,7 +329,7 @@ "tasks": { "merge_and_plot_qc_metrics": { "key": "merge_and_plot_qc_metrics", - "digest": "tfku5xa5owqltkkjxr2ibq36iw5fh6hx", + "digest": "6e55pxc6kpkxuyqrthug5cy4xgpirqta", "tests": [ { "inputs": { @@ -369,7 +369,7 @@ }, "filter_and_normalize": { "key": "filter_and_normalize", - "digest": "526uk3dkuil6gmxfyxiltlyvegxbxpki", + "digest": "sfml3i63wsmbm4jtgvfjn32lrchcesaw", "tests": [ { "inputs": { @@ -429,7 +429,7 @@ }, "plot_spatial": { "key": "plot_spatial", - "digest": "ufcwh7kuftyt6nu74cyoawgjvro7lsfv", + "digest": "3pfo5jdbiyz42mvxy6geg4gd7ednbjy3", "tests": [ { "inputs": { @@ -463,7 +463,7 @@ "tasks": { "spatially_variable_gene_analysis": { "key": "spatially_variable_gene_analysis", - "digest": "in5bndajrnrb4kupxqv7xydhlqpnmghy", + "digest": "ysgd246bcuttozfizskpva2frc2tnml2", "tests": [ { "inputs": { @@ -627,7 +627,7 @@ }, "counts_to_adata": { "key": "counts_to_adata", - "digest": "zh45hobarbnoa2z2b6d3i66fdyneqj3w", + "digest": "srukdp6rz3im6dzlcn365i36tv3422yp", "tests": [ { "inputs": { @@ -658,7 +658,7 @@ }, "qc": { "key": "qc", - "digest": "2jfnfowy32wp57i7ctsx7ni5pzzeadbi", + "digest": "s3lt4rtck6w3p7rc6dlav2wda4oz7f7l", "tests": [ { "inputs": { From 696173d3f54e9bb149c24d9cc39d7bb7b832ffa3 Mon Sep 17 00:00:00 2001 From: Karen Fang Date: Tue, 4 Nov 2025 15:10:11 -0500 Subject: [PATCH 09/11] Remove check_h5ad for integrate_data tasks because it is shared among Visium and GeoMx --- wdl-ci.config.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/wdl-ci.config.json b/wdl-ci.config.json index 580c8b9..4b69b72 100644 --- a/wdl-ci.config.json +++ b/wdl-ci.config.json @@ -276,8 +276,7 @@ "integrated_adata_object": { "value": "${geomx_input_file_path}/${cohort_analysis_workflow_name}/${geomx_team_id}.harmony_integrated.h5ad", "test_tasks": [ - "compare_file_basename", - "check_hdf5" + "compare_file_basename" ] } } @@ -304,8 +303,7 @@ "clustered_adata_object": { "value": "${geomx_input_file_path}/${cohort_analysis_workflow_name}/${geomx_team_id}.clustered.h5ad", "test_tasks": [ - "compare_file_basename", - "check_hdf5" + "compare_file_basename" ] }, "umap_cluster_plots_png": { From 0ed351095f494ebe789b1e6fb1ec0e2adcace850 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 20:19:08 +0000 Subject: [PATCH 10/11] update wdl-ci config file after successful tests --- wdl-ci.config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wdl-ci.config.json b/wdl-ci.config.json index 4b69b72..d7b0827 100644 --- a/wdl-ci.config.json +++ b/wdl-ci.config.json @@ -262,7 +262,7 @@ "tasks": { "integrate_sample_data": { "key": "integrate_sample_data", - "digest": "qjngtpgf2tzriftjt4hfwgo2i2z2uucg", + "digest": "hcdomqajbz6ntwc6xeqrsb65q4end4hn", "tests": [ { "inputs": { From e2b090de013f383325c55c4d21bda6e9b5ba0969 Mon Sep 17 00:00:00 2001 From: Karen Fang Date: Fri, 7 Nov 2025 09:49:28 -0500 Subject: [PATCH 11/11] Update submodule --- wf-common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wf-common b/wf-common index 158757f..d96f404 160000 --- a/wf-common +++ b/wf-common @@ -1 +1 @@ -Subproject commit 158757f9fe8529ca151ea0447b165f6b46475ba9 +Subproject commit d96f40474d5880ccb08a37e8372e848b8d5bae6d