#!/usr/bin/env bash

# cellbender_remove_background v4.0.1
# 
# This wrapper script is auto-generated by viash 0.9.4 and is thus a derivative
# work thereof. This software comes with ABSOLUTELY NO WARRANTY from Data
# Intuitive.
# 
# The component may contain files which fall under a different license. The
# authors of this component should specify the license in the header of such
# files, or include a separate license file detailing the licenses of all included
# files.

set -e

if [ -z "$VIASH_TEMP" ]; then
  VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMPDIR}
  VIASH_TEMP=${VIASH_TEMP:-$VIASH_TEMPDIR}
  VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMP}
  VIASH_TEMP=${VIASH_TEMP:-$TMPDIR}
  VIASH_TEMP=${VIASH_TEMP:-$TMP}
  VIASH_TEMP=${VIASH_TEMP:-$TEMPDIR}
  VIASH_TEMP=${VIASH_TEMP:-$TEMP}
  VIASH_TEMP=${VIASH_TEMP:-/tmp}
fi

# define helper functions
# ViashQuote: put quotes around non flag values
# $1     : unquoted string
# return : possibly quoted string
# examples:
#   ViashQuote --foo      # returns --foo
#   ViashQuote bar        # returns 'bar'
#   Viashquote --foo=bar  # returns --foo='bar'
function ViashQuote {
  if [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+=.+$ ]]; then
    echo "$1" | sed "s#=\(.*\)#='\1'#"
  elif [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+$ ]]; then
    echo "$1"
  else
    echo "'$1'"
  fi
}
# ViashRemoveFlags: Remove leading flag
# $1     : string with a possible leading flag
# return : string without possible leading flag
# examples:
#   ViashRemoveFlags --foo=bar  # returns bar
function ViashRemoveFlags {
  echo "$1" | sed 's/^--*[a-zA-Z0-9_\-]*=//'
}
# ViashSourceDir: return the path of a bash file, following symlinks
# usage   : ViashSourceDir ${BASH_SOURCE[0]}
# $1      : Should always be set to ${BASH_SOURCE[0]}
# returns : The absolute path of the bash file
function ViashSourceDir {
  local source="$1"
  while [ -h "$source" ]; do
    local dir="$( cd -P "$( dirname "$source" )" >/dev/null 2>&1 && pwd )"
    source="$(readlink "$source")"
    [[ $source != /* ]] && source="$dir/$source"
  done
  cd -P "$( dirname "$source" )" >/dev/null 2>&1 && pwd
}
# ViashFindTargetDir: return the path of the '.build.yaml' file, following symlinks
# usage   : ViashFindTargetDir 'ScriptPath'
# $1      : The location from where to start the upward search
# returns : The absolute path of the '.build.yaml' file
function ViashFindTargetDir {
  local source="$1"
  while [[ "$source" != "" && ! -e "$source/.build.yaml" ]]; do
    source=${source%/*}
  done
  echo $source
}
# see https://en.wikipedia.org/wiki/Syslog#Severity_level
VIASH_LOGCODE_EMERGENCY=0
VIASH_LOGCODE_ALERT=1
VIASH_LOGCODE_CRITICAL=2
VIASH_LOGCODE_ERROR=3
VIASH_LOGCODE_WARNING=4
VIASH_LOGCODE_NOTICE=5
VIASH_LOGCODE_INFO=6
VIASH_LOGCODE_DEBUG=7
VIASH_VERBOSITY=$VIASH_LOGCODE_NOTICE

# ViashLog: Log events depending on the verbosity level
# usage: ViashLog 1 alert Oh no something went wrong!
# $1: required verbosity level
# $2: display tag
# $3+: messages to display
# stdout: Your input, prepended by '[$2] '.
function ViashLog {
  local required_level="$1"
  local display_tag="$2"
  shift 2
  if [ $VIASH_VERBOSITY -ge $required_level ]; then
    >&2 echo "[$display_tag]" "$@"
  fi
}

# ViashEmergency: log events when the system is unstable
# usage: ViashEmergency Oh no something went wrong.
# stdout: Your input, prepended by '[emergency] '.
function ViashEmergency {
  ViashLog $VIASH_LOGCODE_EMERGENCY emergency "$@"
}

# ViashAlert: log events when actions must be taken immediately (e.g. corrupted system database)
# usage: ViashAlert Oh no something went wrong.
# stdout: Your input, prepended by '[alert] '.
function ViashAlert {
  ViashLog $VIASH_LOGCODE_ALERT alert "$@"
}

# ViashCritical: log events when a critical condition occurs
# usage: ViashCritical Oh no something went wrong.
# stdout: Your input, prepended by '[critical] '.
function ViashCritical {
  ViashLog $VIASH_LOGCODE_CRITICAL critical "$@"
}

# ViashError: log events when an error condition occurs
# usage: ViashError Oh no something went wrong.
# stdout: Your input, prepended by '[error] '.
function ViashError {
  ViashLog $VIASH_LOGCODE_ERROR error "$@"
}

# ViashWarning: log potentially abnormal events
# usage: ViashWarning Something may have gone wrong.
# stdout: Your input, prepended by '[warning] '.
function ViashWarning {
  ViashLog $VIASH_LOGCODE_WARNING warning "$@"
}

# ViashNotice: log significant but normal events
# usage: ViashNotice This just happened.
# stdout: Your input, prepended by '[notice] '.
function ViashNotice {
  ViashLog $VIASH_LOGCODE_NOTICE notice "$@"
}

# ViashInfo: log normal events
# usage: ViashInfo This just happened.
# stdout: Your input, prepended by '[info] '.
function ViashInfo {
  ViashLog $VIASH_LOGCODE_INFO info "$@"
}

# ViashDebug: log all events, for debugging purposes
# usage: ViashDebug This just happened.
# stdout: Your input, prepended by '[debug] '.
function ViashDebug {
  ViashLog $VIASH_LOGCODE_DEBUG debug "$@"
}

# find source folder of this component
VIASH_META_RESOURCES_DIR=`ViashSourceDir ${BASH_SOURCE[0]}`

# find the root of the built components & dependencies
VIASH_TARGET_DIR=`ViashFindTargetDir $VIASH_META_RESOURCES_DIR`

# define meta fields
VIASH_META_NAME="cellbender_remove_background"
VIASH_META_FUNCTIONALITY_NAME="cellbender_remove_background"
VIASH_META_EXECUTABLE="$VIASH_META_RESOURCES_DIR/$VIASH_META_NAME"
VIASH_META_CONFIG="$VIASH_META_RESOURCES_DIR/.config.vsh.yaml"
VIASH_META_TEMP_DIR="$VIASH_TEMP"



# initialise variables
VIASH_MODE='run'
VIASH_ENGINE_ID='docker'

######## Helper functions for setting up Docker images for viash ########
# expects: ViashDockerBuild

# ViashDockerInstallationCheck: check whether Docker is installed correctly
#
# examples:
#   ViashDockerInstallationCheck
function ViashDockerInstallationCheck {
  ViashDebug "Checking whether Docker is installed"
  if [ ! command -v docker &> /dev/null ]; then
    ViashCritical "Docker doesn't seem to be installed. See 'https://docs.docker.com/get-docker/' for instructions."
    exit 1
  fi

  ViashDebug "Checking whether the Docker daemon is running"
  local save=$-; set +e
  local docker_version=$(docker version --format '{{.Client.APIVersion}}' 2> /dev/null)
  local out=$?
  [[ $save =~ e ]] && set -e
  if [ $out -ne 0 ]; then
    ViashCritical "Docker daemon does not seem to be running. Try one of the following:"
    ViashCritical "- Try running 'dockerd' in the command line"
    ViashCritical "- See https://docs.docker.com/config/daemon/"
    exit 1
  fi
}

# ViashDockerRemoteTagCheck: check whether a Docker image is available 
# on a remote. Assumes `docker login` has been performed, if relevant.
#
# $1                  : image identifier with format `[registry/]image[:tag]`
# exit code $?        : whether or not the image was found
# examples:
#   ViashDockerRemoteTagCheck python:latest
#   echo $?                                     # returns '0'
#   ViashDockerRemoteTagCheck sdaizudceahifu
#   echo $?                                     # returns '1'
function ViashDockerRemoteTagCheck {
  docker manifest inspect $1 > /dev/null 2> /dev/null
}

# ViashDockerLocalTagCheck: check whether a Docker image is available locally
#
# $1                  : image identifier with format `[registry/]image[:tag]`
# exit code $?        : whether or not the image was found
# examples:
#   docker pull python:latest
#   ViashDockerLocalTagCheck python:latest
#   echo $?                                     # returns '0'
#   ViashDockerLocalTagCheck sdaizudceahifu
#   echo $?                                     # returns '1'
function ViashDockerLocalTagCheck {
  [ -n "$(docker images -q $1)" ]
}

# ViashDockerPull: pull a Docker image
#
# $1                  : image identifier with format `[registry/]image[:tag]`
# exit code $?        : whether or not the image was found
# examples:
#   ViashDockerPull python:latest
#   echo $?                                     # returns '0'
#   ViashDockerPull sdaizudceahifu
#   echo $?                                     # returns '1'
function ViashDockerPull {
  ViashNotice "Checking if Docker image is available at '$1'"
  if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then
    docker pull $1 && return 0 || return 1
  else
    local save=$-; set +e
    docker pull $1 2> /dev/null > /dev/null
    local out=$?
    [[ $save =~ e ]] && set -e
    if [ $out -ne 0 ]; then
      ViashWarning "Could not pull from '$1'. Docker image doesn't exist or is not accessible."
    fi
    return $out
  fi
}

# ViashDockerPush: push a Docker image
#
# $1                  : image identifier with format `[registry/]image[:tag]`
# exit code $?        : whether or not the image was found
# examples:
#   ViashDockerPush python:latest
#   echo $?                                     # returns '0'
#   ViashDockerPush sdaizudceahifu
#   echo $?                                     # returns '1'
function ViashDockerPush {
  ViashNotice "Pushing image to '$1'"
  local save=$-; set +e
  local out
  if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then
    docker push $1
    out=$?
  else
    docker push $1 2> /dev/null > /dev/null
    out=$?
  fi
  [[ $save =~ e ]] && set -e
  if [ $out -eq 0 ]; then
    ViashNotice "Container '$1' push succeeded."
  else
    ViashError "Container '$1' push errored. You might not be logged in or have the necessary permissions."
  fi
  return $out
}

# ViashDockerPullElseBuild: pull a Docker image, else build it
#
# $1                  : image identifier with format `[registry/]image[:tag]`
# ViashDockerBuild    : a Bash function which builds a docker image, takes image identifier as argument.
# examples:
#   ViashDockerPullElseBuild mynewcomponent
function ViashDockerPullElseBuild {
  local save=$-; set +e
  ViashDockerPull $1
  local out=$?
  [[ $save =~ e ]] && set -e
  if [ $out -ne 0 ]; then
    ViashDockerBuild $@
  fi
}

# ViashDockerSetup: create a Docker image, according to specified docker setup strategy
#
# $1          : image identifier with format `[registry/]image[:tag]`
# $2          : docker setup strategy, see DockerSetupStrategy.scala
# examples:
#   ViashDockerSetup mynewcomponent alwaysbuild
function ViashDockerSetup {
  local image_id="$1"
  local setup_strategy="$2"
  if [ "$setup_strategy" == "alwaysbuild" -o "$setup_strategy" == "build" -o "$setup_strategy" == "b" ]; then
    ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id")
  elif [ "$setup_strategy" == "alwayspull" -o "$setup_strategy" == "pull" -o "$setup_strategy" == "p" ]; then
    ViashDockerPull $image_id
  elif [ "$setup_strategy" == "alwayspullelsebuild" -o "$setup_strategy" == "pullelsebuild" ]; then
    ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id")
  elif [ "$setup_strategy" == "alwayspullelsecachedbuild" -o "$setup_strategy" == "pullelsecachedbuild" ]; then
    ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id")
  elif [ "$setup_strategy" == "alwayscachedbuild" -o "$setup_strategy" == "cachedbuild" -o "$setup_strategy" == "cb" ]; then
    ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id")
  elif [[ "$setup_strategy" =~ ^ifneedbe ]]; then
    local save=$-; set +e
    ViashDockerLocalTagCheck $image_id
    local outCheck=$?
    [[ $save =~ e ]] && set -e
    if [ $outCheck -eq 0 ]; then
      ViashInfo "Image $image_id already exists"
    elif [ "$setup_strategy" == "ifneedbebuild" ]; then
      ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id")
    elif [ "$setup_strategy" == "ifneedbecachedbuild" ]; then
      ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id")
    elif [ "$setup_strategy" == "ifneedbepull" ]; then
      ViashDockerPull $image_id
    elif [ "$setup_strategy" == "ifneedbepullelsebuild" ]; then
      ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id")
    elif [ "$setup_strategy" == "ifneedbepullelsecachedbuild" ]; then
      ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id")
    else
      ViashError "Unrecognised Docker strategy: $setup_strategy"
      exit 1
    fi
  elif [ "$setup_strategy" == "push" -o "$setup_strategy" == "forcepush" -o "$setup_strategy" == "alwayspush" ]; then
    ViashDockerPush "$image_id"
  elif [ "$setup_strategy" == "pushifnotpresent" -o "$setup_strategy" == "gentlepush" -o "$setup_strategy" == "maybepush" ]; then
    local save=$-; set +e
    ViashDockerRemoteTagCheck $image_id
    local outCheck=$?
    [[ $save =~ e ]] && set -e
    if [ $outCheck -eq 0 ]; then
      ViashNotice "Container '$image_id' exists, doing nothing."
    else
      ViashNotice "Container '$image_id' does not yet exist."
      ViashDockerPush "$image_id"
    fi
  elif [ "$setup_strategy" == "donothing" -o "$setup_strategy" == "meh" ]; then
    ViashNotice "Skipping setup."
  else
    ViashError "Unrecognised Docker strategy: $setup_strategy"
    exit 1
  fi
}

# ViashDockerCheckCommands: Check whether a docker container has the required commands
#
# $1                  : image identifier with format `[registry/]image[:tag]`
# $@                  : commands to verify being present
# examples:
#   ViashDockerCheckCommands bash:4.0 bash ps foo
function ViashDockerCheckCommands {
  local image_id="$1"
  shift 1
  local commands="$@"
  local save=$-; set +e
  local missing # mark 'missing' as local in advance, otherwise the exit code of the command will be missing and always be '0'
  missing=$(docker run --rm --entrypoint=sh "$image_id" -c "for command in $commands; do command -v \$command >/dev/null 2>&1; if [ \$? -ne 0 ]; then echo \$command; exit 1; fi; done")
  local outCheck=$?
  [[ $save =~ e ]] && set -e
  if [ $outCheck -ne 0 ]; then
  	ViashError "Docker container '$image_id' does not contain command '$missing'."
  	exit 1
  fi
}

# ViashDockerBuild: build a docker image
# $1                               : image identifier with format `[registry/]image[:tag]`
# $...                             : additional arguments to pass to docker build
# $VIASH_META_TEMP_DIR             : temporary directory to store dockerfile & optional resources in
# $VIASH_META_NAME                 : name of the component
# $VIASH_META_RESOURCES_DIR        : directory containing the resources
# $VIASH_VERBOSITY                 : verbosity level
# exit code $?                     : whether or not the image was built successfully
function ViashDockerBuild {
  local image_id="$1"
  shift 1

  # create temporary directory to store dockerfile & optional resources in
  local tmpdir=$(mktemp -d "$VIASH_META_TEMP_DIR/dockerbuild-$VIASH_META_NAME-XXXXXX")
  local dockerfile="$tmpdir/Dockerfile"
  function clean_up {
    rm -rf "$tmpdir"
  }
  trap clean_up EXIT

  # store dockerfile and resources
  ViashDockerfile "$VIASH_ENGINE_ID" > "$dockerfile"

  # generate the build command
  local docker_build_cmd="docker build -t '$image_id' $@ '$VIASH_META_RESOURCES_DIR' -f '$dockerfile'"

  # build the container
  ViashNotice "Building container '$image_id' with Dockerfile"
  ViashInfo "$docker_build_cmd"
  local save=$-; set +e
  if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then
    eval $docker_build_cmd
  else
    eval $docker_build_cmd &> "$tmpdir/docker_build.log"
  fi

  # check exit code
  local out=$?
  [[ $save =~ e ]] && set -e
  if [ $out -ne 0 ]; then
    ViashError "Error occurred while building container '$image_id'"
    if [ $VIASH_VERBOSITY -lt $VIASH_LOGCODE_INFO ]; then
      ViashError "Transcript: --------------------------------"
      cat "$tmpdir/docker_build.log"
      ViashError "End of transcript --------------------------"
    fi
    exit 1
  fi
}

######## End of helper functions for setting up Docker images for viash ########

# ViashDockerFile: print the dockerfile to stdout
# $1    : engine identifier
# return : dockerfile required to run this component
# examples:
#   ViashDockerFile
function ViashDockerfile {
  local engine_id="$1"

  if [[ "$engine_id" == "docker" ]]; then
    cat << 'VIASHDOCKER'
FROM nvcr.io/nvidia/cuda:11.8.0-devel-ubuntu22.04
ENTRYPOINT []
ENV PYENV_ROOT="/root/.pyenv"
ENV PATH="$PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH"
ENV PYTHON_VERSION=3.7.16
RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget ca-certificates curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev mecab-ipadic-utf8 git \
&& curl https://pyenv.run | bash \
&& pyenv update \
&& pyenv install $PYTHON_VERSION \
&& pyenv global $PYTHON_VERSION \
&& apt-get clean

RUN pip install --upgrade pip && \
  pip install --upgrade --no-cache-dir "lxml~=4.8.0" "mudata~=0.2.1" "cellbender~=0.3.0"

LABEL org.opencontainers.image.description="Companion container for running component correction cellbender_remove_background"
LABEL org.opencontainers.image.created="2026-02-04T09:06:15Z"
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline"
LABEL org.opencontainers.image.revision="e943ae3d1512ded126303c9481cb554d0dd38c92"
LABEL org.opencontainers.image.version="v4.0.1"

VIASHDOCKER
  fi
}

# ViashDockerBuildArgs: return the arguments to pass to docker build
# $1    : engine identifier
# return : arguments to pass to docker build
function ViashDockerBuildArgs {
  local engine_id="$1"

  if [[ "$engine_id" == "docker" ]]; then
    echo ""
  fi
}

# ViashAbsolutePath: generate absolute path from relative path
# borrowed from https://stackoverflow.com/a/21951256
# $1     : relative filename
# return : absolute path
# examples:
#   ViashAbsolutePath some_file.txt   # returns /path/to/some_file.txt
#   ViashAbsolutePath /foo/bar/..     # returns /foo
function ViashAbsolutePath {
  local thePath
  local parr
  local outp
  local len
  if [[ ! "$1" =~ ^/ ]]; then
    thePath="$PWD/$1"
  else
    thePath="$1"
  fi
  echo "$thePath" | (
    IFS=/
    read -a parr
    declare -a outp
    for i in "${parr[@]}"; do
      case "$i" in
      ''|.) continue ;;
      ..)
        len=${#outp[@]}
        if ((len==0)); then
          continue
        else
          unset outp[$((len-1))]
        fi
        ;;
      *)
        len=${#outp[@]}
        outp[$len]="$i"
      ;;
      esac
    done
    echo /"${outp[*]}"
  )
}
# ViashDockerAutodetectMount: auto configuring docker mounts from parameters
# $1                             : The parameter value
# returns                        : New parameter
# $VIASH_DIRECTORY_MOUNTS        : Added another parameter to be passed to docker
# $VIASH_DOCKER_AUTOMOUNT_PREFIX : The prefix to be used for the automounts
# examples:
#   ViashDockerAutodetectMount /path/to/bar      # returns '/viash_automount/path/to/bar'
#   ViashDockerAutodetectMountArg /path/to/bar   # returns '--volume="/path/to:/viash_automount/path/to"'
function ViashDockerAutodetectMount {
  local abs_path=$(ViashAbsolutePath "$1")
  local mount_source
  local base_name
  if [ -d "$abs_path" ]; then
    mount_source="$abs_path"
    base_name=""
  else
    mount_source=`dirname "$abs_path"`
    base_name=`basename "$abs_path"`
  fi
  local mount_target="$VIASH_DOCKER_AUTOMOUNT_PREFIX$mount_source"
  if [ -z "$base_name" ]; then
    echo "$mount_target"
  else
    echo "$mount_target/$base_name"
  fi
}
function ViashDockerAutodetectMountArg {
  local abs_path=$(ViashAbsolutePath "$1")
  local mount_source
  local base_name
  if [ -d "$abs_path" ]; then
    mount_source="$abs_path"
    base_name=""
  else
    mount_source=`dirname "$abs_path"`
    base_name=`basename "$abs_path"`
  fi
  local mount_target="$VIASH_DOCKER_AUTOMOUNT_PREFIX$mount_source"
  ViashDebug "ViashDockerAutodetectMountArg $1 -> $mount_source -> $mount_target"
  echo "--volume=\"$mount_source:$mount_target\""
}
function ViashDockerStripAutomount {
  local abs_path=$(ViashAbsolutePath "$1")
  echo "${abs_path#$VIASH_DOCKER_AUTOMOUNT_PREFIX}"
}
# initialise variables
VIASH_DIRECTORY_MOUNTS=()

# configure default docker automount prefix if it is unset
if [ -z "${VIASH_DOCKER_AUTOMOUNT_PREFIX+x}" ]; then
  VIASH_DOCKER_AUTOMOUNT_PREFIX="/viash_automount"
fi

# initialise docker variables
VIASH_DOCKER_RUN_ARGS=(-i --rm)


# ViashHelp: Display helpful explanation about this executable
function ViashHelp {
  echo "cellbender_remove_background v4.0.1"
  echo ""
  echo "Eliminating technical artifacts from high-throughput single-cell RNA sequencing"
  echo "data."
  echo ""
  echo "This module removes counts due to ambient RNA molecules and random barcode"
  echo "swapping from (raw) UMI-based scRNA-seq count matrices."
  echo "At the moment, only the count matrices produced by the CellRanger count pipeline"
  echo "is supported. Support for additional tools and protocols"
  echo "will be added in the future. A quick start tutorial can be found here."
  echo ""
  echo "Fleming et al. 2022, bioRxiv."
  echo ""
  echo "Inputs:"
  echo "    -i, --input"
  echo "        type: file, required parameter, file must exist"
  echo "        example: input.h5mu"
  echo "        Input h5mu file. Data file on which to run tool. Data must be"
  echo "        un-filtered: it should include empty droplets."
  echo ""
  echo "    --modality"
  echo "        type: string"
  echo "        default: rna"
  echo "        List of modalities to process."
  echo ""
  echo "Outputs:"
  echo "    -o, --output"
  echo "        type: file, required parameter, output, file must exist"
  echo "        example: output.h5mu"
  echo "        Full count matrix as an h5mu file, with background RNA removed. This"
  echo "        file contains all the original droplet barcodes."
  echo ""
  echo "    --layer_output"
  echo "        type: string"
  echo "        default: cellbender_corrected"
  echo "        Output layer"
  echo ""
  echo "    --obs_background_fraction"
  echo "        type: string"
  echo "        default: cellbender_background_fraction"
  echo ""
  echo "    --obs_cell_probability"
  echo "        type: string"
  echo "        default: cellbender_cell_probability"
  echo ""
  echo "    --obs_cell_size"
  echo "        type: string"
  echo "        default: cellbender_cell_size"
  echo ""
  echo "    --obs_droplet_efficiency"
  echo "        type: string"
  echo "        default: cellbender_droplet_efficiency"
  echo "        Name of the column in the .obs dataframe to store the droplet"
  echo "        efficiencies in."
  echo ""
  echo "    --obs_latent_scale"
  echo "        type: string"
  echo "        default: cellbender_latent_scale"
  echo ""
  echo "    --var_ambient_expression"
  echo "        type: string"
  echo "        default: cellbender_ambient_expression"
  echo ""
  echo "    --obsm_gene_expression_encoding"
  echo "        type: string"
  echo "        default: cellbender_gene_expression_encoding"
  echo ""
  echo "    --output_compression"
  echo "        type: string"
  echo "        example: gzip"
  echo "        choices: [ gzip, lzf ]"
  echo "        Compression format to use for the output AnnData and/or Mudata objects."
  echo "        By default no compression is applied."
  echo ""
  echo "Arguments:"
  echo "    --expected_cells_from_qc"
  echo "        type: boolean"
  echo "        default: false"
  echo "        Will use the Cell Ranger QC to determine the estimated number of cells"
  echo ""
  echo "    --expected_cells"
  echo "        type: integer"
  echo "        example: 1000"
  echo "        Number of cells expected in the dataset (a rough estimate within a"
  echo "        factor of 2 is sufficient)."
  echo ""
  echo "    --total_droplets_included"
  echo "        type: integer"
  echo "        example: 25000"
  echo "        The number of droplets from the rank-ordered UMI plot"
  echo "        that will have their cell probabilities inferred as an"
  echo "        output. Include the droplets which might contain cells."
  echo "        Droplets beyond TOTAL_DROPLETS_INCLUDED should be"
  echo "        'surely empty' droplets."
  echo ""
  echo "    --force_cell_umi_prior"
  echo "        type: integer"
  echo "        Ignore CellBender's heuristic prior estimation, and use this prior for"
  echo "        UMI counts in cells."
  echo ""
  echo "    --force_empty_umi_prior"
  echo "        type: integer"
  echo "        Ignore CellBender's heuristic prior estimation, and use this prior for"
  echo "        UMI counts in empty droplets."
  echo ""
  echo "    --model"
  echo "        type: string"
  echo "        default: full"
  echo "        choices: [ naive, simple, ambient, swapping, full ]"
  echo "        Which model is being used for count data."
  echo "        * 'naive' subtracts the estimated ambient profile."
  echo "        * 'simple' does not model either ambient RNA or random barcode swapping"
  echo "        (for debugging purposes -- not recommended)."
  echo "        * 'ambient' assumes background RNA is incorporated into droplets."
  echo "        * 'swapping' assumes background RNA comes from random barcode swapping"
  echo "        (via PCR chimeras)."
  echo "        * 'full' uses a combined ambient and swapping model."
  echo ""
  echo "    --epochs"
  echo "        type: integer"
  echo "        default: 150"
  echo "        Number of epochs to train."
  echo ""
  echo "    --low_count_threshold"
  echo "        type: integer"
  echo "        default: 5"
  echo "        Droplets with UMI counts below this number are completely"
  echo "        excluded from the analysis. This can help identify the correct"
  echo "        prior for empty droplet counts in the rare case where empty"
  echo "        counts are extremely high (over 200)."
  echo ""
  echo "    --z_dim"
  echo "        type: integer"
  echo "        default: 64"
  echo "        Dimension of latent variable z."
  echo ""
  echo "    --z_layers"
  echo "        type: integer, multiple values allowed"
  echo "        default: 512"
  echo "        Dimension of hidden layers in the encoder for z."
  echo ""
  echo "    --training_fraction"
  echo "        type: double"
  echo "        default: 0.9"
  echo "        Training detail: the fraction of the data used for training."
  echo "        The rest is never seen by the inference algorithm. Speeds up learning."
  echo ""
  echo "    --empty_drop_training_fraction"
  echo "        type: double"
  echo "        default: 0.2"
  echo "        Training detail: the fraction of the training data each epoch that"
  echo "        is drawn (randomly sampled) from surely empty droplets."
  echo ""
  echo "    --ignore_features"
  echo "        type: integer, multiple values allowed"
  echo "        Integer indices of features to ignore entirely. In the output"
  echo "        count matrix, the counts for these features will be unchanged."
  echo ""
  echo "    --fpr"
  echo "        type: double, multiple values allowed"
  echo "        default: 0.01"
  echo "        Target 'delta' false positive rate in [0, 1). Use 0 for a cohort"
  echo "        of samples which will be jointly analyzed for differential expression."
  echo "        A false positive is a true signal count that is erroneously removed."
  echo "        More background removal is accompanied by more signal removal at"
  echo "        high values of FPR. You can specify multiple values, which will"
  echo "        create multiple output files."
  echo ""
  echo "    --exclude_feature_types"
  echo "        type: string, multiple values allowed"
  echo "        Feature types to ignore during the analysis. These features will"
  echo "        be left unchanged in the output file."
  echo ""
  echo "    --projected_ambient_count_threshold"
  echo "        type: double"
  echo "        default: 0.1"
  echo "        Controls how many features are included in the analysis, which"
  echo "        can lead to a large speedup. If a feature is expected to have less"
  echo "        than PROJECTED_AMBIENT_COUNT_THRESHOLD counts total in all cells"
  echo "        (summed), then that gene is excluded, and it will be unchanged"
  echo "        in the output count matrix. For example,"
  echo "        PROJECTED_AMBIENT_COUNT_THRESHOLD = 0 will include all features"
  echo "        which have even a single count in any empty droplet."
  echo ""
  echo "    --learning_rate"
  echo "        type: double"
  echo "        default: 1.0E-4"
  echo "        Training detail: lower learning rate for inference."
  echo "        A OneCycle learning rate schedule is used, where the"
  echo "        upper learning rate is ten times this value. (For this"
  echo "        value, probably do not exceed 1e-3)."
  echo ""
  echo "    --final_elbo_fail_fraction"
  echo "        type: double"
  echo "        Training is considered to have failed if"
  echo "        (best_test_ELBO - final_test_ELBO)/(best_test_ELBO - initial_test_ELBO)"
  echo "        > FINAL_ELBO_FAIL_FRACTION."
  echo "        Training will automatically re-run if --num-training-tries > 1."
  echo "        By default, will not fail training based on final_training_ELBO."
  echo ""
  echo "    --epoch_elbo_fail_fraction"
  echo "        type: double"
  echo "        Training is considered to have failed if"
  echo "        (previous_epoch_test_ELBO -"
  echo "        current_epoch_test_ELBO)/(previous_epoch_test_ELBO - initial_train_ELBO)"
  echo "        > EPOCH_ELBO_FAIL_FRACTION."
  echo "        Training will automatically re-run if --num-training-tries > 1."
  echo "        By default, will not fail training based on epoch_training_ELBO."
  echo ""
  echo "    --num_training_tries"
  echo "        type: integer"
  echo "        default: 1"
  echo "        Number of times to attempt to train the model. At each subsequent"
  echo "        attempt,"
  echo "        the learning rate is multiplied by LEARNING_RATE_RETRY_MULT."
  echo ""
  echo "    --learning_rate_retry_mult"
  echo "        type: double"
  echo "        default: 0.2"
  echo "        Learning rate is multiplied by this amount each time a new training"
  echo "        attempt is made. (This parameter is only used if training fails based"
  echo "        on EPOCH_ELBO_FAIL_FRACTION or FINAL_ELBO_FAIL_FRACTION and"
  echo "        NUM_TRAINING_TRIES is > 1.)"
  echo ""
  echo "    --posterior_batch_size"
  echo "        type: integer"
  echo "        default: 128"
  echo "        Training detail: size of batches when creating the posterior."
  echo "        Reduce this to avoid running out of GPU memory creating the posterior"
  echo "        (will be slower)."
  echo ""
  echo "    --posterior_regulation"
  echo "        type: string"
  echo "        choices: [ PRq, PRmu, PRmu_gene ]"
  echo "        Posterior regularization method. (For experts: not required for normal"
  echo "        usage,"
  echo "        see documentation)."
  echo "        * PRq is approximate quantile-targeting."
  echo "        * PRmu is approximate mean-targeting aggregated over genes (behavior of"
  echo "        v0.2.0)."
  echo "        * PRmu_gene is approximate mean-targeting per gene."
  echo ""
  echo "    --alpha"
  echo "        type: double"
  echo "        Tunable parameter alpha for the PRq posterior regularization method"
  echo "        (not normally used: see documentation)."
  echo ""
  echo "    --q"
  echo "        type: double"
  echo "        Tunable parameter q for the CDF threshold estimation method (not"
  echo "        normally used: see documentation)."
  echo ""
  echo "    --estimator"
  echo "        type: string"
  echo "        default: mckp"
  echo "        choices: [ map, mean, cdf, sample, mckp ]"
  echo "        Output denoised count estimation method. (For experts: not required"
  echo "        for normal usage, see documentation)."
  echo ""
  echo "    --estimator_multiple_cpu"
  echo "        type: boolean_true"
  echo "        Including the flag --estimator-multiple-cpu will use more than one"
  echo "        CPU to compute the MCKP output count estimator in parallel (does nothing"
  echo "        for other estimators)."
  echo ""
  echo "    --constant_learning_rate"
  echo "        type: boolean"
  echo "        Including the flag --constant-learning-rate will use the ClippedAdam"
  echo "        optimizer instead of the OneCycleLR learning rate schedule, which is"
  echo "        the default. Learning is faster with the OneCycleLR schedule."
  echo "        However, training can easily be continued from a checkpoint for more"
  echo "        epochs than the initial command specified when using ClippedAdam. On"
  echo "        the other hand, if using the OneCycleLR schedule with 150 epochs"
  echo "        specified, it is not possible to pick up from that final checkpoint"
  echo "        and continue training until 250 epochs."
  echo ""
  echo "    --debug"
  echo "        type: boolean_true"
  echo "        Including the flag --debug will log extra messages useful for debugging."
  echo ""
  echo "    --cuda"
  echo "        type: boolean_true"
  echo "        Including the flag --cuda will run the inference on a"
  echo "        GPU."
  echo ""
  echo "Viash built in Computational Requirements:"
  echo "    ---cpus=INT"
  echo "        Number of CPUs to use"
  echo "    ---memory=STRING"
  echo "        Amount of memory to use. Examples: 4GB, 3MiB."
  echo ""
  echo "Viash built in Docker:"
  echo "    ---setup=STRATEGY"
  echo "        Setup the docker container. Options are: alwaysbuild, alwayscachedbuild, ifneedbebuild, ifneedbecachedbuild, alwayspull, alwayspullelsebuild, alwayspullelsecachedbuild, ifneedbepull, ifneedbepullelsebuild, ifneedbepullelsecachedbuild, push, pushifnotpresent, donothing."
  echo "        Default: ifneedbepullelsecachedbuild"
  echo "    ---dockerfile"
  echo "        Print the dockerfile to stdout."
  echo "    ---docker_run_args=ARG"
  echo "        Provide runtime arguments to Docker. See the documentation on \`docker run\` for more information."
  echo "    ---docker_image_id"
  echo "        Print the docker image id to stdout."
  echo "    ---debug"
  echo "        Enter the docker container for debugging purposes."
  echo ""
  echo "Viash built in Engines:"
  echo "    ---engine=ENGINE_ID"
  echo "        Specify the engine to use. Options are: docker, native."
  echo "        Default: docker"
}

# initialise array
VIASH_POSITIONAL_ARGS=''

while [[ $# -gt 0 ]]; do
    case "$1" in
        -h|--help)
            ViashHelp
            exit
            ;;
        ---v|---verbose)
            let "VIASH_VERBOSITY=VIASH_VERBOSITY+1"
            shift 1
            ;;
        ---verbosity)
            VIASH_VERBOSITY="$2"
            shift 2
            ;;
        ---verbosity=*)
            VIASH_VERBOSITY="$(ViashRemoveFlags "$1")"
            shift 1
            ;;
        --version)
            echo "cellbender_remove_background v4.0.1"
            exit
            ;;
        --input)
            [ -n "$VIASH_PAR_INPUT" ] && ViashError Bad arguments for option \'--input\': \'$VIASH_PAR_INPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_INPUT="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --input=*)
            [ -n "$VIASH_PAR_INPUT" ] && ViashError Bad arguments for option \'--input=*\': \'$VIASH_PAR_INPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_INPUT=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        -i)
            [ -n "$VIASH_PAR_INPUT" ] && ViashError Bad arguments for option \'-i\': \'$VIASH_PAR_INPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_INPUT="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to -i. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --modality)
            [ -n "$VIASH_PAR_MODALITY" ] && ViashError Bad arguments for option \'--modality\': \'$VIASH_PAR_MODALITY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_MODALITY="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --modality. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --modality=*)
            [ -n "$VIASH_PAR_MODALITY" ] && ViashError Bad arguments for option \'--modality=*\': \'$VIASH_PAR_MODALITY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_MODALITY=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --output)
            [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--output\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OUTPUT="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --output. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --output=*)
            [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--output=*\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OUTPUT=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        -o)
            [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'-o\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OUTPUT="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to -o. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --layer_output)
            [ -n "$VIASH_PAR_LAYER_OUTPUT" ] && ViashError Bad arguments for option \'--layer_output\': \'$VIASH_PAR_LAYER_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_LAYER_OUTPUT="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --layer_output. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --layer_output=*)
            [ -n "$VIASH_PAR_LAYER_OUTPUT" ] && ViashError Bad arguments for option \'--layer_output=*\': \'$VIASH_PAR_LAYER_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_LAYER_OUTPUT=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --obs_background_fraction)
            [ -n "$VIASH_PAR_OBS_BACKGROUND_FRACTION" ] && ViashError Bad arguments for option \'--obs_background_fraction\': \'$VIASH_PAR_OBS_BACKGROUND_FRACTION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBS_BACKGROUND_FRACTION="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_background_fraction. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --obs_background_fraction=*)
            [ -n "$VIASH_PAR_OBS_BACKGROUND_FRACTION" ] && ViashError Bad arguments for option \'--obs_background_fraction=*\': \'$VIASH_PAR_OBS_BACKGROUND_FRACTION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBS_BACKGROUND_FRACTION=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --obs_cell_probability)
            [ -n "$VIASH_PAR_OBS_CELL_PROBABILITY" ] && ViashError Bad arguments for option \'--obs_cell_probability\': \'$VIASH_PAR_OBS_CELL_PROBABILITY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBS_CELL_PROBABILITY="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_cell_probability. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --obs_cell_probability=*)
            [ -n "$VIASH_PAR_OBS_CELL_PROBABILITY" ] && ViashError Bad arguments for option \'--obs_cell_probability=*\': \'$VIASH_PAR_OBS_CELL_PROBABILITY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBS_CELL_PROBABILITY=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --obs_cell_size)
            [ -n "$VIASH_PAR_OBS_CELL_SIZE" ] && ViashError Bad arguments for option \'--obs_cell_size\': \'$VIASH_PAR_OBS_CELL_SIZE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBS_CELL_SIZE="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_cell_size. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --obs_cell_size=*)
            [ -n "$VIASH_PAR_OBS_CELL_SIZE" ] && ViashError Bad arguments for option \'--obs_cell_size=*\': \'$VIASH_PAR_OBS_CELL_SIZE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBS_CELL_SIZE=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --obs_droplet_efficiency)
            [ -n "$VIASH_PAR_OBS_DROPLET_EFFICIENCY" ] && ViashError Bad arguments for option \'--obs_droplet_efficiency\': \'$VIASH_PAR_OBS_DROPLET_EFFICIENCY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBS_DROPLET_EFFICIENCY="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_droplet_efficiency. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --obs_droplet_efficiency=*)
            [ -n "$VIASH_PAR_OBS_DROPLET_EFFICIENCY" ] && ViashError Bad arguments for option \'--obs_droplet_efficiency=*\': \'$VIASH_PAR_OBS_DROPLET_EFFICIENCY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBS_DROPLET_EFFICIENCY=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --obs_latent_scale)
            [ -n "$VIASH_PAR_OBS_LATENT_SCALE" ] && ViashError Bad arguments for option \'--obs_latent_scale\': \'$VIASH_PAR_OBS_LATENT_SCALE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBS_LATENT_SCALE="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --obs_latent_scale. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --obs_latent_scale=*)
            [ -n "$VIASH_PAR_OBS_LATENT_SCALE" ] && ViashError Bad arguments for option \'--obs_latent_scale=*\': \'$VIASH_PAR_OBS_LATENT_SCALE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBS_LATENT_SCALE=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --var_ambient_expression)
            [ -n "$VIASH_PAR_VAR_AMBIENT_EXPRESSION" ] && ViashError Bad arguments for option \'--var_ambient_expression\': \'$VIASH_PAR_VAR_AMBIENT_EXPRESSION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VAR_AMBIENT_EXPRESSION="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --var_ambient_expression. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --var_ambient_expression=*)
            [ -n "$VIASH_PAR_VAR_AMBIENT_EXPRESSION" ] && ViashError Bad arguments for option \'--var_ambient_expression=*\': \'$VIASH_PAR_VAR_AMBIENT_EXPRESSION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VAR_AMBIENT_EXPRESSION=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --obsm_gene_expression_encoding)
            [ -n "$VIASH_PAR_OBSM_GENE_EXPRESSION_ENCODING" ] && ViashError Bad arguments for option \'--obsm_gene_expression_encoding\': \'$VIASH_PAR_OBSM_GENE_EXPRESSION_ENCODING\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBSM_GENE_EXPRESSION_ENCODING="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --obsm_gene_expression_encoding. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --obsm_gene_expression_encoding=*)
            [ -n "$VIASH_PAR_OBSM_GENE_EXPRESSION_ENCODING" ] && ViashError Bad arguments for option \'--obsm_gene_expression_encoding=*\': \'$VIASH_PAR_OBSM_GENE_EXPRESSION_ENCODING\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OBSM_GENE_EXPRESSION_ENCODING=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --output_compression)
            [ -n "$VIASH_PAR_OUTPUT_COMPRESSION" ] && ViashError Bad arguments for option \'--output_compression\': \'$VIASH_PAR_OUTPUT_COMPRESSION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OUTPUT_COMPRESSION="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --output_compression. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --output_compression=*)
            [ -n "$VIASH_PAR_OUTPUT_COMPRESSION" ] && ViashError Bad arguments for option \'--output_compression=*\': \'$VIASH_PAR_OUTPUT_COMPRESSION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_OUTPUT_COMPRESSION=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --expected_cells_from_qc)
            [ -n "$VIASH_PAR_EXPECTED_CELLS_FROM_QC" ] && ViashError Bad arguments for option \'--expected_cells_from_qc\': \'$VIASH_PAR_EXPECTED_CELLS_FROM_QC\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EXPECTED_CELLS_FROM_QC="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --expected_cells_from_qc. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --expected_cells_from_qc=*)
            [ -n "$VIASH_PAR_EXPECTED_CELLS_FROM_QC" ] && ViashError Bad arguments for option \'--expected_cells_from_qc=*\': \'$VIASH_PAR_EXPECTED_CELLS_FROM_QC\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EXPECTED_CELLS_FROM_QC=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --expected_cells)
            [ -n "$VIASH_PAR_EXPECTED_CELLS" ] && ViashError Bad arguments for option \'--expected_cells\': \'$VIASH_PAR_EXPECTED_CELLS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EXPECTED_CELLS="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --expected_cells. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --expected_cells=*)
            [ -n "$VIASH_PAR_EXPECTED_CELLS" ] && ViashError Bad arguments for option \'--expected_cells=*\': \'$VIASH_PAR_EXPECTED_CELLS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EXPECTED_CELLS=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --total_droplets_included)
            [ -n "$VIASH_PAR_TOTAL_DROPLETS_INCLUDED" ] && ViashError Bad arguments for option \'--total_droplets_included\': \'$VIASH_PAR_TOTAL_DROPLETS_INCLUDED\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_TOTAL_DROPLETS_INCLUDED="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --total_droplets_included. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --total_droplets_included=*)
            [ -n "$VIASH_PAR_TOTAL_DROPLETS_INCLUDED" ] && ViashError Bad arguments for option \'--total_droplets_included=*\': \'$VIASH_PAR_TOTAL_DROPLETS_INCLUDED\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_TOTAL_DROPLETS_INCLUDED=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --force_cell_umi_prior)
            [ -n "$VIASH_PAR_FORCE_CELL_UMI_PRIOR" ] && ViashError Bad arguments for option \'--force_cell_umi_prior\': \'$VIASH_PAR_FORCE_CELL_UMI_PRIOR\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FORCE_CELL_UMI_PRIOR="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --force_cell_umi_prior. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --force_cell_umi_prior=*)
            [ -n "$VIASH_PAR_FORCE_CELL_UMI_PRIOR" ] && ViashError Bad arguments for option \'--force_cell_umi_prior=*\': \'$VIASH_PAR_FORCE_CELL_UMI_PRIOR\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FORCE_CELL_UMI_PRIOR=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --force_empty_umi_prior)
            [ -n "$VIASH_PAR_FORCE_EMPTY_UMI_PRIOR" ] && ViashError Bad arguments for option \'--force_empty_umi_prior\': \'$VIASH_PAR_FORCE_EMPTY_UMI_PRIOR\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FORCE_EMPTY_UMI_PRIOR="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --force_empty_umi_prior. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --force_empty_umi_prior=*)
            [ -n "$VIASH_PAR_FORCE_EMPTY_UMI_PRIOR" ] && ViashError Bad arguments for option \'--force_empty_umi_prior=*\': \'$VIASH_PAR_FORCE_EMPTY_UMI_PRIOR\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FORCE_EMPTY_UMI_PRIOR=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --model)
            [ -n "$VIASH_PAR_MODEL" ] && ViashError Bad arguments for option \'--model\': \'$VIASH_PAR_MODEL\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_MODEL="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --model. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --model=*)
            [ -n "$VIASH_PAR_MODEL" ] && ViashError Bad arguments for option \'--model=*\': \'$VIASH_PAR_MODEL\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_MODEL=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --epochs)
            [ -n "$VIASH_PAR_EPOCHS" ] && ViashError Bad arguments for option \'--epochs\': \'$VIASH_PAR_EPOCHS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EPOCHS="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --epochs. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --epochs=*)
            [ -n "$VIASH_PAR_EPOCHS" ] && ViashError Bad arguments for option \'--epochs=*\': \'$VIASH_PAR_EPOCHS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EPOCHS=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --low_count_threshold)
            [ -n "$VIASH_PAR_LOW_COUNT_THRESHOLD" ] && ViashError Bad arguments for option \'--low_count_threshold\': \'$VIASH_PAR_LOW_COUNT_THRESHOLD\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_LOW_COUNT_THRESHOLD="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --low_count_threshold. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --low_count_threshold=*)
            [ -n "$VIASH_PAR_LOW_COUNT_THRESHOLD" ] && ViashError Bad arguments for option \'--low_count_threshold=*\': \'$VIASH_PAR_LOW_COUNT_THRESHOLD\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_LOW_COUNT_THRESHOLD=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --z_dim)
            [ -n "$VIASH_PAR_Z_DIM" ] && ViashError Bad arguments for option \'--z_dim\': \'$VIASH_PAR_Z_DIM\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_Z_DIM="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --z_dim. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --z_dim=*)
            [ -n "$VIASH_PAR_Z_DIM" ] && ViashError Bad arguments for option \'--z_dim=*\': \'$VIASH_PAR_Z_DIM\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_Z_DIM=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --z_layers)
            if [ -z "$VIASH_PAR_Z_LAYERS" ]; then
              VIASH_PAR_Z_LAYERS="$2"
            else
              VIASH_PAR_Z_LAYERS="$VIASH_PAR_Z_LAYERS;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --z_layers. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --z_layers=*)
            if [ -z "$VIASH_PAR_Z_LAYERS" ]; then
              VIASH_PAR_Z_LAYERS=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_Z_LAYERS="$VIASH_PAR_Z_LAYERS;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --training_fraction)
            [ -n "$VIASH_PAR_TRAINING_FRACTION" ] && ViashError Bad arguments for option \'--training_fraction\': \'$VIASH_PAR_TRAINING_FRACTION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_TRAINING_FRACTION="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --training_fraction. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --training_fraction=*)
            [ -n "$VIASH_PAR_TRAINING_FRACTION" ] && ViashError Bad arguments for option \'--training_fraction=*\': \'$VIASH_PAR_TRAINING_FRACTION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_TRAINING_FRACTION=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --empty_drop_training_fraction)
            [ -n "$VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION" ] && ViashError Bad arguments for option \'--empty_drop_training_fraction\': \'$VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --empty_drop_training_fraction. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --empty_drop_training_fraction=*)
            [ -n "$VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION" ] && ViashError Bad arguments for option \'--empty_drop_training_fraction=*\': \'$VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --ignore_features)
            if [ -z "$VIASH_PAR_IGNORE_FEATURES" ]; then
              VIASH_PAR_IGNORE_FEATURES="$2"
            else
              VIASH_PAR_IGNORE_FEATURES="$VIASH_PAR_IGNORE_FEATURES;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --ignore_features. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --ignore_features=*)
            if [ -z "$VIASH_PAR_IGNORE_FEATURES" ]; then
              VIASH_PAR_IGNORE_FEATURES=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_IGNORE_FEATURES="$VIASH_PAR_IGNORE_FEATURES;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --fpr)
            if [ -z "$VIASH_PAR_FPR" ]; then
              VIASH_PAR_FPR="$2"
            else
              VIASH_PAR_FPR="$VIASH_PAR_FPR;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --fpr. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --fpr=*)
            if [ -z "$VIASH_PAR_FPR" ]; then
              VIASH_PAR_FPR=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_FPR="$VIASH_PAR_FPR;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --exclude_feature_types)
            if [ -z "$VIASH_PAR_EXCLUDE_FEATURE_TYPES" ]; then
              VIASH_PAR_EXCLUDE_FEATURE_TYPES="$2"
            else
              VIASH_PAR_EXCLUDE_FEATURE_TYPES="$VIASH_PAR_EXCLUDE_FEATURE_TYPES;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --exclude_feature_types. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --exclude_feature_types=*)
            if [ -z "$VIASH_PAR_EXCLUDE_FEATURE_TYPES" ]; then
              VIASH_PAR_EXCLUDE_FEATURE_TYPES=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_EXCLUDE_FEATURE_TYPES="$VIASH_PAR_EXCLUDE_FEATURE_TYPES;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --projected_ambient_count_threshold)
            [ -n "$VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD" ] && ViashError Bad arguments for option \'--projected_ambient_count_threshold\': \'$VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --projected_ambient_count_threshold. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --projected_ambient_count_threshold=*)
            [ -n "$VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD" ] && ViashError Bad arguments for option \'--projected_ambient_count_threshold=*\': \'$VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --learning_rate)
            [ -n "$VIASH_PAR_LEARNING_RATE" ] && ViashError Bad arguments for option \'--learning_rate\': \'$VIASH_PAR_LEARNING_RATE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_LEARNING_RATE="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --learning_rate. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --learning_rate=*)
            [ -n "$VIASH_PAR_LEARNING_RATE" ] && ViashError Bad arguments for option \'--learning_rate=*\': \'$VIASH_PAR_LEARNING_RATE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_LEARNING_RATE=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --final_elbo_fail_fraction)
            [ -n "$VIASH_PAR_FINAL_ELBO_FAIL_FRACTION" ] && ViashError Bad arguments for option \'--final_elbo_fail_fraction\': \'$VIASH_PAR_FINAL_ELBO_FAIL_FRACTION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FINAL_ELBO_FAIL_FRACTION="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --final_elbo_fail_fraction. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --final_elbo_fail_fraction=*)
            [ -n "$VIASH_PAR_FINAL_ELBO_FAIL_FRACTION" ] && ViashError Bad arguments for option \'--final_elbo_fail_fraction=*\': \'$VIASH_PAR_FINAL_ELBO_FAIL_FRACTION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FINAL_ELBO_FAIL_FRACTION=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --epoch_elbo_fail_fraction)
            [ -n "$VIASH_PAR_EPOCH_ELBO_FAIL_FRACTION" ] && ViashError Bad arguments for option \'--epoch_elbo_fail_fraction\': \'$VIASH_PAR_EPOCH_ELBO_FAIL_FRACTION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EPOCH_ELBO_FAIL_FRACTION="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --epoch_elbo_fail_fraction. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --epoch_elbo_fail_fraction=*)
            [ -n "$VIASH_PAR_EPOCH_ELBO_FAIL_FRACTION" ] && ViashError Bad arguments for option \'--epoch_elbo_fail_fraction=*\': \'$VIASH_PAR_EPOCH_ELBO_FAIL_FRACTION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EPOCH_ELBO_FAIL_FRACTION=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --num_training_tries)
            [ -n "$VIASH_PAR_NUM_TRAINING_TRIES" ] && ViashError Bad arguments for option \'--num_training_tries\': \'$VIASH_PAR_NUM_TRAINING_TRIES\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_NUM_TRAINING_TRIES="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --num_training_tries. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --num_training_tries=*)
            [ -n "$VIASH_PAR_NUM_TRAINING_TRIES" ] && ViashError Bad arguments for option \'--num_training_tries=*\': \'$VIASH_PAR_NUM_TRAINING_TRIES\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_NUM_TRAINING_TRIES=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --learning_rate_retry_mult)
            [ -n "$VIASH_PAR_LEARNING_RATE_RETRY_MULT" ] && ViashError Bad arguments for option \'--learning_rate_retry_mult\': \'$VIASH_PAR_LEARNING_RATE_RETRY_MULT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_LEARNING_RATE_RETRY_MULT="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --learning_rate_retry_mult. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --learning_rate_retry_mult=*)
            [ -n "$VIASH_PAR_LEARNING_RATE_RETRY_MULT" ] && ViashError Bad arguments for option \'--learning_rate_retry_mult=*\': \'$VIASH_PAR_LEARNING_RATE_RETRY_MULT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_LEARNING_RATE_RETRY_MULT=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --posterior_batch_size)
            [ -n "$VIASH_PAR_POSTERIOR_BATCH_SIZE" ] && ViashError Bad arguments for option \'--posterior_batch_size\': \'$VIASH_PAR_POSTERIOR_BATCH_SIZE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_POSTERIOR_BATCH_SIZE="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --posterior_batch_size. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --posterior_batch_size=*)
            [ -n "$VIASH_PAR_POSTERIOR_BATCH_SIZE" ] && ViashError Bad arguments for option \'--posterior_batch_size=*\': \'$VIASH_PAR_POSTERIOR_BATCH_SIZE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_POSTERIOR_BATCH_SIZE=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --posterior_regulation)
            [ -n "$VIASH_PAR_POSTERIOR_REGULATION" ] && ViashError Bad arguments for option \'--posterior_regulation\': \'$VIASH_PAR_POSTERIOR_REGULATION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_POSTERIOR_REGULATION="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --posterior_regulation. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --posterior_regulation=*)
            [ -n "$VIASH_PAR_POSTERIOR_REGULATION" ] && ViashError Bad arguments for option \'--posterior_regulation=*\': \'$VIASH_PAR_POSTERIOR_REGULATION\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_POSTERIOR_REGULATION=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --alpha)
            [ -n "$VIASH_PAR_ALPHA" ] && ViashError Bad arguments for option \'--alpha\': \'$VIASH_PAR_ALPHA\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_ALPHA="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --alpha. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --alpha=*)
            [ -n "$VIASH_PAR_ALPHA" ] && ViashError Bad arguments for option \'--alpha=*\': \'$VIASH_PAR_ALPHA\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_ALPHA=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --q)
            [ -n "$VIASH_PAR_Q" ] && ViashError Bad arguments for option \'--q\': \'$VIASH_PAR_Q\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_Q="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --q. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --q=*)
            [ -n "$VIASH_PAR_Q" ] && ViashError Bad arguments for option \'--q=*\': \'$VIASH_PAR_Q\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_Q=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --estimator)
            [ -n "$VIASH_PAR_ESTIMATOR" ] && ViashError Bad arguments for option \'--estimator\': \'$VIASH_PAR_ESTIMATOR\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_ESTIMATOR="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --estimator. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --estimator=*)
            [ -n "$VIASH_PAR_ESTIMATOR" ] && ViashError Bad arguments for option \'--estimator=*\': \'$VIASH_PAR_ESTIMATOR\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_ESTIMATOR=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --estimator_multiple_cpu)
            [ -n "$VIASH_PAR_ESTIMATOR_MULTIPLE_CPU" ] && ViashError Bad arguments for option \'--estimator_multiple_cpu\': \'$VIASH_PAR_ESTIMATOR_MULTIPLE_CPU\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_ESTIMATOR_MULTIPLE_CPU=true
            shift 1
            ;;
        --constant_learning_rate)
            [ -n "$VIASH_PAR_CONSTANT_LEARNING_RATE" ] && ViashError Bad arguments for option \'--constant_learning_rate\': \'$VIASH_PAR_CONSTANT_LEARNING_RATE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_CONSTANT_LEARNING_RATE="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --constant_learning_rate. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --constant_learning_rate=*)
            [ -n "$VIASH_PAR_CONSTANT_LEARNING_RATE" ] && ViashError Bad arguments for option \'--constant_learning_rate=*\': \'$VIASH_PAR_CONSTANT_LEARNING_RATE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_CONSTANT_LEARNING_RATE=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --debug)
            [ -n "$VIASH_PAR_DEBUG" ] && ViashError Bad arguments for option \'--debug\': \'$VIASH_PAR_DEBUG\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_DEBUG=true
            shift 1
            ;;
        --cuda)
            [ -n "$VIASH_PAR_CUDA" ] && ViashError Bad arguments for option \'--cuda\': \'$VIASH_PAR_CUDA\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_CUDA=true
            shift 1
            ;;
        ---engine)
            VIASH_ENGINE_ID="$2"
            shift 2
            ;;
        ---engine=*)
            VIASH_ENGINE_ID="$(ViashRemoveFlags "$1")"
            shift 1
            ;;
        ---setup)
            VIASH_MODE='setup'
            VIASH_SETUP_STRATEGY="$2"
            shift 2
            ;;
        ---setup=*)
            VIASH_MODE='setup'
            VIASH_SETUP_STRATEGY="$(ViashRemoveFlags "$1")"
            shift 1
            ;;
        ---dockerfile)
            VIASH_MODE='dockerfile'
            shift 1
            ;;
        ---docker_run_args)
            VIASH_DOCKER_RUN_ARGS+=("$2")
            shift 2
            ;;
        ---docker_run_args=*)
            VIASH_DOCKER_RUN_ARGS+=("$(ViashRemoveFlags "$1")")
            shift 1
            ;;
        ---docker_image_id)
            VIASH_MODE='docker_image_id'
            shift 1
            ;;
        ---debug)
            VIASH_MODE='debug'
            shift 1
            ;;
        ---cpus)
            [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_META_CPUS="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to ---cpus. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        ---cpus=*)
            [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus=*\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_META_CPUS=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        ---memory)
            [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_META_MEMORY="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to ---memory. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        ---memory=*)
            [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory=*\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_META_MEMORY=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        *)  # positional arg or unknown option
            # since the positional args will be eval'd, can we always quote, instead of using ViashQuote
            VIASH_POSITIONAL_ARGS="$VIASH_POSITIONAL_ARGS '$1'"
            [[ $1 == -* ]] && ViashWarning $1 looks like a parameter but is not a defined parameter and will instead be treated as a positional argument. Use "--help" to get more information on the parameters.
            shift # past argument
            ;;
    esac
done

# parse positional parameters
eval set -- $VIASH_POSITIONAL_ARGS


if   [ "$VIASH_ENGINE_ID" == "native" ]  ; then
  VIASH_ENGINE_TYPE='native'
elif   [ "$VIASH_ENGINE_ID" == "docker" ]  ; then
  VIASH_ENGINE_TYPE='docker'
else
  ViashError "Engine '$VIASH_ENGINE_ID' is not recognized. Options are: docker, native."
  exit 1
fi

if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
  # check if docker is installed properly
  ViashDockerInstallationCheck

  # determine docker image id
  if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then
    VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/openpipeline/correction/cellbender_remove_background:v4.0.1'
  fi

  # print dockerfile
  if [ "$VIASH_MODE" == "dockerfile" ]; then
    ViashDockerfile "$VIASH_ENGINE_ID"
    exit 0

  elif [ "$VIASH_MODE" == "docker_image_id" ]; then
    echo "$VIASH_DOCKER_IMAGE_ID"
    exit 0
  
  # enter docker container
  elif [[ "$VIASH_MODE" == "debug" ]]; then
    VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} -v '$(pwd)':/pwd --workdir /pwd -t $VIASH_DOCKER_IMAGE_ID"
    ViashNotice "+ $VIASH_CMD"
    eval $VIASH_CMD
    exit 

  # build docker image
  elif [ "$VIASH_MODE" == "setup" ]; then
    ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" "$VIASH_SETUP_STRATEGY"
    ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'bash'
    exit 0
  fi

  # check if docker image exists
  ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" ifneedbepullelsecachedbuild
  ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'bash'
fi

# setting computational defaults

# helper function for parsing memory strings
function ViashMemoryAsBytes {
  local memory=`echo "$1" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]'`
  local memory_regex='^([0-9]+)([kmgtp]i?b?|b)$'
  if [[ $memory =~ $memory_regex ]]; then
    local number=${memory/[^0-9]*/}
    local symbol=${memory/*[0-9]/}
    
    case $symbol in
      b)      memory_b=$number ;;
      kb|k)   memory_b=$(( $number * 1000 )) ;;
      mb|m)   memory_b=$(( $number * 1000 * 1000 )) ;;
      gb|g)   memory_b=$(( $number * 1000 * 1000 * 1000 )) ;;
      tb|t)   memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 )) ;;
      pb|p)   memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 * 1000 )) ;;
      kib|ki)   memory_b=$(( $number * 1024 )) ;;
      mib|mi)   memory_b=$(( $number * 1024 * 1024 )) ;;
      gib|gi)   memory_b=$(( $number * 1024 * 1024 * 1024 )) ;;
      tib|ti)   memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 )) ;;
      pib|pi)   memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 * 1024 )) ;;
    esac
    echo "$memory_b"
  fi
}
# compute memory in different units
if [ ! -z ${VIASH_META_MEMORY+x} ]; then
  VIASH_META_MEMORY_B=`ViashMemoryAsBytes $VIASH_META_MEMORY`
  # do not define other variables if memory_b is an empty string
  if [ ! -z "$VIASH_META_MEMORY_B" ]; then
    VIASH_META_MEMORY_KB=$(( ($VIASH_META_MEMORY_B+999) / 1000 ))
    VIASH_META_MEMORY_MB=$(( ($VIASH_META_MEMORY_KB+999) / 1000 ))
    VIASH_META_MEMORY_GB=$(( ($VIASH_META_MEMORY_MB+999) / 1000 ))
    VIASH_META_MEMORY_TB=$(( ($VIASH_META_MEMORY_GB+999) / 1000 ))
    VIASH_META_MEMORY_PB=$(( ($VIASH_META_MEMORY_TB+999) / 1000 ))
    VIASH_META_MEMORY_KIB=$(( ($VIASH_META_MEMORY_B+1023) / 1024 ))
    VIASH_META_MEMORY_MIB=$(( ($VIASH_META_MEMORY_KIB+1023) / 1024 ))
    VIASH_META_MEMORY_GIB=$(( ($VIASH_META_MEMORY_MIB+1023) / 1024 ))
    VIASH_META_MEMORY_TIB=$(( ($VIASH_META_MEMORY_GIB+1023) / 1024 ))
    VIASH_META_MEMORY_PIB=$(( ($VIASH_META_MEMORY_TIB+1023) / 1024 ))
  else
    # unset memory if string is empty
    unset $VIASH_META_MEMORY_B
  fi
fi
# unset nproc if string is empty
if [ -z "$VIASH_META_CPUS" ]; then
  unset $VIASH_META_CPUS
fi


# check whether required parameters exist
if [ -z ${VIASH_PAR_INPUT+x} ]; then
  ViashError '--input' is a required argument. Use "--help" to get more information on the parameters.
  exit 1
fi
if [ -z ${VIASH_PAR_OUTPUT+x} ]; then
  ViashError '--output' is a required argument. Use "--help" to get more information on the parameters.
  exit 1
fi
if [ -z ${VIASH_META_NAME+x} ]; then
  ViashError 'name' is a required argument. Use "--help" to get more information on the parameters.
  exit 1
fi
if [ -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then
  ViashError 'functionality_name' is a required argument. Use "--help" to get more information on the parameters.
  exit 1
fi
if [ -z ${VIASH_META_RESOURCES_DIR+x} ]; then
  ViashError 'resources_dir' is a required argument. Use "--help" to get more information on the parameters.
  exit 1
fi
if [ -z ${VIASH_META_EXECUTABLE+x} ]; then
  ViashError 'executable' is a required argument. Use "--help" to get more information on the parameters.
  exit 1
fi
if [ -z ${VIASH_META_CONFIG+x} ]; then
  ViashError 'config' is a required argument. Use "--help" to get more information on the parameters.
  exit 1
fi
if [ -z ${VIASH_META_TEMP_DIR+x} ]; then
  ViashError 'temp_dir' is a required argument. Use "--help" to get more information on the parameters.
  exit 1
fi

# filling in defaults
if [ -z ${VIASH_PAR_MODALITY+x} ]; then
  VIASH_PAR_MODALITY="rna"
fi
if [ -z ${VIASH_PAR_LAYER_OUTPUT+x} ]; then
  VIASH_PAR_LAYER_OUTPUT="cellbender_corrected"
fi
if [ -z ${VIASH_PAR_OBS_BACKGROUND_FRACTION+x} ]; then
  VIASH_PAR_OBS_BACKGROUND_FRACTION="cellbender_background_fraction"
fi
if [ -z ${VIASH_PAR_OBS_CELL_PROBABILITY+x} ]; then
  VIASH_PAR_OBS_CELL_PROBABILITY="cellbender_cell_probability"
fi
if [ -z ${VIASH_PAR_OBS_CELL_SIZE+x} ]; then
  VIASH_PAR_OBS_CELL_SIZE="cellbender_cell_size"
fi
if [ -z ${VIASH_PAR_OBS_DROPLET_EFFICIENCY+x} ]; then
  VIASH_PAR_OBS_DROPLET_EFFICIENCY="cellbender_droplet_efficiency"
fi
if [ -z ${VIASH_PAR_OBS_LATENT_SCALE+x} ]; then
  VIASH_PAR_OBS_LATENT_SCALE="cellbender_latent_scale"
fi
if [ -z ${VIASH_PAR_VAR_AMBIENT_EXPRESSION+x} ]; then
  VIASH_PAR_VAR_AMBIENT_EXPRESSION="cellbender_ambient_expression"
fi
if [ -z ${VIASH_PAR_OBSM_GENE_EXPRESSION_ENCODING+x} ]; then
  VIASH_PAR_OBSM_GENE_EXPRESSION_ENCODING="cellbender_gene_expression_encoding"
fi
if [ -z ${VIASH_PAR_EXPECTED_CELLS_FROM_QC+x} ]; then
  VIASH_PAR_EXPECTED_CELLS_FROM_QC="false"
fi
if [ -z ${VIASH_PAR_MODEL+x} ]; then
  VIASH_PAR_MODEL="full"
fi
if [ -z ${VIASH_PAR_EPOCHS+x} ]; then
  VIASH_PAR_EPOCHS="150"
fi
if [ -z ${VIASH_PAR_LOW_COUNT_THRESHOLD+x} ]; then
  VIASH_PAR_LOW_COUNT_THRESHOLD="5"
fi
if [ -z ${VIASH_PAR_Z_DIM+x} ]; then
  VIASH_PAR_Z_DIM="64"
fi
if [ -z ${VIASH_PAR_Z_LAYERS+x} ]; then
  VIASH_PAR_Z_LAYERS="512"
fi
if [ -z ${VIASH_PAR_TRAINING_FRACTION+x} ]; then
  VIASH_PAR_TRAINING_FRACTION="0.9"
fi
if [ -z ${VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION+x} ]; then
  VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION="0.2"
fi
if [ -z ${VIASH_PAR_FPR+x} ]; then
  VIASH_PAR_FPR="0.01"
fi
if [ -z ${VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD+x} ]; then
  VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD="0.1"
fi
if [ -z ${VIASH_PAR_LEARNING_RATE+x} ]; then
  VIASH_PAR_LEARNING_RATE="1.0E-4"
fi
if [ -z ${VIASH_PAR_NUM_TRAINING_TRIES+x} ]; then
  VIASH_PAR_NUM_TRAINING_TRIES="1"
fi
if [ -z ${VIASH_PAR_LEARNING_RATE_RETRY_MULT+x} ]; then
  VIASH_PAR_LEARNING_RATE_RETRY_MULT="0.2"
fi
if [ -z ${VIASH_PAR_POSTERIOR_BATCH_SIZE+x} ]; then
  VIASH_PAR_POSTERIOR_BATCH_SIZE="128"
fi
if [ -z ${VIASH_PAR_ESTIMATOR+x} ]; then
  VIASH_PAR_ESTIMATOR="mckp"
fi
if [ -z ${VIASH_PAR_ESTIMATOR_MULTIPLE_CPU+x} ]; then
  VIASH_PAR_ESTIMATOR_MULTIPLE_CPU="false"
fi
if [ -z ${VIASH_PAR_DEBUG+x} ]; then
  VIASH_PAR_DEBUG="false"
fi
if [ -z ${VIASH_PAR_CUDA+x} ]; then
  VIASH_PAR_CUDA="false"
fi

# check whether required files exist
if [ ! -z "$VIASH_PAR_INPUT" ] && [ ! -e "$VIASH_PAR_INPUT" ]; then
  ViashError "Input file '$VIASH_PAR_INPUT' does not exist."
  exit 1
fi

# check whether parameters values are of the right type
if [[ -n "$VIASH_PAR_EXPECTED_CELLS_FROM_QC" ]]; then
  if ! [[ "$VIASH_PAR_EXPECTED_CELLS_FROM_QC" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--expected_cells_from_qc' has to be a boolean. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_EXPECTED_CELLS" ]]; then
  if ! [[ "$VIASH_PAR_EXPECTED_CELLS" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--expected_cells' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_TOTAL_DROPLETS_INCLUDED" ]]; then
  if ! [[ "$VIASH_PAR_TOTAL_DROPLETS_INCLUDED" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--total_droplets_included' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_FORCE_CELL_UMI_PRIOR" ]]; then
  if ! [[ "$VIASH_PAR_FORCE_CELL_UMI_PRIOR" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--force_cell_umi_prior' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_FORCE_EMPTY_UMI_PRIOR" ]]; then
  if ! [[ "$VIASH_PAR_FORCE_EMPTY_UMI_PRIOR" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--force_empty_umi_prior' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_EPOCHS" ]]; then
  if ! [[ "$VIASH_PAR_EPOCHS" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--epochs' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_LOW_COUNT_THRESHOLD" ]]; then
  if ! [[ "$VIASH_PAR_LOW_COUNT_THRESHOLD" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--low_count_threshold' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_Z_DIM" ]]; then
  if ! [[ "$VIASH_PAR_Z_DIM" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--z_dim' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [ -n "$VIASH_PAR_Z_LAYERS" ]; then
  IFS=';'
  set -f
  for val in $VIASH_PAR_Z_LAYERS; do
    if ! [[ "${val}" =~ ^[-+]?[0-9]+$ ]]; then
      ViashError '--z_layers' has to be an integer. Use "--help" to get more information on the parameters.
      exit 1
    fi
  done
  set +f
  unset IFS
fi

if [[ -n "$VIASH_PAR_TRAINING_FRACTION" ]]; then
  if ! [[ "$VIASH_PAR_TRAINING_FRACTION" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
    ViashError '--training_fraction' has to be a double. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION" ]]; then
  if ! [[ "$VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
    ViashError '--empty_drop_training_fraction' has to be a double. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [ -n "$VIASH_PAR_IGNORE_FEATURES" ]; then
  IFS=';'
  set -f
  for val in $VIASH_PAR_IGNORE_FEATURES; do
    if ! [[ "${val}" =~ ^[-+]?[0-9]+$ ]]; then
      ViashError '--ignore_features' has to be an integer. Use "--help" to get more information on the parameters.
      exit 1
    fi
  done
  set +f
  unset IFS
fi

if [ -n "$VIASH_PAR_FPR" ]; then
  IFS=';'
  set -f
  for val in $VIASH_PAR_FPR; do
    if ! [[ "${val}" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
      ViashError '--fpr' has to be a double. Use "--help" to get more information on the parameters.
      exit 1
    fi
  done
  set +f
  unset IFS
fi

if [[ -n "$VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD" ]]; then
  if ! [[ "$VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
    ViashError '--projected_ambient_count_threshold' has to be a double. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_LEARNING_RATE" ]]; then
  if ! [[ "$VIASH_PAR_LEARNING_RATE" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
    ViashError '--learning_rate' has to be a double. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_FINAL_ELBO_FAIL_FRACTION" ]]; then
  if ! [[ "$VIASH_PAR_FINAL_ELBO_FAIL_FRACTION" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
    ViashError '--final_elbo_fail_fraction' has to be a double. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_EPOCH_ELBO_FAIL_FRACTION" ]]; then
  if ! [[ "$VIASH_PAR_EPOCH_ELBO_FAIL_FRACTION" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
    ViashError '--epoch_elbo_fail_fraction' has to be a double. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_NUM_TRAINING_TRIES" ]]; then
  if ! [[ "$VIASH_PAR_NUM_TRAINING_TRIES" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--num_training_tries' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_LEARNING_RATE_RETRY_MULT" ]]; then
  if ! [[ "$VIASH_PAR_LEARNING_RATE_RETRY_MULT" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
    ViashError '--learning_rate_retry_mult' has to be a double. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_POSTERIOR_BATCH_SIZE" ]]; then
  if ! [[ "$VIASH_PAR_POSTERIOR_BATCH_SIZE" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--posterior_batch_size' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_ALPHA" ]]; then
  if ! [[ "$VIASH_PAR_ALPHA" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
    ViashError '--alpha' has to be a double. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_Q" ]]; then
  if ! [[ "$VIASH_PAR_Q" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
    ViashError '--q' has to be a double. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_ESTIMATOR_MULTIPLE_CPU" ]]; then
  if ! [[ "$VIASH_PAR_ESTIMATOR_MULTIPLE_CPU" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--estimator_multiple_cpu' has to be a boolean_true. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_CONSTANT_LEARNING_RATE" ]]; then
  if ! [[ "$VIASH_PAR_CONSTANT_LEARNING_RATE" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--constant_learning_rate' has to be a boolean. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_DEBUG" ]]; then
  if ! [[ "$VIASH_PAR_DEBUG" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--debug' has to be a boolean_true. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_CUDA" ]]; then
  if ! [[ "$VIASH_PAR_CUDA" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--cuda' has to be a boolean_true. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_CPUS" ]]; then
  if ! [[ "$VIASH_META_CPUS" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'cpus' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_B" ]]; then
  if ! [[ "$VIASH_META_MEMORY_B" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_b' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_KB" ]]; then
  if ! [[ "$VIASH_META_MEMORY_KB" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_kb' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_MB" ]]; then
  if ! [[ "$VIASH_META_MEMORY_MB" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_mb' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_GB" ]]; then
  if ! [[ "$VIASH_META_MEMORY_GB" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_gb' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_TB" ]]; then
  if ! [[ "$VIASH_META_MEMORY_TB" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_tb' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_PB" ]]; then
  if ! [[ "$VIASH_META_MEMORY_PB" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_pb' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_KIB" ]]; then
  if ! [[ "$VIASH_META_MEMORY_KIB" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_kib' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_MIB" ]]; then
  if ! [[ "$VIASH_META_MEMORY_MIB" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_mib' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_GIB" ]]; then
  if ! [[ "$VIASH_META_MEMORY_GIB" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_gib' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_TIB" ]]; then
  if ! [[ "$VIASH_META_MEMORY_TIB" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_tib' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_META_MEMORY_PIB" ]]; then
  if ! [[ "$VIASH_META_MEMORY_PIB" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError 'memory_pib' has to be a long. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi

# check whether value is belongs to a set of choices
if [ ! -z "$VIASH_PAR_OUTPUT_COMPRESSION" ]; then
  VIASH_PAR_OUTPUT_COMPRESSION_CHOICES=("gzip;lzf")
  IFS=';'
  set -f
  if ! [[ ";${VIASH_PAR_OUTPUT_COMPRESSION_CHOICES[*]};" =~ ";$VIASH_PAR_OUTPUT_COMPRESSION;" ]]; then
    ViashError '--output_compression' specified value of \'$VIASH_PAR_OUTPUT_COMPRESSION\' is not in the list of allowed values. Use "--help" to get more information on the parameters.
    exit 1
  fi
  set +f
  unset IFS
fi

if [ ! -z "$VIASH_PAR_MODEL" ]; then
  VIASH_PAR_MODEL_CHOICES=("naive;simple;ambient;swapping;full")
  IFS=';'
  set -f
  if ! [[ ";${VIASH_PAR_MODEL_CHOICES[*]};" =~ ";$VIASH_PAR_MODEL;" ]]; then
    ViashError '--model' specified value of \'$VIASH_PAR_MODEL\' is not in the list of allowed values. Use "--help" to get more information on the parameters.
    exit 1
  fi
  set +f
  unset IFS
fi

if [ ! -z "$VIASH_PAR_POSTERIOR_REGULATION" ]; then
  VIASH_PAR_POSTERIOR_REGULATION_CHOICES=("PRq;PRmu;PRmu_gene")
  IFS=';'
  set -f
  if ! [[ ";${VIASH_PAR_POSTERIOR_REGULATION_CHOICES[*]};" =~ ";$VIASH_PAR_POSTERIOR_REGULATION;" ]]; then
    ViashError '--posterior_regulation' specified value of \'$VIASH_PAR_POSTERIOR_REGULATION\' is not in the list of allowed values. Use "--help" to get more information on the parameters.
    exit 1
  fi
  set +f
  unset IFS
fi

if [ ! -z "$VIASH_PAR_ESTIMATOR" ]; then
  VIASH_PAR_ESTIMATOR_CHOICES=("map;mean;cdf;sample;mckp")
  IFS=';'
  set -f
  if ! [[ ";${VIASH_PAR_ESTIMATOR_CHOICES[*]};" =~ ";$VIASH_PAR_ESTIMATOR;" ]]; then
    ViashError '--estimator' specified value of \'$VIASH_PAR_ESTIMATOR\' is not in the list of allowed values. Use "--help" to get more information on the parameters.
    exit 1
  fi
  set +f
  unset IFS
fi

# create parent directories of output files, if so desired
if [ ! -z "$VIASH_PAR_OUTPUT" ] && [ ! -d "$(dirname "$VIASH_PAR_OUTPUT")" ]; then
  mkdir -p "$(dirname "$VIASH_PAR_OUTPUT")"
fi

if  [ "$VIASH_ENGINE_ID" == "native" ]  ; then
  if [ "$VIASH_MODE" == "run" ]; then
    VIASH_CMD="bash"
  else
    ViashError "Engine '$VIASH_ENGINE_ID' does not support mode '$VIASH_MODE'."
    exit 1
  fi
fi

if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
  # detect volumes from file arguments
  VIASH_CHOWN_VARS=()
if [ ! -z "$VIASH_PAR_INPUT" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_INPUT")" )
  VIASH_PAR_INPUT=$(ViashDockerAutodetectMount "$VIASH_PAR_INPUT")
fi
if [ ! -z "$VIASH_PAR_OUTPUT" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_OUTPUT")" )
  VIASH_PAR_OUTPUT=$(ViashDockerAutodetectMount "$VIASH_PAR_OUTPUT")
  VIASH_CHOWN_VARS+=( "$VIASH_PAR_OUTPUT" )
fi
if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_RESOURCES_DIR")" )
  VIASH_META_RESOURCES_DIR=$(ViashDockerAutodetectMount "$VIASH_META_RESOURCES_DIR")
fi
if [ ! -z "$VIASH_META_EXECUTABLE" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_EXECUTABLE")" )
  VIASH_META_EXECUTABLE=$(ViashDockerAutodetectMount "$VIASH_META_EXECUTABLE")
fi
if [ ! -z "$VIASH_META_CONFIG" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_CONFIG")" )
  VIASH_META_CONFIG=$(ViashDockerAutodetectMount "$VIASH_META_CONFIG")
fi
if [ ! -z "$VIASH_META_TEMP_DIR" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_TEMP_DIR")" )
  VIASH_META_TEMP_DIR=$(ViashDockerAutodetectMount "$VIASH_META_TEMP_DIR")
fi
  
  # get unique mounts
  VIASH_UNIQUE_MOUNTS=($(for val in "${VIASH_DIRECTORY_MOUNTS[@]}"; do echo "$val"; done | sort -u))
fi

if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
  # change file ownership
  function ViashPerformChown {
    if (( ${#VIASH_CHOWN_VARS[@]} )); then
      set +e
      VIASH_CMD="docker run --entrypoint=bash --rm ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID -c 'chown $(id -u):$(id -g) --silent --recursive ${VIASH_CHOWN_VARS[@]}'"
      ViashDebug "+ $VIASH_CMD"
      eval $VIASH_CMD
      set -e
    fi
  }
  trap ViashPerformChown EXIT
fi

if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
  # helper function for filling in extra docker args
  if [ ! -z "$VIASH_META_MEMORY_B" ]; then
    VIASH_DOCKER_RUN_ARGS+=("--memory=${VIASH_META_MEMORY_B}")
  fi
  if [ ! -z "$VIASH_META_CPUS" ]; then
    VIASH_DOCKER_RUN_ARGS+=("--cpus=${VIASH_META_CPUS}")
  fi
fi

if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
  VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID"
fi


# set dependency paths


ViashDebug "Running command: $(echo $VIASH_CMD)"
cat << VIASHEOF | eval $VIASH_CMD
set -e
tempscript=\$(mktemp "$VIASH_META_TEMP_DIR/viash-run-cellbender_remove_background-XXXXXX").py
function clean_up {
  rm "\$tempscript"
}
function interrupt {
  echo -e "\nCTRL-C Pressed..."
  exit 1
}
trap clean_up EXIT
trap interrupt INT SIGINT
cat > "\$tempscript" << 'VIASHMAIN'
import mudata as mu
import tempfile
import subprocess
import os
import sys
import numpy as np
from scipy.sparse import csr_matrix
from cellbender.remove_background.downstream import anndata_from_h5

## VIASH START
# The following code has been auto-generated by Viash.
par = {
  'input': $( if [ ! -z ${VIASH_PAR_INPUT+x} ]; then echo "r'${VIASH_PAR_INPUT//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'modality': $( if [ ! -z ${VIASH_PAR_MODALITY+x} ]; then echo "r'${VIASH_PAR_MODALITY//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'output': $( if [ ! -z ${VIASH_PAR_OUTPUT+x} ]; then echo "r'${VIASH_PAR_OUTPUT//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'layer_output': $( if [ ! -z ${VIASH_PAR_LAYER_OUTPUT+x} ]; then echo "r'${VIASH_PAR_LAYER_OUTPUT//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'obs_background_fraction': $( if [ ! -z ${VIASH_PAR_OBS_BACKGROUND_FRACTION+x} ]; then echo "r'${VIASH_PAR_OBS_BACKGROUND_FRACTION//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'obs_cell_probability': $( if [ ! -z ${VIASH_PAR_OBS_CELL_PROBABILITY+x} ]; then echo "r'${VIASH_PAR_OBS_CELL_PROBABILITY//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'obs_cell_size': $( if [ ! -z ${VIASH_PAR_OBS_CELL_SIZE+x} ]; then echo "r'${VIASH_PAR_OBS_CELL_SIZE//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'obs_droplet_efficiency': $( if [ ! -z ${VIASH_PAR_OBS_DROPLET_EFFICIENCY+x} ]; then echo "r'${VIASH_PAR_OBS_DROPLET_EFFICIENCY//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'obs_latent_scale': $( if [ ! -z ${VIASH_PAR_OBS_LATENT_SCALE+x} ]; then echo "r'${VIASH_PAR_OBS_LATENT_SCALE//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'var_ambient_expression': $( if [ ! -z ${VIASH_PAR_VAR_AMBIENT_EXPRESSION+x} ]; then echo "r'${VIASH_PAR_VAR_AMBIENT_EXPRESSION//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'obsm_gene_expression_encoding': $( if [ ! -z ${VIASH_PAR_OBSM_GENE_EXPRESSION_ENCODING+x} ]; then echo "r'${VIASH_PAR_OBSM_GENE_EXPRESSION_ENCODING//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'output_compression': $( if [ ! -z ${VIASH_PAR_OUTPUT_COMPRESSION+x} ]; then echo "r'${VIASH_PAR_OUTPUT_COMPRESSION//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'expected_cells_from_qc': $( if [ ! -z ${VIASH_PAR_EXPECTED_CELLS_FROM_QC+x} ]; then echo "r'${VIASH_PAR_EXPECTED_CELLS_FROM_QC//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi ),
  'expected_cells': $( if [ ! -z ${VIASH_PAR_EXPECTED_CELLS+x} ]; then echo "int(r'${VIASH_PAR_EXPECTED_CELLS//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'total_droplets_included': $( if [ ! -z ${VIASH_PAR_TOTAL_DROPLETS_INCLUDED+x} ]; then echo "int(r'${VIASH_PAR_TOTAL_DROPLETS_INCLUDED//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'force_cell_umi_prior': $( if [ ! -z ${VIASH_PAR_FORCE_CELL_UMI_PRIOR+x} ]; then echo "int(r'${VIASH_PAR_FORCE_CELL_UMI_PRIOR//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'force_empty_umi_prior': $( if [ ! -z ${VIASH_PAR_FORCE_EMPTY_UMI_PRIOR+x} ]; then echo "int(r'${VIASH_PAR_FORCE_EMPTY_UMI_PRIOR//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'model': $( if [ ! -z ${VIASH_PAR_MODEL+x} ]; then echo "r'${VIASH_PAR_MODEL//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'epochs': $( if [ ! -z ${VIASH_PAR_EPOCHS+x} ]; then echo "int(r'${VIASH_PAR_EPOCHS//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'low_count_threshold': $( if [ ! -z ${VIASH_PAR_LOW_COUNT_THRESHOLD+x} ]; then echo "int(r'${VIASH_PAR_LOW_COUNT_THRESHOLD//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'z_dim': $( if [ ! -z ${VIASH_PAR_Z_DIM+x} ]; then echo "int(r'${VIASH_PAR_Z_DIM//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'z_layers': $( if [ ! -z ${VIASH_PAR_Z_LAYERS+x} ]; then echo "list(map(int, r'${VIASH_PAR_Z_LAYERS//\'/\'\"\'\"r\'}'.split(';')))"; else echo None; fi ),
  'training_fraction': $( if [ ! -z ${VIASH_PAR_TRAINING_FRACTION+x} ]; then echo "float(r'${VIASH_PAR_TRAINING_FRACTION//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'empty_drop_training_fraction': $( if [ ! -z ${VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION+x} ]; then echo "float(r'${VIASH_PAR_EMPTY_DROP_TRAINING_FRACTION//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'ignore_features': $( if [ ! -z ${VIASH_PAR_IGNORE_FEATURES+x} ]; then echo "list(map(int, r'${VIASH_PAR_IGNORE_FEATURES//\'/\'\"\'\"r\'}'.split(';')))"; else echo None; fi ),
  'fpr': $( if [ ! -z ${VIASH_PAR_FPR+x} ]; then echo "list(map(float, r'${VIASH_PAR_FPR//\'/\'\"\'\"r\'}'.split(';')))"; else echo None; fi ),
  'exclude_feature_types': $( if [ ! -z ${VIASH_PAR_EXCLUDE_FEATURE_TYPES+x} ]; then echo "r'${VIASH_PAR_EXCLUDE_FEATURE_TYPES//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'projected_ambient_count_threshold': $( if [ ! -z ${VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD+x} ]; then echo "float(r'${VIASH_PAR_PROJECTED_AMBIENT_COUNT_THRESHOLD//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'learning_rate': $( if [ ! -z ${VIASH_PAR_LEARNING_RATE+x} ]; then echo "float(r'${VIASH_PAR_LEARNING_RATE//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'final_elbo_fail_fraction': $( if [ ! -z ${VIASH_PAR_FINAL_ELBO_FAIL_FRACTION+x} ]; then echo "float(r'${VIASH_PAR_FINAL_ELBO_FAIL_FRACTION//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'epoch_elbo_fail_fraction': $( if [ ! -z ${VIASH_PAR_EPOCH_ELBO_FAIL_FRACTION+x} ]; then echo "float(r'${VIASH_PAR_EPOCH_ELBO_FAIL_FRACTION//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'num_training_tries': $( if [ ! -z ${VIASH_PAR_NUM_TRAINING_TRIES+x} ]; then echo "int(r'${VIASH_PAR_NUM_TRAINING_TRIES//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'learning_rate_retry_mult': $( if [ ! -z ${VIASH_PAR_LEARNING_RATE_RETRY_MULT+x} ]; then echo "float(r'${VIASH_PAR_LEARNING_RATE_RETRY_MULT//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'posterior_batch_size': $( if [ ! -z ${VIASH_PAR_POSTERIOR_BATCH_SIZE+x} ]; then echo "int(r'${VIASH_PAR_POSTERIOR_BATCH_SIZE//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'posterior_regulation': $( if [ ! -z ${VIASH_PAR_POSTERIOR_REGULATION+x} ]; then echo "r'${VIASH_PAR_POSTERIOR_REGULATION//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'alpha': $( if [ ! -z ${VIASH_PAR_ALPHA+x} ]; then echo "float(r'${VIASH_PAR_ALPHA//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'q': $( if [ ! -z ${VIASH_PAR_Q+x} ]; then echo "float(r'${VIASH_PAR_Q//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'estimator': $( if [ ! -z ${VIASH_PAR_ESTIMATOR+x} ]; then echo "r'${VIASH_PAR_ESTIMATOR//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'estimator_multiple_cpu': $( if [ ! -z ${VIASH_PAR_ESTIMATOR_MULTIPLE_CPU+x} ]; then echo "r'${VIASH_PAR_ESTIMATOR_MULTIPLE_CPU//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi ),
  'constant_learning_rate': $( if [ ! -z ${VIASH_PAR_CONSTANT_LEARNING_RATE+x} ]; then echo "r'${VIASH_PAR_CONSTANT_LEARNING_RATE//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi ),
  'debug': $( if [ ! -z ${VIASH_PAR_DEBUG+x} ]; then echo "r'${VIASH_PAR_DEBUG//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi ),
  'cuda': $( if [ ! -z ${VIASH_PAR_CUDA+x} ]; then echo "r'${VIASH_PAR_CUDA//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi )
}
meta = {
  'name': $( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "r'${VIASH_META_NAME//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'functionality_name': $( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "r'${VIASH_META_FUNCTIONALITY_NAME//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'resources_dir': $( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "r'${VIASH_META_RESOURCES_DIR//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'executable': $( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "r'${VIASH_META_EXECUTABLE//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'config': $( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "r'${VIASH_META_CONFIG//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'temp_dir': $( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "r'${VIASH_META_TEMP_DIR//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'cpus': $( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "int(r'${VIASH_META_CPUS//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_b': $( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "int(r'${VIASH_META_MEMORY_B//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_kb': $( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "int(r'${VIASH_META_MEMORY_KB//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_mb': $( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "int(r'${VIASH_META_MEMORY_MB//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_gb': $( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "int(r'${VIASH_META_MEMORY_GB//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_tb': $( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "int(r'${VIASH_META_MEMORY_TB//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_pb': $( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "int(r'${VIASH_META_MEMORY_PB//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_kib': $( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "int(r'${VIASH_META_MEMORY_KIB//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_mib': $( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "int(r'${VIASH_META_MEMORY_MIB//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_gib': $( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "int(r'${VIASH_META_MEMORY_GIB//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_tib': $( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "int(r'${VIASH_META_MEMORY_TIB//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'memory_pib': $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "int(r'${VIASH_META_MEMORY_PIB//\'/\'\"\'\"r\'}')"; else echo None; fi )
}
dep = {
  
}

## VIASH END

sys.path.append(meta["resources_dir"])
from setup_logger import setup_logger

logger = setup_logger()


logger.info("Reading input mudata")
mdata = mu.read_h5mu(par["input"])

mod = par["modality"]
logger.info("Performing log transformation on modality %s", mod)
data = mdata.mod[mod]

# import pathlib
# with pathlib.Path(os.path.dirname(par["output"])) / "cellbender" as temp_dir:
#     os.mkdir(temp_dir)
with tempfile.TemporaryDirectory(
    prefix="cellbender-", dir=meta["temp_dir"]
) as temp_dir:
    # construct paths within tempdir
    input_file = os.path.join(temp_dir, "input.h5ad")
    output_file = os.path.join(temp_dir, "output.h5")

    logger.info("Creating AnnData input file for CellBender: '%s'", input_file)
    data.write_h5ad(input_file)

    logger.info("Constructing CellBender command")
    cmd_pars = [
        "cellbender",
        "remove-background",
        "--input",
        input_file,
        "--output",
        output_file,
        # don't create checkpoints because they're not used / returned anyways
        "--checkpoint-mins",
        "99999999",
    ]

    if meta.get("cpus") is not None:
        cmd_pars += ["--cpu-threads", str(meta["cpus"])]

    extra_args = [
        ("--expected-cells", "expected_cells", True),
        ("--total-droplets-included", "total_droplets_included", True),
        ("--force-cell-umi-prior", "force_cell_umi_prior", True),
        ("--force-empty-umi-prior", "force_empty_umi_prior", True),
        ("--model", "model", True),
        ("--epochs", "epochs", True),
        ("--low-count-threshold", "low_count_threshold", True),
        ("--z-dim", "z_dim", True),
        ("--z-layers", "z_layers", True),
        ("--training-fraction", "training_fraction", True),
        ("--empty-drop-training-fraction", "empty_drop_training_fraction", True),
        ("--ignore-features", "ignore_features", True),
        ("--fpr", "fpr", True),
        ("--exclude-feature-types", "exclude_feature_types", True),
        (
            "--projected-ambient-count-threshold",
            "projected_ambient_count_threshold",
            True,
        ),
        ("--learning-rate", "learning_rate", True),
        ("--final-elbo-fail-fraction", "final_elbo_fail_fraction", True),
        ("--epoch-elbo-fail-fraction", "epoch_elbo_fail_fraction", True),
        ("--num-training-tries", "num_training_tries", True),
        ("--learning-rate-retry-mult", "learning_rate_retry_mult", True),
        ("--posterior-batch-size", "posterior_batch_size", True),
        ("--posterior-regulation", "posterior_regulation", True),
        ("--alpha", "alpha", True),
        ("--q", "q", True),
        ("--estimator", "estimator", True),
        ("--estimator-multiple-cpu", "estimator_multiple_cpu", False),
        ("--constant-learning-rate", "constant_learning_rate", False),
        ("--debug", "debug", False),
        ("--cuda", "cuda", False),
    ]
    for flag, name, is_kwarg in extra_args:
        if par[name]:
            values = par[name] if isinstance(par[name], list) else [par[name]]
            cmd_pars += [flag] + [str(val) for val in values] if is_kwarg else [flag]

    if par["expected_cells_from_qc"] and "metrics_cellranger" in data.uns:
        assert par["expected_cells"] is None, (
            "If min_counts is defined, expected_cells should be undefined"
        )
        assert par["total_droplets_included"] is None, (
            "If min_counts is defined, expected_cells should be undefined"
        )
        met = data.uns["metrics_cellranger"]
        col_name = "Estimated Number of Cells"
        assert col_name in met.columns, (
            "%s should be a column in .obs[metrics_cellranger]"
        )
        est_cells = met[col_name].values[0]
        logger.info(
            "Selecting --expected-cells %d and --total-droplets-included %d",
            est_cells,
            est_cells * 5,
        )
        cmd_pars += [
            "--expected-cells",
            str(est_cells),
            "--total-droplets-included",
            str(5 * est_cells),
        ]

    logger.info("Running CellBender: '%s'", " ".join(cmd_pars))
    out = subprocess.check_output(cmd_pars).decode("utf-8")

    logger.info("Reading CellBender 10xh5 output file: '%s'", output_file)
    adata_out = anndata_from_h5(output_file, analyzed_barcodes_only=False)

    logger.info("CellBender output format:", adata_out)

    # AnnData object with n_obs x n_vars = 6794880 x 33538
    #     obs: 'cellbender_analyzed'
    #     var: 'ambient_expression', 'feature_type', 'genome', 'gene_id', 'cellbender_analyzed'
    #     uns: 'background_fraction', 'barcode_indices_for_latents', 'cell_probability', 'cell_size', 'droplet_efficiency', 'gene_expression_encoding',
    #          'cell_size_lognormal_std', 'empty_droplet_size_lognormal_loc', 'empty_droplet_size_lognormal_scale', 'swapping_fraction_dist_params',
    #          'barcodes_analyzed', 'barcodes_analyzed_inds', 'estimator', 'features_analyzed_inds', 'fraction_data_used_for_testing', 'learning_curve_learning_rate_epoch',
    #          'learning_curve_learning_rate_value', 'learning_curve_test_elbo', 'learning_curve_test_epoch', 'learning_curve_train_elbo', 'learning_curve_train_epoch',
    #          'target_false_positive_rate'

    logger.info("Copying X output to MuData")
    data.layers[par["layer_output"]] = adata_out.X

    logger.info("Copying .obs output to MuData")
    obs_store = {
        "obs_background_fraction": "background_fraction",
        "obs_cell_probability": "cell_probability",
        "obs_cell_size": "cell_size",
        "obs_droplet_efficiency": "droplet_efficiency",
        "obs_latent_scale": "latent_scale",
    }
    for to_name, from_name in obs_store.items():
        if par[to_name]:
            if from_name in adata_out.obs:
                data.obs[par[to_name]] = adata_out.obs[from_name]
            # when using unfiltered data, the values will be in uns instead of obs
            elif (
                from_name in adata_out.uns
                and "barcode_indices_for_latents" in adata_out.uns
            ):
                vec = np.zeros(data.n_obs)
                vec[adata_out.uns["barcode_indices_for_latents"]] = adata_out.uns[
                    from_name
                ]
                data.obs[par[to_name]] = vec

    logger.info("Copying .var output to MuData")
    var_store = {"var_ambient_expression": "ambient_expression"}
    for to_name, from_name in var_store.items():
        if par[to_name]:
            data.var[par[to_name]] = adata_out.var[from_name]

    logger.info("Copying obsm_gene_expression_encoding output to MuData")
    obsm_store = {"obsm_gene_expression_encoding": "gene_expression_encoding"}
    for to_name, from_name in obsm_store.items():
        if par[to_name]:
            if from_name in adata_out.obsm:
                data.obsm[par[to_name]] = adata_out.obsm[from_name]
            elif (
                from_name in adata_out.uns
                and "barcode_indices_for_latents" in adata_out.uns
            ):
                matrix_to_store = adata_out.uns[from_name]
                number_of_obs = data.X.shape[0]
                latent_space_sparse = csr_matrix(
                    (number_of_obs, par["z_dim"]), dtype=adata_out.uns[from_name].dtype
                )
                obs_rows_in_space_representation = adata_out.uns[
                    "barcode_indices_for_latents"
                ]
                latent_space_sparse[obs_rows_in_space_representation] = adata_out.uns[
                    from_name
                ]
                data.obsm[par[to_name]] = latent_space_sparse
            else:
                raise RuntimeError(
                    "Requested to save latent gene encoding, but the data is either missing "
                    "from cellbender output or in an incorrect format."
                )


logger.info("Writing to file %s", par["output"])
mdata.write_h5mu(filename=par["output"], compression=par["output_compression"])
VIASHMAIN
python -B "\$tempscript" &
wait "\$!"

VIASHEOF


if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
  # strip viash automount from file paths
  
  if [ ! -z "$VIASH_PAR_INPUT" ]; then
    VIASH_PAR_INPUT=$(ViashDockerStripAutomount "$VIASH_PAR_INPUT")
  fi
  if [ ! -z "$VIASH_PAR_OUTPUT" ]; then
    VIASH_PAR_OUTPUT=$(ViashDockerStripAutomount "$VIASH_PAR_OUTPUT")
  fi
  if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then
    VIASH_META_RESOURCES_DIR=$(ViashDockerStripAutomount "$VIASH_META_RESOURCES_DIR")
  fi
  if [ ! -z "$VIASH_META_EXECUTABLE" ]; then
    VIASH_META_EXECUTABLE=$(ViashDockerStripAutomount "$VIASH_META_EXECUTABLE")
  fi
  if [ ! -z "$VIASH_META_CONFIG" ]; then
    VIASH_META_CONFIG=$(ViashDockerStripAutomount "$VIASH_META_CONFIG")
  fi
  if [ ! -z "$VIASH_META_TEMP_DIR" ]; then
    VIASH_META_TEMP_DIR=$(ViashDockerStripAutomount "$VIASH_META_TEMP_DIR")
  fi
fi


# check whether required files exist
if [ ! -z "$VIASH_PAR_OUTPUT" ] && [ ! -e "$VIASH_PAR_OUTPUT" ]; then
  ViashError "Output file '$VIASH_PAR_OUTPUT' does not exist."
  exit 1
fi


exit 0
