diff --git a/scripts/run_benchmark/param_sweep/run_test_baysor_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_baysor_nebius.sh new file mode 100644 index 000000000..dd1d42b4e --- /dev/null +++ b/scripts/run_benchmark/param_sweep/run_test_baysor_nebius.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +# Nebius test run: all default methods + baysor at the transcript-assignment stage, +# with a parameter sweep over baysor's tuning knobs. +# See src/methods_transcript_assignment/baysor/NOTES.md ("Optimization / tuning"). +# +# The stage default (basic_transcript_assignment) stays enabled alongside baysor so the run +# also produces the baseline the sweep is scored against — the workflow allows at most ONE +# non-default variant at a time, and baysor is that one non-default method here; every OTHER +# stage stays on its single default. +# +# PARAMS-FILE CAVEAT: `method_parameters_yaml` is opened by the WORKFLOW at runtime on the cloud +# (readYaml -> Nextflow file()), so a local /tmp path won't exist there and /scratch is read-only +# from the launch host. file() DOES stage http(s):// and this repo is public, so the sweep lives +# in a COMMITTED file read from GitHub via its raw URL => commit AND PUSH +# scripts/run_benchmark/param_sweep/baysor_params.yaml to $params_branch before launching. +# This is independent of --revision (which selects the pipeline CODE). + +# get the root of the directory +REPO_ROOT=$(git rev-parse --show-toplevel) + +# ensure that the command below is run from the root of the repository +cd "$REPO_ROOT" + +set -e + +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" +# Results publish to /scratch — created and written by the cloud compute env (read-only here). +publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_baysor" + +# The sweep lives in a committed file, read from GitHub at runtime. $params_branch defaults to +# the branch you are on; the file must be pushed there. (Independent of --revision below.) +params_repo="openproblems-bio/task_ist_preprocessing" +params_branch="$(git rev-parse --abbrev-ref HEAD)" +params_url="https://raw.githubusercontent.com/${params_repo}/${params_branch}/scripts/run_benchmark/param_sweep/baysor_params.yaml" + +cat > /tmp/params_settings.yaml << HERE +default_methods: + - custom_segmentation + - basic_transcript_assignment + - basic_count_aggregation + - basic_qc_filter + - alpha_shapes + - normalize_by_volume + - tacco + - no_correction +segmentation_methods: + - custom_segmentation +transcript_assignment_methods: + - basic_transcript_assignment + - baysor +count_aggregation_methods: + - basic_count_aggregation +qc_filtering_methods: + - basic_qc_filter +volume_calculation_methods: + - alpha_shapes +normalization_methods: + - normalize_by_volume +celltype_annotation_methods: + - tacco +expression_correction_methods: + - no_correction +gene_efficiency_correction_methods: + - no_correction +method_parameters_yaml: $params_url +HERE + +# Write the parameters to file (input_states version, NOTE: enable `-entry_name auto` for this) +cat > /tmp/params.yaml << HERE +input_states: $resources_test_s3/**/state.yaml +rename_keys: 'input_sc:output_sc;input_sp:output_sp' +save_spatial_data: false +settings: '$(yq -o json /tmp/params_settings.yaml | jq -c .)' +output_state: "state.yaml" +publish_dir: "$publish_dir" +HERE + +# Fail early with a clear message if the params file isn't reachable on GitHub yet. +if ! curl -fsSL -o /dev/null "$params_url"; then + echo "ERROR: params file not reachable at:" >&2 + echo " $params_url" >&2 + echo "Commit and push scripts/run_benchmark/param_sweep/baysor_params.yaml to '$params_branch' first." >&2 + exit 1 +fi + +tw launch https://github.com/openproblems-bio/task_ist_preprocessing.git \ + --revision build/main \ + --pull-latest \ + --main-script target/nextflow/workflows/run_benchmark/main.nf \ + --workspace 167877437119966 \ + --compute-env 5hfmdCBxMRd4nHZaJKYEQZ \ + --params-file /tmp/params.yaml \ + --entry-name auto \ + --config src/base/labels_nebius.config \ + --labels task_ist_preprocessing,test,baysor diff --git a/scripts/run_benchmark/param_sweep/run_test_binning_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_binning_nebius.sh index 527e0d3d6..3cab53120 100644 --- a/scripts/run_benchmark/param_sweep/run_test_binning_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_binning_nebius.sh @@ -31,7 +31,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch — created and written by the cloud compute env, so # the launcher does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_binning" diff --git a/scripts/run_benchmark/param_sweep/run_test_cellpose_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_cellpose_nebius.sh index e3458e9a6..05d49e0bb 100644 --- a/scripts/run_benchmark/param_sweep/run_test_cellpose_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_cellpose_nebius.sh @@ -29,7 +29,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch — created and written by the cloud compute env, so # the launcher does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_cellpose" diff --git a/scripts/run_benchmark/param_sweep/run_test_cellposev4_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_cellposev4_nebius.sh index 5c092195e..b2877beef 100644 --- a/scripts/run_benchmark/param_sweep/run_test_cellposev4_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_cellposev4_nebius.sh @@ -15,7 +15,7 @@ # publish) is READ-ONLY from the launch host — which is why the binning # method_params block is commented out in run_test_nebius.sh. file() does stage # http(s):// though, and this repo is public, so we keep the sweep in a COMMITTED -# file (scripts/run_benchmark/cellposev4_params.yaml) and read it from GitHub via +# file (scripts/run_benchmark/param_sweep/cellposev4_params.yaml) and read it from GitHub via # its raw URL. => the params file must be committed AND PUSHED to $params_branch # before launching (edit the file there, not here, to change the sweep). @@ -27,7 +27,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch — created and written by the cloud compute env, so # the launcher does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_cellposev4" @@ -37,7 +37,7 @@ publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_cellposev4" # is independent of --revision below, which selects the pipeline CODE to run.) params_repo="openproblems-bio/task_ist_preprocessing" params_branch="$(git rev-parse --abbrev-ref HEAD)" -params_url="https://raw.githubusercontent.com/${params_repo}/${params_branch}/scripts/run_benchmark/cellposev4_params.yaml" +params_url="https://raw.githubusercontent.com/${params_repo}/${params_branch}/scripts/run_benchmark/param_sweep/cellposev4_params.yaml" cat > /tmp/params_settings.yaml << HERE default_methods: @@ -89,7 +89,7 @@ HERE if ! curl -fsSL -o /dev/null "$params_url"; then echo "ERROR: params file not reachable at:" >&2 echo " $params_url" >&2 - echo "Commit and push scripts/run_benchmark/cellposev4_params.yaml to '$params_branch' first." >&2 + echo "Commit and push scripts/run_benchmark/param_sweep/cellposev4_params.yaml to '$params_branch' first." >&2 exit 1 fi diff --git a/scripts/run_benchmark/param_sweep/run_test_clustermap_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_clustermap_nebius.sh new file mode 100644 index 000000000..4183a0b4a --- /dev/null +++ b/scripts/run_benchmark/param_sweep/run_test_clustermap_nebius.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +# Nebius test run: all default methods + clustermap at the transcript-assignment stage, +# with a parameter sweep over clustermap's tuning knobs. +# See src/methods_transcript_assignment/clustermap/NOTES.md ("Optimization / tuning"). +# +# The stage default (basic_transcript_assignment) stays enabled alongside clustermap so the run +# also produces the baseline the sweep is scored against — the workflow allows at most ONE +# non-default variant at a time, and clustermap is that one non-default method here; every OTHER +# stage stays on its single default. +# +# PARAMS-FILE CAVEAT: `method_parameters_yaml` is opened by the WORKFLOW at runtime on the cloud +# (readYaml -> Nextflow file()), so a local /tmp path won't exist there and /scratch is read-only +# from the launch host. file() DOES stage http(s):// and this repo is public, so the sweep lives +# in a COMMITTED file read from GitHub via its raw URL => commit AND PUSH +# scripts/run_benchmark/param_sweep/clustermap_params.yaml to $params_branch before launching. +# This is independent of --revision (which selects the pipeline CODE). + +# get the root of the directory +REPO_ROOT=$(git rev-parse --show-toplevel) + +# ensure that the command below is run from the root of the repository +cd "$REPO_ROOT" + +set -e + +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" +# Results publish to /scratch — created and written by the cloud compute env (read-only here). +publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_clustermap" + +# The sweep lives in a committed file, read from GitHub at runtime. $params_branch defaults to +# the branch you are on; the file must be pushed there. (Independent of --revision below.) +params_repo="openproblems-bio/task_ist_preprocessing" +params_branch="$(git rev-parse --abbrev-ref HEAD)" +params_url="https://raw.githubusercontent.com/${params_repo}/${params_branch}/scripts/run_benchmark/param_sweep/clustermap_params.yaml" + +cat > /tmp/params_settings.yaml << HERE +default_methods: + - custom_segmentation + - basic_transcript_assignment + - basic_count_aggregation + - basic_qc_filter + - alpha_shapes + - normalize_by_volume + - tacco + - no_correction +segmentation_methods: + - custom_segmentation +transcript_assignment_methods: + - basic_transcript_assignment + - clustermap +count_aggregation_methods: + - basic_count_aggregation +qc_filtering_methods: + - basic_qc_filter +volume_calculation_methods: + - alpha_shapes +normalization_methods: + - normalize_by_volume +celltype_annotation_methods: + - tacco +expression_correction_methods: + - no_correction +gene_efficiency_correction_methods: + - no_correction +method_parameters_yaml: $params_url +HERE + +# Write the parameters to file (input_states version, NOTE: enable `-entry_name auto` for this) +cat > /tmp/params.yaml << HERE +input_states: $resources_test_s3/**/state.yaml +rename_keys: 'input_sc:output_sc;input_sp:output_sp' +save_spatial_data: false +settings: '$(yq -o json /tmp/params_settings.yaml | jq -c .)' +output_state: "state.yaml" +publish_dir: "$publish_dir" +HERE + +# Fail early with a clear message if the params file isn't reachable on GitHub yet. +if ! curl -fsSL -o /dev/null "$params_url"; then + echo "ERROR: params file not reachable at:" >&2 + echo " $params_url" >&2 + echo "Commit and push scripts/run_benchmark/param_sweep/clustermap_params.yaml to '$params_branch' first." >&2 + exit 1 +fi + +tw launch https://github.com/openproblems-bio/task_ist_preprocessing.git \ + --revision build/main \ + --pull-latest \ + --main-script target/nextflow/workflows/run_benchmark/main.nf \ + --workspace 167877437119966 \ + --compute-env 5hfmdCBxMRd4nHZaJKYEQZ \ + --params-file /tmp/params.yaml \ + --entry-name auto \ + --config src/base/labels_nebius.config \ + --labels task_ist_preprocessing,test,clustermap diff --git a/scripts/run_benchmark/param_sweep/run_test_comseg_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_comseg_nebius.sh new file mode 100644 index 000000000..d31e7d018 --- /dev/null +++ b/scripts/run_benchmark/param_sweep/run_test_comseg_nebius.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +# Nebius test run: all default methods + comseg at the transcript-assignment stage, +# with a parameter sweep over comseg's tuning knobs. +# See src/methods_transcript_assignment/comseg/NOTES.md ("Optimization / tuning"). +# +# The stage default (basic_transcript_assignment) stays enabled alongside comseg so the run +# also produces the baseline the sweep is scored against — the workflow allows at most ONE +# non-default variant at a time, and comseg is that one non-default method here; every OTHER +# stage stays on its single default. +# +# PARAMS-FILE CAVEAT: `method_parameters_yaml` is opened by the WORKFLOW at runtime on the cloud +# (readYaml -> Nextflow file()), so a local /tmp path won't exist there and /scratch is read-only +# from the launch host. file() DOES stage http(s):// and this repo is public, so the sweep lives +# in a COMMITTED file read from GitHub via its raw URL => commit AND PUSH +# scripts/run_benchmark/param_sweep/comseg_params.yaml to $params_branch before launching. +# This is independent of --revision (which selects the pipeline CODE). + +# get the root of the directory +REPO_ROOT=$(git rev-parse --show-toplevel) + +# ensure that the command below is run from the root of the repository +cd "$REPO_ROOT" + +set -e + +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" +# Results publish to /scratch — created and written by the cloud compute env (read-only here). +publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_comseg" + +# The sweep lives in a committed file, read from GitHub at runtime. $params_branch defaults to +# the branch you are on; the file must be pushed there. (Independent of --revision below.) +params_repo="openproblems-bio/task_ist_preprocessing" +params_branch="$(git rev-parse --abbrev-ref HEAD)" +params_url="https://raw.githubusercontent.com/${params_repo}/${params_branch}/scripts/run_benchmark/param_sweep/comseg_params.yaml" + +cat > /tmp/params_settings.yaml << HERE +default_methods: + - custom_segmentation + - basic_transcript_assignment + - basic_count_aggregation + - basic_qc_filter + - alpha_shapes + - normalize_by_volume + - tacco + - no_correction +segmentation_methods: + - custom_segmentation +transcript_assignment_methods: + - basic_transcript_assignment + - comseg +count_aggregation_methods: + - basic_count_aggregation +qc_filtering_methods: + - basic_qc_filter +volume_calculation_methods: + - alpha_shapes +normalization_methods: + - normalize_by_volume +celltype_annotation_methods: + - tacco +expression_correction_methods: + - no_correction +gene_efficiency_correction_methods: + - no_correction +method_parameters_yaml: $params_url +HERE + +# Write the parameters to file (input_states version, NOTE: enable `-entry_name auto` for this) +cat > /tmp/params.yaml << HERE +input_states: $resources_test_s3/**/state.yaml +rename_keys: 'input_sc:output_sc;input_sp:output_sp' +save_spatial_data: false +settings: '$(yq -o json /tmp/params_settings.yaml | jq -c .)' +output_state: "state.yaml" +publish_dir: "$publish_dir" +HERE + +# Fail early with a clear message if the params file isn't reachable on GitHub yet. +if ! curl -fsSL -o /dev/null "$params_url"; then + echo "ERROR: params file not reachable at:" >&2 + echo " $params_url" >&2 + echo "Commit and push scripts/run_benchmark/param_sweep/comseg_params.yaml to '$params_branch' first." >&2 + exit 1 +fi + +tw launch https://github.com/openproblems-bio/task_ist_preprocessing.git \ + --revision build/main \ + --pull-latest \ + --main-script target/nextflow/workflows/run_benchmark/main.nf \ + --workspace 167877437119966 \ + --compute-env 5hfmdCBxMRd4nHZaJKYEQZ \ + --params-file /tmp/params.yaml \ + --entry-name auto \ + --config src/base/labels_nebius.config \ + --labels task_ist_preprocessing,test,comseg diff --git a/scripts/run_benchmark/param_sweep/run_test_fastreseg_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_fastreseg_nebius.sh new file mode 100644 index 000000000..acaebb3f7 --- /dev/null +++ b/scripts/run_benchmark/param_sweep/run_test_fastreseg_nebius.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +# Nebius test run: all default methods + fastreseg at the transcript-assignment stage, +# with a parameter sweep over fastreseg's tuning knobs. +# See src/methods_transcript_assignment/fastreseg/NOTES.md ("Optimization / tuning"). +# +# The stage default (basic_transcript_assignment) stays enabled alongside fastreseg so the run +# also produces the baseline the sweep is scored against — the workflow allows at most ONE +# non-default variant at a time, and fastreseg is that one non-default method here; every OTHER +# stage stays on its single default. +# +# PARAMS-FILE CAVEAT: `method_parameters_yaml` is opened by the WORKFLOW at runtime on the cloud +# (readYaml -> Nextflow file()), so a local /tmp path won't exist there and /scratch is read-only +# from the launch host. file() DOES stage http(s):// and this repo is public, so the sweep lives +# in a COMMITTED file read from GitHub via its raw URL => commit AND PUSH +# scripts/run_benchmark/param_sweep/fastreseg_params.yaml to $params_branch before launching. +# This is independent of --revision (which selects the pipeline CODE). + +# get the root of the directory +REPO_ROOT=$(git rev-parse --show-toplevel) + +# ensure that the command below is run from the root of the repository +cd "$REPO_ROOT" + +set -e + +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" +# Results publish to /scratch — created and written by the cloud compute env (read-only here). +publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_fastreseg" + +# The sweep lives in a committed file, read from GitHub at runtime. $params_branch defaults to +# the branch you are on; the file must be pushed there. (Independent of --revision below.) +params_repo="openproblems-bio/task_ist_preprocessing" +params_branch="$(git rev-parse --abbrev-ref HEAD)" +params_url="https://raw.githubusercontent.com/${params_repo}/${params_branch}/scripts/run_benchmark/param_sweep/fastreseg_params.yaml" + +cat > /tmp/params_settings.yaml << HERE +default_methods: + - custom_segmentation + - basic_transcript_assignment + - basic_count_aggregation + - basic_qc_filter + - alpha_shapes + - normalize_by_volume + - tacco + - no_correction +segmentation_methods: + - custom_segmentation +transcript_assignment_methods: + - basic_transcript_assignment + - fastreseg +count_aggregation_methods: + - basic_count_aggregation +qc_filtering_methods: + - basic_qc_filter +volume_calculation_methods: + - alpha_shapes +normalization_methods: + - normalize_by_volume +celltype_annotation_methods: + - tacco +expression_correction_methods: + - no_correction +gene_efficiency_correction_methods: + - no_correction +method_parameters_yaml: $params_url +HERE + +# Write the parameters to file (input_states version, NOTE: enable `-entry_name auto` for this) +cat > /tmp/params.yaml << HERE +input_states: $resources_test_s3/**/state.yaml +rename_keys: 'input_sc:output_sc;input_sp:output_sp' +save_spatial_data: false +settings: '$(yq -o json /tmp/params_settings.yaml | jq -c .)' +output_state: "state.yaml" +publish_dir: "$publish_dir" +HERE + +# Fail early with a clear message if the params file isn't reachable on GitHub yet. +if ! curl -fsSL -o /dev/null "$params_url"; then + echo "ERROR: params file not reachable at:" >&2 + echo " $params_url" >&2 + echo "Commit and push scripts/run_benchmark/param_sweep/fastreseg_params.yaml to '$params_branch' first." >&2 + exit 1 +fi + +tw launch https://github.com/openproblems-bio/task_ist_preprocessing.git \ + --revision build/main \ + --pull-latest \ + --main-script target/nextflow/workflows/run_benchmark/main.nf \ + --workspace 167877437119966 \ + --compute-env 5hfmdCBxMRd4nHZaJKYEQZ \ + --params-file /tmp/params.yaml \ + --entry-name auto \ + --config src/base/labels_nebius.config \ + --labels task_ist_preprocessing,test,fastreseg diff --git a/scripts/run_benchmark/param_sweep/run_test_moscot_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_moscot_nebius.sh index 7319cfb74..27d1a5c6e 100644 --- a/scripts/run_benchmark/param_sweep/run_test_moscot_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_moscot_nebius.sh @@ -36,7 +36,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch — created and written by the cloud compute env, so # the launcher does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_moscot" diff --git a/scripts/run_benchmark/param_sweep/run_test_pciseq_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_pciseq_nebius.sh new file mode 100644 index 000000000..be965b33c --- /dev/null +++ b/scripts/run_benchmark/param_sweep/run_test_pciseq_nebius.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +# Nebius test run: all default methods + pciseq at the transcript-assignment stage, +# with a parameter sweep over pciseq's tuning knobs. +# See src/methods_transcript_assignment/pciseq/NOTES.md ("Optimization / tuning"). +# +# The stage default (basic_transcript_assignment) stays enabled alongside pciseq so the run +# also produces the baseline the sweep is scored against — the workflow allows at most ONE +# non-default variant at a time, and pciseq is that one non-default method here; every OTHER +# stage stays on its single default. +# +# PARAMS-FILE CAVEAT: `method_parameters_yaml` is opened by the WORKFLOW at runtime on the cloud +# (readYaml -> Nextflow file()), so a local /tmp path won't exist there and /scratch is read-only +# from the launch host. file() DOES stage http(s):// and this repo is public, so the sweep lives +# in a COMMITTED file read from GitHub via its raw URL => commit AND PUSH +# scripts/run_benchmark/param_sweep/pciseq_params.yaml to $params_branch before launching. +# This is independent of --revision (which selects the pipeline CODE). + +# get the root of the directory +REPO_ROOT=$(git rev-parse --show-toplevel) + +# ensure that the command below is run from the root of the repository +cd "$REPO_ROOT" + +set -e + +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" +# Results publish to /scratch — created and written by the cloud compute env (read-only here). +publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_pciseq" + +# The sweep lives in a committed file, read from GitHub at runtime. $params_branch defaults to +# the branch you are on; the file must be pushed there. (Independent of --revision below.) +params_repo="openproblems-bio/task_ist_preprocessing" +params_branch="$(git rev-parse --abbrev-ref HEAD)" +params_url="https://raw.githubusercontent.com/${params_repo}/${params_branch}/scripts/run_benchmark/param_sweep/pciseq_params.yaml" + +cat > /tmp/params_settings.yaml << HERE +default_methods: + - custom_segmentation + - basic_transcript_assignment + - basic_count_aggregation + - basic_qc_filter + - alpha_shapes + - normalize_by_volume + - tacco + - no_correction +segmentation_methods: + - custom_segmentation +transcript_assignment_methods: + - basic_transcript_assignment + - pciseq +count_aggregation_methods: + - basic_count_aggregation +qc_filtering_methods: + - basic_qc_filter +volume_calculation_methods: + - alpha_shapes +normalization_methods: + - normalize_by_volume +celltype_annotation_methods: + - tacco +expression_correction_methods: + - no_correction +gene_efficiency_correction_methods: + - no_correction +method_parameters_yaml: $params_url +HERE + +# Write the parameters to file (input_states version, NOTE: enable `-entry_name auto` for this) +cat > /tmp/params.yaml << HERE +input_states: $resources_test_s3/**/state.yaml +rename_keys: 'input_sc:output_sc;input_sp:output_sp' +save_spatial_data: false +settings: '$(yq -o json /tmp/params_settings.yaml | jq -c .)' +output_state: "state.yaml" +publish_dir: "$publish_dir" +HERE + +# Fail early with a clear message if the params file isn't reachable on GitHub yet. +if ! curl -fsSL -o /dev/null "$params_url"; then + echo "ERROR: params file not reachable at:" >&2 + echo " $params_url" >&2 + echo "Commit and push scripts/run_benchmark/param_sweep/pciseq_params.yaml to '$params_branch' first." >&2 + exit 1 +fi + +tw launch https://github.com/openproblems-bio/task_ist_preprocessing.git \ + --revision build/main \ + --pull-latest \ + --main-script target/nextflow/workflows/run_benchmark/main.nf \ + --workspace 167877437119966 \ + --compute-env 5hfmdCBxMRd4nHZaJKYEQZ \ + --params-file /tmp/params.yaml \ + --entry-name auto \ + --config src/base/labels_nebius.config \ + --labels task_ist_preprocessing,test,pciseq diff --git a/scripts/run_benchmark/param_sweep/run_test_proseg_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_proseg_nebius.sh new file mode 100644 index 000000000..bbcff5c34 --- /dev/null +++ b/scripts/run_benchmark/param_sweep/run_test_proseg_nebius.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +# Nebius test run: all default methods + proseg at the transcript-assignment stage, +# with a parameter sweep over proseg's tuning knobs. +# See src/methods_transcript_assignment/proseg/NOTES.md ("Optimization / tuning"). +# +# The stage default (basic_transcript_assignment) stays enabled alongside proseg so the run +# also produces the baseline the sweep is scored against — the workflow allows at most ONE +# non-default variant at a time, and proseg is that one non-default method here; every OTHER +# stage stays on its single default. +# +# PARAMS-FILE CAVEAT: `method_parameters_yaml` is opened by the WORKFLOW at runtime on the cloud +# (readYaml -> Nextflow file()), so a local /tmp path won't exist there and /scratch is read-only +# from the launch host. file() DOES stage http(s):// and this repo is public, so the sweep lives +# in a COMMITTED file read from GitHub via its raw URL => commit AND PUSH +# scripts/run_benchmark/param_sweep/proseg_params.yaml to $params_branch before launching. +# This is independent of --revision (which selects the pipeline CODE). + +# get the root of the directory +REPO_ROOT=$(git rev-parse --show-toplevel) + +# ensure that the command below is run from the root of the repository +cd "$REPO_ROOT" + +set -e + +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" +# Results publish to /scratch — created and written by the cloud compute env (read-only here). +publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_proseg" + +# The sweep lives in a committed file, read from GitHub at runtime. $params_branch defaults to +# the branch you are on; the file must be pushed there. (Independent of --revision below.) +params_repo="openproblems-bio/task_ist_preprocessing" +params_branch="$(git rev-parse --abbrev-ref HEAD)" +params_url="https://raw.githubusercontent.com/${params_repo}/${params_branch}/scripts/run_benchmark/param_sweep/proseg_params.yaml" + +cat > /tmp/params_settings.yaml << HERE +default_methods: + - custom_segmentation + - basic_transcript_assignment + - basic_count_aggregation + - basic_qc_filter + - alpha_shapes + - normalize_by_volume + - tacco + - no_correction +segmentation_methods: + - custom_segmentation +transcript_assignment_methods: + - basic_transcript_assignment + - proseg +count_aggregation_methods: + - basic_count_aggregation +qc_filtering_methods: + - basic_qc_filter +volume_calculation_methods: + - alpha_shapes +normalization_methods: + - normalize_by_volume +celltype_annotation_methods: + - tacco +expression_correction_methods: + - no_correction +gene_efficiency_correction_methods: + - no_correction +method_parameters_yaml: $params_url +HERE + +# Write the parameters to file (input_states version, NOTE: enable `-entry_name auto` for this) +cat > /tmp/params.yaml << HERE +input_states: $resources_test_s3/**/state.yaml +rename_keys: 'input_sc:output_sc;input_sp:output_sp' +save_spatial_data: false +settings: '$(yq -o json /tmp/params_settings.yaml | jq -c .)' +output_state: "state.yaml" +publish_dir: "$publish_dir" +HERE + +# Fail early with a clear message if the params file isn't reachable on GitHub yet. +if ! curl -fsSL -o /dev/null "$params_url"; then + echo "ERROR: params file not reachable at:" >&2 + echo " $params_url" >&2 + echo "Commit and push scripts/run_benchmark/param_sweep/proseg_params.yaml to '$params_branch' first." >&2 + exit 1 +fi + +tw launch https://github.com/openproblems-bio/task_ist_preprocessing.git \ + --revision build/main \ + --pull-latest \ + --main-script target/nextflow/workflows/run_benchmark/main.nf \ + --workspace 167877437119966 \ + --compute-env 5hfmdCBxMRd4nHZaJKYEQZ \ + --params-file /tmp/params.yaml \ + --entry-name auto \ + --config src/base/labels_nebius.config \ + --labels task_ist_preprocessing,test,proseg diff --git a/scripts/run_benchmark/param_sweep/run_test_rctd_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_rctd_nebius.sh index 438c3a14e..5144b1d94 100644 --- a/scripts/run_benchmark/param_sweep/run_test_rctd_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_rctd_nebius.sh @@ -34,7 +34,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch — created and written by the cloud compute env, so # the launcher does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_rctd" diff --git a/scripts/run_benchmark/param_sweep/run_test_resolvi_correction_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_resolvi_correction_nebius.sh index a96ab96f0..f09969f85 100644 --- a/scripts/run_benchmark/param_sweep/run_test_resolvi_correction_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_resolvi_correction_nebius.sh @@ -29,7 +29,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch — created and written by the cloud compute env, so the launcher # does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_resolvi_correction" diff --git a/scripts/run_benchmark/param_sweep/run_test_segger_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_segger_nebius.sh new file mode 100644 index 000000000..6763f1df3 --- /dev/null +++ b/scripts/run_benchmark/param_sweep/run_test_segger_nebius.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +# Nebius test run: all default methods + segger at the transcript-assignment stage, +# with a parameter sweep over segger's tuning knobs. +# See src/methods_transcript_assignment/segger/NOTES.md ("Optimization / tuning"). +# segger is GPU-only: the `gpuh100` label in its config + src/base/labels_nebius.config +# (runAsUser:0 + /dev/shm volume) pin it to the GPU node group — no GPU-specific change is +# needed here (same as the existing run_test_segger_nebius.sh). +# +# The stage default (basic_transcript_assignment) stays enabled alongside segger so the run +# also produces the baseline the sweep is scored against — the workflow allows at most ONE +# non-default variant at a time, and segger is that one non-default method here; every OTHER +# stage stays on its single default. +# +# PARAMS-FILE CAVEAT: `method_parameters_yaml` is opened by the WORKFLOW at runtime on the cloud +# (readYaml -> Nextflow file()), so a local /tmp path won't exist there and /scratch is read-only +# from the launch host. file() DOES stage http(s):// and this repo is public, so the sweep lives +# in a COMMITTED file read from GitHub via its raw URL => commit AND PUSH +# scripts/run_benchmark/param_sweep/segger_params.yaml to $params_branch before launching. +# This is independent of --revision (which selects the pipeline CODE). + +# get the root of the directory +REPO_ROOT=$(git rev-parse --show-toplevel) + +# ensure that the command below is run from the root of the repository +cd "$REPO_ROOT" + +set -e + +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" +# Results publish to /scratch — created and written by the cloud compute env (read-only here). +publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_segger" + +# The sweep lives in a committed file, read from GitHub at runtime. $params_branch defaults to +# the branch you are on; the file must be pushed there. (Independent of --revision below.) +params_repo="openproblems-bio/task_ist_preprocessing" +params_branch="$(git rev-parse --abbrev-ref HEAD)" +params_url="https://raw.githubusercontent.com/${params_repo}/${params_branch}/scripts/run_benchmark/param_sweep/segger_params.yaml" + +cat > /tmp/params_settings.yaml << HERE +default_methods: + - custom_segmentation + - basic_transcript_assignment + - basic_count_aggregation + - basic_qc_filter + - alpha_shapes + - normalize_by_volume + - tacco + - no_correction +segmentation_methods: + - custom_segmentation +transcript_assignment_methods: + - basic_transcript_assignment + - segger +count_aggregation_methods: + - basic_count_aggregation +qc_filtering_methods: + - basic_qc_filter +volume_calculation_methods: + - alpha_shapes +normalization_methods: + - normalize_by_volume +celltype_annotation_methods: + - tacco +expression_correction_methods: + - no_correction +gene_efficiency_correction_methods: + - no_correction +method_parameters_yaml: $params_url +HERE + +# Write the parameters to file (input_states version, NOTE: enable `-entry_name auto` for this) +cat > /tmp/params.yaml << HERE +input_states: $resources_test_s3/**/state.yaml +rename_keys: 'input_sc:output_sc;input_sp:output_sp' +save_spatial_data: false +settings: '$(yq -o json /tmp/params_settings.yaml | jq -c .)' +output_state: "state.yaml" +publish_dir: "$publish_dir" +HERE + +# Fail early with a clear message if the params file isn't reachable on GitHub yet. +if ! curl -fsSL -o /dev/null "$params_url"; then + echo "ERROR: params file not reachable at:" >&2 + echo " $params_url" >&2 + echo "Commit and push scripts/run_benchmark/param_sweep/segger_params.yaml to '$params_branch' first." >&2 + exit 1 +fi + +tw launch https://github.com/openproblems-bio/task_ist_preprocessing.git \ + --revision build/main \ + --pull-latest \ + --main-script target/nextflow/workflows/run_benchmark/main.nf \ + --workspace 167877437119966 \ + --compute-env 5hfmdCBxMRd4nHZaJKYEQZ \ + --params-file /tmp/params.yaml \ + --entry-name auto \ + --config src/base/labels_nebius.config \ + --labels task_ist_preprocessing,test,segger diff --git a/scripts/run_benchmark/param_sweep/run_test_singler_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_singler_nebius.sh new file mode 100644 index 000000000..db0323fe7 --- /dev/null +++ b/scripts/run_benchmark/param_sweep/run_test_singler_nebius.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +# Nebius test run: all default methods + SingleR (singler) cell-type annotation, +# with a parameter sweep over the one exposed optimization lever for SingleR. +# See src/methods_cell_type_annotation/singler/NOTES.md ("Optimization / tuning"). +# +# SingleR (singler-py) is a CPU-only reference-correlation labeller — NO GPU, so +# there is no `gpu` label here (the non-GPU parts mirror run_test_nebius.sh). The +# compute env is the same one all these test runs use. +# +# The annotation stage keeps its default method `tacco` alongside `singler` so the +# run has a baseline to compare the singler variants against. Every other stage is +# left on its single default (the swept method must be the only non-default thing). +# +# !!! SUBMITTABLE-BUT-NO-OP CAVEAT !!! +# The sweep varies `celltype_key`, which ALREADY EXISTS in build/main's config, so +# this launches WITHOUT a rebuild. BUT build/main's baked-in script.py hardcodes the +# reference label column (ref_labels = ...column("cell_type")) and never reads +# par['celltype_key'] -- so on the deployed build/main container all four variants +# produce IDENTICAL annotations. The sweep only measures anything after a one-line +# wiring fix (...column(par["celltype_key"])) AND a container rebuild. See NOTES.md. +# +# PARAMS-FILE CAVEAT (why this reads from GitHub): +# `tw launch --params-file` is read client-side, but `method_parameters_yaml` +# is a path the WORKFLOW opens at runtime on the cloud (readYaml -> Nextflow +# file()). A local /tmp path does not exist there, and /scratch (where results +# publish) is READ-ONLY from the launch host. file() does stage http(s):// though, +# and this repo is public, so we keep the sweep in a COMMITTED file +# (scripts/run_benchmark/param_sweep/singler_params.yaml) and read it from GitHub +# via its raw URL. => the params file must be committed AND PUSHED to +# $params_branch before launching (edit the file there, not here, to change the +# sweep). This is independent of --revision below, which selects the pipeline CODE. + +# get the root of the directory +REPO_ROOT=$(git rev-parse --show-toplevel) + +# ensure that the command below is run from the root of the repository +cd "$REPO_ROOT" + +set -e + +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" +# Results publish to /scratch — created and written by the cloud compute env, so +# the launcher does NOT create it here (it is read-only from the launch host). +publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_singler" + +# The sweep lives in a committed file, read from GitHub at runtime. $params_branch +# defaults to the branch you are on; the file must be pushed there on GitHub. (This +# is independent of --revision below, which selects the pipeline CODE to run.) +params_repo="openproblems-bio/task_ist_preprocessing" +params_branch="$(git rev-parse --abbrev-ref HEAD)" +params_url="https://raw.githubusercontent.com/${params_repo}/${params_branch}/scripts/run_benchmark/param_sweep/singler_params.yaml" + +cat > /tmp/params_settings.yaml << HERE +default_methods: + - custom_segmentation + - basic_transcript_assignment + - basic_count_aggregation + - basic_qc_filter + - alpha_shapes + - normalize_by_volume + - tacco + - no_correction +segmentation_methods: + - custom_segmentation +transcript_assignment_methods: + - basic_transcript_assignment +count_aggregation_methods: + - basic_count_aggregation +qc_filtering_methods: + - basic_qc_filter +volume_calculation_methods: + - alpha_shapes +normalization_methods: + - normalize_by_volume +celltype_annotation_methods: + - tacco + - singler +expression_correction_methods: + - no_correction +gene_efficiency_correction_methods: + - no_correction +method_parameters_yaml: $params_url +HERE + +# Write the parameters to file (input_states version, NOTE: enable `-entry_name auto` for this) +cat > /tmp/params.yaml << HERE +input_states: $resources_test_s3/**/state.yaml +rename_keys: 'input_sc:output_sc;input_sp:output_sp' +save_spatial_data: false +settings: '$(yq -o json /tmp/params_settings.yaml | jq -c .)' +output_state: "state.yaml" +publish_dir: "$publish_dir" +HERE + +# Fail early with a clear message if the params file isn't reachable on GitHub yet. +if ! curl -fsSL -o /dev/null "$params_url"; then + echo "ERROR: params file not reachable at:" >&2 + echo " $params_url" >&2 + echo "Commit and push scripts/run_benchmark/param_sweep/singler_params.yaml to '$params_branch' first." >&2 + exit 1 +fi + +tw launch https://github.com/openproblems-bio/task_ist_preprocessing.git \ + --revision build/main \ + --pull-latest \ + --main-script target/nextflow/workflows/run_benchmark/main.nf \ + --workspace 167877437119966 \ + --compute-env 5hfmdCBxMRd4nHZaJKYEQZ \ + --params-file /tmp/params.yaml \ + --entry-name auto \ + --config src/base/labels_nebius.config \ + --labels task_ist_preprocessing,test,singler diff --git a/scripts/run_benchmark/param_sweep/run_test_split_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_split_nebius.sh index 0a20da769..bb63ff97b 100644 --- a/scripts/run_benchmark/param_sweep/run_test_split_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_split_nebius.sh @@ -37,7 +37,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch — created and written by the cloud compute env, so # the launcher does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_split" diff --git a/scripts/run_benchmark/param_sweep/run_test_ssam_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_ssam_nebius.sh index 7ac988081..6d0517717 100644 --- a/scripts/run_benchmark/param_sweep/run_test_ssam_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_ssam_nebius.sh @@ -30,7 +30,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch -- created and written by the cloud compute env, so # the launcher does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_ssam" diff --git a/scripts/run_benchmark/param_sweep/run_test_stardist_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_stardist_nebius.sh index 21d22c6bc..31d0d6765 100644 --- a/scripts/run_benchmark/param_sweep/run_test_stardist_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_stardist_nebius.sh @@ -27,7 +27,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch — created and written by the cloud compute env, so # the launcher does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_stardist" diff --git a/scripts/run_benchmark/param_sweep/run_test_tangram_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_tangram_nebius.sh index be7c40618..a9ddf4d95 100644 --- a/scripts/run_benchmark/param_sweep/run_test_tangram_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_tangram_nebius.sh @@ -30,7 +30,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch — created and written by the cloud compute env, so # the launcher does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_tangram" diff --git a/scripts/run_benchmark/param_sweep/run_test_watershed_nebius.sh b/scripts/run_benchmark/param_sweep/run_test_watershed_nebius.sh index 657635223..4118a4e0c 100644 --- a/scripts/run_benchmark/param_sweep/run_test_watershed_nebius.sh +++ b/scripts/run_benchmark/param_sweep/run_test_watershed_nebius.sh @@ -27,7 +27,7 @@ cd "$REPO_ROOT" set -e -resources_test_s3=s3://openproblems-data/resources_test/task_ist_preprocessing +resources_test_s3="/scratch/task_ist_preprocessing/resources_test/task_ist_preprocessing/" # Results publish to /scratch — created and written by the cloud compute env, so # the launcher does NOT create it here (it is read-only from the launch host). publish_dir="/scratch/results/runs/$(date +%Y-%m-%d_%H-%M-%S)_watershed" diff --git a/src/methods_transcript_assignment/segger/NOTES.md b/src/methods_transcript_assignment/segger/NOTES.md index 0ce302627..f3a1e138e 100644 --- a/src/methods_transcript_assignment/segger/NOTES.md +++ b/src/methods_transcript_assignment/segger/NOTES.md @@ -218,6 +218,24 @@ Nextflow runner labels: `[hightime, midcpu, highmem, gpuh100]`. ## Risk points / gotchas +- **Never start a continuation line in `script.py` with `|` — viash's Nextflow codegen + deletes it (Groovy `stripMargin`).** viash embeds `script.py` into the Nextflow module + (`target/nextflow/.../segger/main.nf`) as a Groovy string and runs it through + `.stripMargin()`, whose **default margin delimiter is `|`**: any line matching + `^\s*\|` has the leading whitespace **and the `|`** stripped. A wrapped boolean/bitwise + expression like + `n_oob = int(np.count_nonzero(\n (y_coords < 0) | (y_coords >= H)\n | (x_coords < 0) | (x_coords >= W)\n))` + becomes `... (y_coords >= H)\n (x_coords < 0) ...` in the generated module — the two + parenthesised groups then **juxtapose into a call**, so at run time Python raises + `TypeError: 'numpy.ndarray' object is not callable` (the caret points at the *first* + group, the "callable"). **This corrupts ONLY the `=nextflow=>` target**, so `viash test` / + `viash run` (the `=executable=>` target, no `stripMargin`) pass clean and the bug is + invisible until a Nextflow/Tower benchmark run. It also survives across builds: the + `build/main` executable can be correct while the `build/main` *nextflow module* is + corrupt. **Fix = put the operator at the END of the line** (`... (y_coords >= H) |` / + next line `(x_coords < 0) ...`) so no line begins with `|`; or keep it on one line. + Grep guard before committing: `grep -nE '^[[:space:]]*\|' script.py` must be empty. + (Diagnosed 2026-08-06: reproduced byte-for-byte, incl. the exact caret placement.) - **numba must use the NVIDIA (cuda-python) driver binding, or cudf/numba see 0 GPUs.** The load-bearing GPU fix: `run_segger` sets **`NUMBA_CUDA_USE_NVIDIA_BINDING=1`** for the subprocess. RAPIDS (cudf/cuml/cugraph) builds its CUDA context through the cuda-python diff --git a/src/methods_transcript_assignment/segger/script.py b/src/methods_transcript_assignment/segger/script.py index 71e1eb29d..69c0de530 100644 --- a/src/methods_transcript_assignment/segger/script.py +++ b/src/methods_transcript_assignment/segger/script.py @@ -173,9 +173,16 @@ # rounding is all that remains, and it's handled below. NOTE: this does NOT touch the separate # empty-`bd`-batch crash (a cell-free INTERIOR tile), which is intra-field, not OOB-driven, and # still needs the segger-encoder guard -- see NOTES.md. +# NB: keep the `|` operators at the END of each line -- a continuation line must NOT start +# with `|`. viash embeds this script into the Nextflow module as a Groovy string and runs it +# through `.stripMargin()`, which treats a leading `|` as the margin delimiter and DELETES it. +# A leading-`|` line like `| (x_coords < 0) ...` becomes ` (x_coords < 0) ...`, so the previous +# line's `(...)` and this line's `(...)` juxtapose into a call -> the Nextflow run dies with +# `TypeError: 'numpy.ndarray' object is not callable` while `viash test`/`viash run` (the +# executable target, no stripMargin) pass. Trailing operators sidestep it entirely. n_oob = int(np.count_nonzero( - (y_coords < 0) | (y_coords >= label_image.shape[0]) - | (x_coords < 0) | (x_coords >= label_image.shape[1]) + (y_coords < 0) | (y_coords >= label_image.shape[0]) | + (x_coords < 0) | (x_coords >= label_image.shape[1]) )) y_coords = np.clip(y_coords, 0, label_image.shape[0] - 1) x_coords = np.clip(x_coords, 0, label_image.shape[1] - 1)