#!/usr/bin/env bash

# cellranger_multi v4.0.4
# 
# 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.
# 
# Component authors:
#  * Dries Schaumont (maintainer)
#  * Angela Oliveira Pisco (author)
#  * Robrecht Cannoodt (author, maintainer)
#  * Dries De Maeyer (author)
#  * Weiwei Schultz (contributor)
#  * Dorien Roosen (author)

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="cellranger_multi"
VIASH_META_FUNCTIONALITY_NAME="cellranger_multi"
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 quay.io/nf-core/cellranger:10.0.0
ENTRYPOINT []
RUN apt-get update && \
  DEBIAN_FRONTEND=noninteractive apt-get install -y procps && \
  rm -rf /var/lib/apt/lists/*

RUN cellranger telemetry disable
RUN pip install --upgrade pip && \
  pip install --upgrade --no-cache-dir "pandas" "pyyaml"

LABEL org.opencontainers.image.authors="Dries Schaumont, Angela Oliveira Pisco, Robrecht Cannoodt, Dries De Maeyer, Weiwei Schultz, Dorien Roosen"
LABEL org.opencontainers.image.description="Companion container for running component mapping cellranger_multi"
LABEL org.opencontainers.image.created="2026-03-17T13:31:44Z"
LABEL org.opencontainers.image.source="https://github.com/openpipelines-bio/openpipeline"
LABEL org.opencontainers.image.revision="fb7dc76676aa63d06ae1421bbdd6312ad4f67312"
LABEL org.opencontainers.image.version="v4.0.4"

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 "cellranger_multi v4.0.4"
  echo ""
  echo "Align fastq files using Cell Ranger multi."
  echo ""
  echo "Input files:"
  echo "    --input"
  echo "        type: file, multiple values allowed, file must exist"
  echo "        example:"
  echo "mysample_S1_L001_R1_001.fastq.gz;mysample_S1_L001_R2_001.fastq.gz"
  echo "        The FASTQ files to be analyzed. FASTQ files should conform to the naming"
  echo "        conventions of bcl2fastq and mkfastq:"
  echo "        \`[Sample Name]_S[Sample Index]_L00[Lane Number]_[Read"
  echo "        Type]_001.fastq.gz\`"
  echo ""
  echo "Feature type-specific input files:"
  echo "    Helper functionality to allow feature type-specific input files, without the"
  echo "    need to specify"
  echo "    library_type or library_id. The library_id will be inferred from the input"
  echo "    paths."
  echo ""
  echo "    --gex_input"
  echo "        type: file, multiple values allowed, file must exist"
  echo "        example:"
  echo "mysample_S1_L001_R1_001.fastq.gz;mysample_S1_L001_R2_001.fastq.gz"
  echo "        The FASTQ files to be analyzed for Gene Expression. FASTQ files should"
  echo "        conform to the"
  echo "        naming conventions of bcl2fastq and mkfastq:"
  echo "        \`[Sample Name]_S[Sample Index]_L00[Lane Number]_[Read"
  echo "        Type]_001.fastq.gz\`"
  echo ""
  echo "    --abc_input"
  echo "        type: file, multiple values allowed, file must exist"
  echo "        example:"
  echo "mysample_S1_L001_R1_001.fastq.gz;mysample_S1_L001_R2_001.fastq.gz"
  echo "        The FASTQ files to be analyzed for Antibody Capture. FASTQ files should"
  echo "        conform to"
  echo "        the naming conventions of bcl2fastq and mkfastq:"
  echo "        \`[Sample Name]_S[Sample Index]_L00[Lane Number]_[Read"
  echo "        Type]_001.fastq.gz\`"
  echo ""
  echo "    --cgc_input"
  echo "        type: file, multiple values allowed, file must exist"
  echo "        example:"
  echo "mysample_S1_L001_R1_001.fastq.gz;mysample_S1_L001_R2_001.fastq.gz"
  echo "        The FASTQ files to be analyzed for CRISPR Guide Capture. FASTQ files"
  echo "        should conform to"
  echo "        the naming conventions of bcl2fastq and mkfastq:"
  echo "        \`[Sample Name]_S[Sample Index]_L00[Lane Number]_[Read"
  echo "        Type]_001.fastq.gz\`"
  echo ""
  echo "    --mux_input"
  echo "        type: file, multiple values allowed, file must exist"
  echo "        example:"
  echo "mysample_S1_L001_R1_001.fastq.gz;mysample_S1_L001_R2_001.fastq.gz"
  echo "        The FASTQ files to be analyzed for Multiplexing Capture. FASTQ files"
  echo "        should conform to"
  echo "        the naming conventions of bcl2fastq and mkfastq:"
  echo "        \`[Sample Name]_S[Sample Index]_L00[Lane Number]_[Read"
  echo "        Type]_001.fastq.gz\`"
  echo ""
  echo "    --vdj_input"
  echo "        type: file, multiple values allowed, file must exist"
  echo "        example:"
  echo "mysample_S1_L001_R1_001.fastq.gz;mysample_S1_L001_R2_001.fastq.gz"
  echo "        The FASTQ files to be analyzed for VDJ. FASTQ files should conform to"
  echo "        the"
  echo "        naming conventions of bcl2fastq and mkfastq:"
  echo "        \`[Sample Name]_S[Sample Index]_L00[Lane Number]_[Read"
  echo "        Type]_001.fastq.gz\`"
  echo ""
  echo "    --vdj_t_input"
  echo "        type: file, multiple values allowed, file must exist"
  echo "        example:"
  echo "mysample_S1_L001_R1_001.fastq.gz;mysample_S1_L001_R2_001.fastq.gz"
  echo "        The FASTQ files to be analyzed for VDJ-T. FASTQ files should conform to"
  echo "        the naming"
  echo "        conventions of bcl2fastq and mkfastq:"
  echo "        \`[Sample Name]_S[Sample Index]_L00[Lane Number]_[Read"
  echo "        Type]_001.fastq.gz\`"
  echo ""
  echo "    --vdj_t_gd_input"
  echo "        type: file, multiple values allowed, file must exist"
  echo "        example:"
  echo "mysample_S1_L001_R1_001.fastq.gz;mysample_S1_L001_R2_001.fastq.gz"
  echo "        The FASTQ files to be analyzed for VDJ-T-GD. FASTQ files should conform"
  echo "        to"
  echo "        the naming conventions of bcl2fastq and mkfastq:"
  echo "        \`[Sample Name]_S[Sample Index]_L00[Lane Number]_[Read"
  echo "        Type]_001.fastq.gz\`"
  echo ""
  echo "    --vdj_b_input"
  echo "        type: file, multiple values allowed, file must exist"
  echo "        example:"
  echo "mysample_S1_L001_R1_001.fastq.gz;mysample_S1_L001_R2_001.fastq.gz"
  echo "        The FASTQ files to be analyzed for VDJ-B. FASTQ files should conform to"
  echo "        the naming conventions of bcl2fastq and mkfastq:"
  echo "        \`[Sample Name]_S[Sample Index]_L00[Lane Number]_[Read"
  echo "        Type]_001.fastq.gz\`"
  echo ""
  echo "    --agc_input"
  echo "        type: file, multiple values allowed, file must exist"
  echo "        example:"
  echo "mysample_S1_L001_R1_001.fastq.gz;mysample_S1_L001_R2_001.fastq.gz"
  echo "        The FASTQ files to be analyzed for Antigen Capture. FASTQ files should"
  echo "        conform to"
  echo "        the naming conventions of bcl2fastq and mkfastq:"
  echo "        \`[Sample Name]_S[Sample Index]_L00[Lane Number]_[Read"
  echo "        Type]_001.fastq.gz\`"
  echo ""
  echo "Library arguments:"
  echo "    --library_id"
  echo "        type: string, multiple values allowed"
  echo "        example: mysample1"
  echo "        The Illumina sample name to analyze. This must exactly match the 'Sample"
  echo "        Name'part"
  echo "        of the FASTQ files specified in the \`--input\` argument."
  echo ""
  echo "    --library_type"
  echo "        type: string, multiple values allowed"
  echo "        example: Gene Expression"
  echo "        choices: [ Gene Expression, VDJ, VDJ-T, VDJ-B, VDJ-T-GD, Antibody"
  echo "Capture, CRISPR Guide Capture, Multiplexing Capture, Antigen Capture, Custom ]"
  echo "        The underlying feature type of the library."
  echo ""
  echo "    --library_subsample"
  echo "        type: string, multiple values allowed"
  echo "        example: 0.5"
  echo "        The rate at which reads from the provided FASTQ files are sampled."
  echo "        Must be strictly greater than 0 and less than or equal to 1."
  echo ""
  echo "    --library_lanes"
  echo "        type: string, multiple values allowed"
  echo "        example: 1-4"
  echo "        Lanes associated with this sample. Defaults to using all lanes."
  echo ""
  echo "    --library_chemistry"
  echo "        type: string"
  echo "        Only applicable to FRP. Library-specific assay configuration. By"
  echo "        default,"
  echo "        the assay configuration is detected automatically. Typically, users will"
  echo "        not need to specify a chemistry."
  echo ""
  echo "Sample parameters:"
  echo "    --cell_multiplex_sample_id, --sample_ids"
  echo "        type: string, multiple values allowed"
  echo "        A name to identify a multiplexed sample. Must be alphanumeric with"
  echo "        hyphens and/or underscores,"
  echo "        and less than 64 characters. Required for Cell Multiplexing libraries."
  echo ""
  echo "    --cell_multiplex_description, --sample_description"
  echo "        type: string, multiple values allowed"
  echo "        A description for the sample."
  echo ""
  echo "    --sample_expect_cells"
  echo "        type: integer, multiple values allowed"
  echo "        example: 3000"
  echo "        Expected number of recovered cells, used as input to cell calling"
  echo "        algorithm."
  echo ""
  echo "    --sample_force_cells"
  echo "        type: integer, multiple values allowed"
  echo "        example: 3000"
  echo "        Force pipeline to use this number of cells, bypassing cell detection."
  echo ""
  echo "Feature Barcode library specific arguments:"
  echo "    --feature_reference"
  echo "        type: file, file must exist"
  echo "        example: feature_reference.csv"
  echo "        Path to the Feature reference CSV file, declaring Feature Barcode"
  echo "        constructs and associated barcodes."
  echo "        Required only for Antibody Capture or CRISPR Guide Capture libraries."
  echo "        See"
  echo "       "
  echo "https://support.10xgenomics.com/single-cell-gene-expression/software/pipelines/latest/using/feature-bc-analysis#feature-ref"
  echo "        for more information.\""
  echo ""
  echo "    --feature_r1_length"
  echo "        type: integer"
  echo "        Limit the length of the input Read 1 sequence of V(D)J libraries to the"
  echo "        first N bases,"
  echo "        where N is the user-supplied value. Note that the length includes the"
  echo "        Barcode and UMI"
  echo "        sequences so do not set this below 26."
  echo ""
  echo "    --feature_r2_length"
  echo "        type: integer"
  echo "        Limit the length of the input Read 2 sequence of V(D)J libraries to the"
  echo "        first N bases,"
  echo "        where N is a user-supplied value. Trimming occurs before sequencing"
  echo "        metrics are computed"
  echo "        and therefore, limiting the length of Read 2 may affect Q30 scores."
  echo ""
  echo "    --min_crispr_umi"
  echo "        type: integer"
  echo "        min: 1"
  echo "        Set the minimum number of CRISPR guide RNA UMIs required for protospacer"
  echo "        detection."
  echo "        If a lower or higher sensitivity is desired for detection, this value"
  echo "        can be customized"
  echo "        according to specific experimental needs. Applicable only to datasets"
  echo "        that include a"
  echo "        CRISPR Guide Capture library."
  echo ""
  echo "Gene expression arguments:"
  echo "    Arguments relevant to the analysis of gene expression data."
  echo ""
  echo "    --gex_reference"
  echo "        type: file, required parameter, file must exist"
  echo "        example: reference_genome.tar.gz"
  echo "        Genome refence index built by Cell Ranger mkref."
  echo ""
  echo "    --gex_secondary_analysis"
  echo "        type: boolean"
  echo "        default: false"
  echo "        Whether or not to run the secondary analysis e.g. clustering."
  echo ""
  echo "    --gex_generate_bam"
  echo "        type: boolean"
  echo "        default: false"
  echo "        Whether to generate a BAM file."
  echo ""
  echo "    --tenx_cloud_token_path"
  echo "        type: file, file must exist"
  echo "        The 10x Cloud Analysis user token used to enable cell annotation."
  echo ""
  echo "    --cell_annotation_model"
  echo "        type: string"
  echo "        choices: [ auto, human_pca_v1_beta, mouse_pca_v1_beta ]"
  echo "        \"Cell annotation model to use. If auto, uses the default model for the"
  echo "        species."
  echo "        If not given, does not run cell annotation.\""
  echo ""
  echo "    --gex_expect_cells"
  echo "        type: integer"
  echo "        example: 3000"
  echo "        Expected number of recovered cells, used as input to cell calling"
  echo "        algorithm."
  echo ""
  echo "    --gex_force_cells"
  echo "        type: integer"
  echo "        example: 3000"
  echo "        Force pipeline to use this number of cells, bypassing cell detection."
  echo ""
  echo "    --gex_include_introns"
  echo "        type: boolean"
  echo "        default: true"
  echo "        Whether or not to include intronic reads in counts."
  echo "        This option does not apply to Fixed RNA Profiling analysis."
  echo ""
  echo "    --gex_r1_length"
  echo "        type: integer"
  echo "        Limit the length of the input Read 1 sequence of V(D)J libraries to the"
  echo "        first N bases,"
  echo "        where N is the user-supplied value. Note that the length includes the"
  echo "        Barcode and UMI"
  echo "        sequences so do not set this below 26."
  echo ""
  echo "    --gex_r2_length"
  echo "        type: integer"
  echo "        Limit the length of the input Read 2 sequence of V(D)J libraries to the"
  echo "        first N bases,"
  echo "        where N is a user-supplied value. Trimming occurs before sequencing"
  echo "        metrics are computed"
  echo "        and therefore, limiting the length of Read 2 may affect Q30 scores."
  echo ""
  echo "    --gex_chemistry"
  echo "        type: string"
  echo "        default: auto"
  echo "        choices: [ auto, threeprime, fiveprime, SC3Pv1, SC3Pv2, SC3Pv3,"
  echo "SC3Pv3-polyA, SC3Pv4, SC3Pv4-polyA, SC3Pv3LT, SC3Pv3HT, SC3Pv3HT-polyA, SC5P-PE,"
  echo "SC5P-PE-v3, SC5P-R2, SC-FB, SC5P-R2-v3, SCP5-PE-v3, SC5PHT, MFRP, MFRP-R1,"
  echo "MFRP-RNA, MFRP-Ab, SFRP, MFRP-Ab-R2pos50, MFRP-RNA-R1, MFRP-Ab-R1, ARC-v1 ]"
  echo "        Assay configuration. Either specify a single value which will be applied"
  echo "        to all libraries,"
  echo "        or a number of values that is equal to the number of libararies. The"
  echo "        latter is only applicable"
  echo "        to only applicable to Fixed RNA Profiling."
  echo "          - auto: Chemistry autodetection (default)"
  echo "          - threeprime: Single Cell 3'"
  echo "          - SC3Pv1, SC3Pv2, SC3Pv3(-polyA), SC3Pv4(-polyA): Single Cell 3' v1,"
  echo "        v2, v3, or v4"
  echo "          - SC3Pv3HT(-polyA): Single Cell 3' v3.1 HT"
  echo "          - SC-FB: Single Cell Antibody-only 3' v2 or 5'"
  echo "          - fiveprime: Single Cell 5'"
  echo "          - SC5P-PE: Paired-end Single Cell 5'"
  echo "          - SC5P-PE-v3: Paired-end Single Cell 5' v3"
  echo "          - SC5P-R2: R2-only Single Cell 5'"
  echo "          - SC5P-R2-v3: R2-only Single Cell 5' v3"
  echo "          - SCP5-PE-v3: Single Cell 5' paired-end v3 (GEM-X)"
  echo "          - SC5PHT : Single Cell 5' v2 HT"
  echo "          - SFRP: Fixed RNA Profiling (Singleplex)"
  echo "          - MFRP: Fixed RNA Profiling (Multiplex, Probe Barcode on R2)"
  echo "          - MFRP-R1: Fixed RNA Profiling (Multiplex, Probe Barcode on R1)"
  echo "          - MFRP-RNA: Fixed RNA Profiling (Multiplex, RNA, Probe Barcode on R2)"
  echo "          - MFRP-Ab: Fixed RNA Profiling (Multiplex, Antibody, Probe Barcode at"
  echo "        R2:69)"
  echo "          - MFRP-Ab-R2pos50: Fixed RNA Profiling (Multiplex, Antibody, Probe"
  echo "        Barcode at R2:50)"
  echo "          - MFRP-RNA-R1: Fixed RNA Profiling (Multiplex, RNA, Probe Barcode on"
  echo "        R1)"
  echo "          - MFRP-Ab-R1: Fixed RNA Profiling (Multiplex, Antibody, Probe Barcode"
  echo "        on R1)"
  echo "          - ARC-v1 for analyzing the Gene Expression portion of Multiome data."
  echo "        If Cell Ranger auto-detects ARC-v1 chemistry, an error is triggered."
  echo "        See"
  echo "       "
  echo "https://kb.10xgenomics.com/hc/en-us/articles/115003764132-How-does-Cell-Ranger-auto-detect-chemistry-"
  echo "        for more information."
  echo ""
  echo "VDJ related parameters:"
  echo "    --vdj_reference"
  echo "        type: file, file must exist"
  echo "        example: reference_vdj.tar.gz"
  echo "        VDJ refence index built by Cell Ranger mkref."
  echo ""
  echo "    --vdj_inner_enrichment_primers"
  echo "        type: file, file must exist"
  echo "        example: enrichment_primers.txt"
  echo "        V(D)J Immune Profiling libraries: if inner enrichment primers other than"
  echo "        those provided"
  echo "        in the 10x Genomics kits are used, they need to be specified here as a"
  echo "        text file with one primer per line."
  echo ""
  echo "    --vdj_r1_length"
  echo "        type: integer"
  echo "        Limit the length of the input Read 1 sequence of V(D)J libraries to the"
  echo "        first N bases, where N is the user-supplied value."
  echo "        Note that the length includes the Barcode and UMI sequences so do not"
  echo "        set this below 26."
  echo ""
  echo "    --vdj_r2_length"
  echo "        type: integer"
  echo "        Limit the length of the input Read 2 sequence of V(D)J libraries to the"
  echo "        first N bases, where N is a user-supplied value."
  echo "        Trimming occurs before sequencing metrics are computed and therefore,"
  echo "        limiting the length of Read 2 may affect Q30 scores"
  echo ""
  echo "    --vdj_denovo"
  echo "        type: boolean"
  echo "        Run in reference-free mode (i.e., do not use annotations). This option"
  echo "        is not supported for multiplexed experiments."
  echo ""
  echo "3' Cell multiplexing parameters (CellPlex Multiplexing):"
  echo "    --cmo_ids, --cell_multiplex_oligo_ids"
  echo "        type: string, multiple values allowed"
  echo "        The Cell Multiplexing oligo IDs used to multiplex this sample. If"
  echo "        multiple CMOs were used for a sample,"
  echo "        separate IDs with a pipe (e.g., CMO301|CMO302). Required for Cell"
  echo "        Multiplexing libraries."
  echo ""
  echo "    --min_assignment_confidence"
  echo "        type: double"
  echo "        The minimum estimated likelihood to call a sample as tagged with a Cell"
  echo "        Multiplexing Oligo (CMO) instead of \"Unassigned\"."
  echo "        Users may wish to tolerate a higher rate of mis-assignment in order to"
  echo "        obtain more singlets to include in their analysis,"
  echo "        or a lower rate of mis-assignment at the cost of obtaining fewer"
  echo "        singlets."
  echo ""
  echo "    --cmo_set"
  echo "        type: file, file must exist"
  echo "        Path to a custom CMO set CSV file, declaring CMO constructs and"
  echo "        associated barcodes. If the default CMO reference IDs that are built"
  echo "        into"
  echo "        the Cell Ranger software are required, this option does not need to be"
  echo "        used."
  echo ""
  echo "    --barcode_sample_assignment"
  echo "        type: file, file must exist"
  echo "        Path to a barcode-sample assignment CSV file that specifies the barcodes"
  echo "        that belong to each sample."
  echo ""
  echo "Hashtag multiplexing parameters:"
  echo "    --hashtag_ids"
  echo "        type: string, multiple values allowed"
  echo "        The hashtag IDs used to multiplex this sample. If multiple antibody"
  echo "        hashtags were used for the same sample,"
  echo "        you can separate IDs with a pipe."
  echo ""
  echo "On-chip multiplexing parameters:"
  echo "    --ocm_barcode_ids"
  echo "        type: string, multiple values allowed"
  echo "        The OCM barcode IDs used to multiplex this sample. Must be one of OB1,"
  echo "        OB2, OB3, OB4."
  echo "        If multiple OCM Barcodes were used for the same sample, you can separate"
  echo "        IDs"
  echo "        with a pipe (e.g., OB1|OB2)."
  echo ""
  echo "Flex multiplexing paramaters:"
  echo "    --probe_set"
  echo "        type: file, file must exist"
  echo "        A probe set reference CSV file. It specifies the sequences used as a"
  echo "        reference for probe alignment and the gene ID associated with each"
  echo "        probe."
  echo "        It must include 4 columns (probe file format 1.0.0):"
  echo "        gene_id,probe_seq,probe_id,included,region and an optional 5th column"
  echo "        (probe file format 1.0.1)."
  echo "        - gene_id: The Ensembl gene identifier targeted by the probe."
  echo "        - probe_seq: The nucleotide sequence of the probe, which is"
  echo "        complementary to the transcript sequence."
  echo "        - probe_id: The probe identifier, whose format is described in Probe"
  echo "        identifiers."
  echo "        - included: A TRUE or FALSE flag specifying whether the probe is"
  echo "        included in the filtered counts matrix output or excluded by the probe"
  echo "        filter."
  echo "                    See filter-probes option of cellranger multi. All probes of"
  echo "        a gene must be marked TRUE in the included column for that gene to be"
  echo "        included."
  echo "        - region: Present only in v1.0.1 probe set reference CSV. The gene"
  echo "        boundary targeted by the probe. Accepted values are spliced or"
  echo "        unspliced."
  echo "        The file also contains a number of required metadata fields in the"
  echo "        header in the format #key=value:"
  echo "        - panel_name: The name of the probe set."
  echo "        - panel_type: Always predesigned for predesigned probe sets."
  echo "        - reference_genome: The reference genome build used for probe design."
  echo "        - reference_version: The version of the Cell Ranger reference"
  echo "        transcriptome used for probe design."
  echo "        - probe_set_file_format: The version of the probe set file format"
  echo "        specification that this file conforms to."
  echo ""
  echo "    --filter_probes"
  echo "        type: boolean"
  echo "        If 'false', include all non-deprecated probes listed in the probe set"
  echo "        reference CSV file."
  echo "        If 'true' or not set, probes that are predicted to have off-target"
  echo "        activity to homologous genes are excluded from analysis."
  echo "        Not filtering will result in UMI counts from all non-deprecated probes,"
  echo "        including those with predicted off-target activity, to be used in the"
  echo "        analysis."
  echo "        Probes whose ID is prefixed with DEPRECATED are always excluded from the"
  echo "        analysis."
  echo ""
  echo "    --probe_barcode_ids"
  echo "        type: string, multiple values allowed"
  echo "        The Fixed RNA Probe Barcode ID used for this sample, and for multiplex"
  echo "        GEX + Antibody Capture libraries,"
  echo "        the corresponding Antibody Multiplexing Barcode IDs. 10x recommends"
  echo "        specifying both barcodes (e.g., BC001+AB001)"
  echo "        when an Antibody Capture library is present. The barcode pair order is"
  echo "        BC+AB and they"
  echo "        are separated with a \"+\" (no spaces). Alternatively, you can specify the"
  echo "        Probe Barcode ID alone and"
  echo "        Cell Ranger's barcode pairing auto-detection algorithm will"
  echo "        automatically match to the corresponding Antibody"
  echo "        Multiplexing Barcode."
  echo ""
  echo "    --emptydrops_minimum_umis"
  echo "        type: integer"
  echo "        min: 1"
  echo "        For singleplex Flex experiments, use this option to adjust the UMI"
  echo "        cutoff during the second step of cell calling."
  echo "        Cell Ranger will still perform the full cell calling process but will"
  echo "        only evaluate barcodes with UMIs above"
  echo "        the threshold you specify."
  echo ""
  echo "Antigen Capture (BEAM) libary arguments:"
  echo "    These arguments are recommended if an Antigen Capture (BEAM) library is"
  echo "    present."
  echo "    It is needed to calculate the antigen specificity score."
  echo ""
  echo "    --control_id"
  echo "        type: string, multiple values allowed"
  echo "        A user-defined ID for any negative controls used in the T/BCR Antigen"
  echo "        Capture assay. Must match id specified in the feature reference CSV."
  echo "        May only include ASCII characters and must not use whitespace, slash,"
  echo "        quote, or comma characters."
  echo "        Each ID must be unique and must not collide with a gene identifier from"
  echo "        the transcriptome."
  echo ""
  echo "    --mhc_allele"
  echo "        type: string, multiple values allowed"
  echo "        The MHC allele for TCR Antigen Capture libraries. Must match mhc_allele"
  echo "        name specified in the Feature Reference CSV."
  echo ""
  echo "General arguments:"
  echo "    These arguments are applicable to all library types."
  echo ""
  echo "    --check_library_compatibility"
  echo "        type: boolean"
  echo "        default: true"
  echo "        Optional. This option allows users to disable the check that evaluates"
  echo "        10x Barcode overlap between"
  echo "        ibraries when multiple libraries are specified (e.g., Gene Expression +"
  echo "        Antibody Capture). Setting"
  echo "        this option to false will disable the check across all library"
  echo "        combinations. We recommend running"
  echo "        this check (default), however if the pipeline errors out, users can"
  echo "        bypass the check to generate"
  echo "        outputs for troubleshooting."
  echo ""
  echo "Outputs:"
  echo "    --output"
  echo "        type: file, required parameter, output, file must exist"
  echo "        example: /path/to/output"
  echo "        The folder to store the alignment results."
  echo ""
  echo "Executor arguments:"
  echo "    --dryrun"
  echo "        type: boolean_true"
  echo "        If true, the output directory will only contain the CWL input files, but"
  echo "        the pipeline itself will not be executed."
  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 "cellranger_multi v4.0.4"
            exit
            ;;
        --input)
            if [ -z "$VIASH_PAR_INPUT" ]; then
              VIASH_PAR_INPUT="$2"
            else
              VIASH_PAR_INPUT="$VIASH_PAR_INPUT;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --input=*)
            if [ -z "$VIASH_PAR_INPUT" ]; then
              VIASH_PAR_INPUT=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_INPUT="$VIASH_PAR_INPUT;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --gex_input)
            if [ -z "$VIASH_PAR_GEX_INPUT" ]; then
              VIASH_PAR_GEX_INPUT="$2"
            else
              VIASH_PAR_GEX_INPUT="$VIASH_PAR_GEX_INPUT;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --gex_input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --gex_input=*)
            if [ -z "$VIASH_PAR_GEX_INPUT" ]; then
              VIASH_PAR_GEX_INPUT=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_GEX_INPUT="$VIASH_PAR_GEX_INPUT;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --abc_input)
            if [ -z "$VIASH_PAR_ABC_INPUT" ]; then
              VIASH_PAR_ABC_INPUT="$2"
            else
              VIASH_PAR_ABC_INPUT="$VIASH_PAR_ABC_INPUT;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --abc_input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --abc_input=*)
            if [ -z "$VIASH_PAR_ABC_INPUT" ]; then
              VIASH_PAR_ABC_INPUT=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_ABC_INPUT="$VIASH_PAR_ABC_INPUT;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --cgc_input)
            if [ -z "$VIASH_PAR_CGC_INPUT" ]; then
              VIASH_PAR_CGC_INPUT="$2"
            else
              VIASH_PAR_CGC_INPUT="$VIASH_PAR_CGC_INPUT;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --cgc_input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --cgc_input=*)
            if [ -z "$VIASH_PAR_CGC_INPUT" ]; then
              VIASH_PAR_CGC_INPUT=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_CGC_INPUT="$VIASH_PAR_CGC_INPUT;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --mux_input)
            if [ -z "$VIASH_PAR_MUX_INPUT" ]; then
              VIASH_PAR_MUX_INPUT="$2"
            else
              VIASH_PAR_MUX_INPUT="$VIASH_PAR_MUX_INPUT;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --mux_input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --mux_input=*)
            if [ -z "$VIASH_PAR_MUX_INPUT" ]; then
              VIASH_PAR_MUX_INPUT=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_MUX_INPUT="$VIASH_PAR_MUX_INPUT;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --vdj_input)
            if [ -z "$VIASH_PAR_VDJ_INPUT" ]; then
              VIASH_PAR_VDJ_INPUT="$2"
            else
              VIASH_PAR_VDJ_INPUT="$VIASH_PAR_VDJ_INPUT;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --vdj_input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --vdj_input=*)
            if [ -z "$VIASH_PAR_VDJ_INPUT" ]; then
              VIASH_PAR_VDJ_INPUT=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_VDJ_INPUT="$VIASH_PAR_VDJ_INPUT;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --vdj_t_input)
            if [ -z "$VIASH_PAR_VDJ_T_INPUT" ]; then
              VIASH_PAR_VDJ_T_INPUT="$2"
            else
              VIASH_PAR_VDJ_T_INPUT="$VIASH_PAR_VDJ_T_INPUT;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --vdj_t_input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --vdj_t_input=*)
            if [ -z "$VIASH_PAR_VDJ_T_INPUT" ]; then
              VIASH_PAR_VDJ_T_INPUT=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_VDJ_T_INPUT="$VIASH_PAR_VDJ_T_INPUT;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --vdj_t_gd_input)
            if [ -z "$VIASH_PAR_VDJ_T_GD_INPUT" ]; then
              VIASH_PAR_VDJ_T_GD_INPUT="$2"
            else
              VIASH_PAR_VDJ_T_GD_INPUT="$VIASH_PAR_VDJ_T_GD_INPUT;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --vdj_t_gd_input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --vdj_t_gd_input=*)
            if [ -z "$VIASH_PAR_VDJ_T_GD_INPUT" ]; then
              VIASH_PAR_VDJ_T_GD_INPUT=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_VDJ_T_GD_INPUT="$VIASH_PAR_VDJ_T_GD_INPUT;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --vdj_b_input)
            if [ -z "$VIASH_PAR_VDJ_B_INPUT" ]; then
              VIASH_PAR_VDJ_B_INPUT="$2"
            else
              VIASH_PAR_VDJ_B_INPUT="$VIASH_PAR_VDJ_B_INPUT;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --vdj_b_input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --vdj_b_input=*)
            if [ -z "$VIASH_PAR_VDJ_B_INPUT" ]; then
              VIASH_PAR_VDJ_B_INPUT=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_VDJ_B_INPUT="$VIASH_PAR_VDJ_B_INPUT;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --agc_input)
            if [ -z "$VIASH_PAR_AGC_INPUT" ]; then
              VIASH_PAR_AGC_INPUT="$2"
            else
              VIASH_PAR_AGC_INPUT="$VIASH_PAR_AGC_INPUT;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --agc_input. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --agc_input=*)
            if [ -z "$VIASH_PAR_AGC_INPUT" ]; then
              VIASH_PAR_AGC_INPUT=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_AGC_INPUT="$VIASH_PAR_AGC_INPUT;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --library_id)
            if [ -z "$VIASH_PAR_LIBRARY_ID" ]; then
              VIASH_PAR_LIBRARY_ID="$2"
            else
              VIASH_PAR_LIBRARY_ID="$VIASH_PAR_LIBRARY_ID;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --library_id. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --library_id=*)
            if [ -z "$VIASH_PAR_LIBRARY_ID" ]; then
              VIASH_PAR_LIBRARY_ID=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_LIBRARY_ID="$VIASH_PAR_LIBRARY_ID;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --library_type)
            if [ -z "$VIASH_PAR_LIBRARY_TYPE" ]; then
              VIASH_PAR_LIBRARY_TYPE="$2"
            else
              VIASH_PAR_LIBRARY_TYPE="$VIASH_PAR_LIBRARY_TYPE;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --library_type. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --library_type=*)
            if [ -z "$VIASH_PAR_LIBRARY_TYPE" ]; then
              VIASH_PAR_LIBRARY_TYPE=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_LIBRARY_TYPE="$VIASH_PAR_LIBRARY_TYPE;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --library_subsample)
            if [ -z "$VIASH_PAR_LIBRARY_SUBSAMPLE" ]; then
              VIASH_PAR_LIBRARY_SUBSAMPLE="$2"
            else
              VIASH_PAR_LIBRARY_SUBSAMPLE="$VIASH_PAR_LIBRARY_SUBSAMPLE;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --library_subsample. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --library_subsample=*)
            if [ -z "$VIASH_PAR_LIBRARY_SUBSAMPLE" ]; then
              VIASH_PAR_LIBRARY_SUBSAMPLE=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_LIBRARY_SUBSAMPLE="$VIASH_PAR_LIBRARY_SUBSAMPLE;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --library_lanes)
            if [ -z "$VIASH_PAR_LIBRARY_LANES" ]; then
              VIASH_PAR_LIBRARY_LANES="$2"
            else
              VIASH_PAR_LIBRARY_LANES="$VIASH_PAR_LIBRARY_LANES;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --library_lanes. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --library_lanes=*)
            if [ -z "$VIASH_PAR_LIBRARY_LANES" ]; then
              VIASH_PAR_LIBRARY_LANES=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_LIBRARY_LANES="$VIASH_PAR_LIBRARY_LANES;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --library_chemistry)
            [ -n "$VIASH_PAR_LIBRARY_CHEMISTRY" ] && ViashError Bad arguments for option \'--library_chemistry\': \'$VIASH_PAR_LIBRARY_CHEMISTRY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_LIBRARY_CHEMISTRY="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --library_chemistry. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --library_chemistry=*)
            [ -n "$VIASH_PAR_LIBRARY_CHEMISTRY" ] && ViashError Bad arguments for option \'--library_chemistry=*\': \'$VIASH_PAR_LIBRARY_CHEMISTRY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_LIBRARY_CHEMISTRY=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --sample_ids)
            if [ -z "$VIASH_PAR_SAMPLE_IDS" ]; then
              VIASH_PAR_SAMPLE_IDS="$2"
            else
              VIASH_PAR_SAMPLE_IDS="$VIASH_PAR_SAMPLE_IDS;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --sample_ids. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --sample_ids=*)
            if [ -z "$VIASH_PAR_SAMPLE_IDS" ]; then
              VIASH_PAR_SAMPLE_IDS=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_SAMPLE_IDS="$VIASH_PAR_SAMPLE_IDS;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --cell_multiplex_sample_id)
            if [ -z "$VIASH_PAR_SAMPLE_IDS" ]; then
              VIASH_PAR_SAMPLE_IDS="$2"
            else
              VIASH_PAR_SAMPLE_IDS="$VIASH_PAR_SAMPLE_IDS;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --cell_multiplex_sample_id. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --sample_description)
            if [ -z "$VIASH_PAR_SAMPLE_DESCRIPTION" ]; then
              VIASH_PAR_SAMPLE_DESCRIPTION="$2"
            else
              VIASH_PAR_SAMPLE_DESCRIPTION="$VIASH_PAR_SAMPLE_DESCRIPTION;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --sample_description. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --sample_description=*)
            if [ -z "$VIASH_PAR_SAMPLE_DESCRIPTION" ]; then
              VIASH_PAR_SAMPLE_DESCRIPTION=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_SAMPLE_DESCRIPTION="$VIASH_PAR_SAMPLE_DESCRIPTION;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --cell_multiplex_description)
            if [ -z "$VIASH_PAR_SAMPLE_DESCRIPTION" ]; then
              VIASH_PAR_SAMPLE_DESCRIPTION="$2"
            else
              VIASH_PAR_SAMPLE_DESCRIPTION="$VIASH_PAR_SAMPLE_DESCRIPTION;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --cell_multiplex_description. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --sample_expect_cells)
            if [ -z "$VIASH_PAR_SAMPLE_EXPECT_CELLS" ]; then
              VIASH_PAR_SAMPLE_EXPECT_CELLS="$2"
            else
              VIASH_PAR_SAMPLE_EXPECT_CELLS="$VIASH_PAR_SAMPLE_EXPECT_CELLS;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --sample_expect_cells. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --sample_expect_cells=*)
            if [ -z "$VIASH_PAR_SAMPLE_EXPECT_CELLS" ]; then
              VIASH_PAR_SAMPLE_EXPECT_CELLS=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_SAMPLE_EXPECT_CELLS="$VIASH_PAR_SAMPLE_EXPECT_CELLS;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --sample_force_cells)
            if [ -z "$VIASH_PAR_SAMPLE_FORCE_CELLS" ]; then
              VIASH_PAR_SAMPLE_FORCE_CELLS="$2"
            else
              VIASH_PAR_SAMPLE_FORCE_CELLS="$VIASH_PAR_SAMPLE_FORCE_CELLS;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --sample_force_cells. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --sample_force_cells=*)
            if [ -z "$VIASH_PAR_SAMPLE_FORCE_CELLS" ]; then
              VIASH_PAR_SAMPLE_FORCE_CELLS=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_SAMPLE_FORCE_CELLS="$VIASH_PAR_SAMPLE_FORCE_CELLS;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --feature_reference)
            [ -n "$VIASH_PAR_FEATURE_REFERENCE" ] && ViashError Bad arguments for option \'--feature_reference\': \'$VIASH_PAR_FEATURE_REFERENCE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FEATURE_REFERENCE="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --feature_reference. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --feature_reference=*)
            [ -n "$VIASH_PAR_FEATURE_REFERENCE" ] && ViashError Bad arguments for option \'--feature_reference=*\': \'$VIASH_PAR_FEATURE_REFERENCE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FEATURE_REFERENCE=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --feature_r1_length)
            [ -n "$VIASH_PAR_FEATURE_R1_LENGTH" ] && ViashError Bad arguments for option \'--feature_r1_length\': \'$VIASH_PAR_FEATURE_R1_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FEATURE_R1_LENGTH="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --feature_r1_length. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --feature_r1_length=*)
            [ -n "$VIASH_PAR_FEATURE_R1_LENGTH" ] && ViashError Bad arguments for option \'--feature_r1_length=*\': \'$VIASH_PAR_FEATURE_R1_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FEATURE_R1_LENGTH=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --feature_r2_length)
            [ -n "$VIASH_PAR_FEATURE_R2_LENGTH" ] && ViashError Bad arguments for option \'--feature_r2_length\': \'$VIASH_PAR_FEATURE_R2_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FEATURE_R2_LENGTH="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --feature_r2_length. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --feature_r2_length=*)
            [ -n "$VIASH_PAR_FEATURE_R2_LENGTH" ] && ViashError Bad arguments for option \'--feature_r2_length=*\': \'$VIASH_PAR_FEATURE_R2_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FEATURE_R2_LENGTH=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --min_crispr_umi)
            [ -n "$VIASH_PAR_MIN_CRISPR_UMI" ] && ViashError Bad arguments for option \'--min_crispr_umi\': \'$VIASH_PAR_MIN_CRISPR_UMI\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_MIN_CRISPR_UMI="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --min_crispr_umi. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --min_crispr_umi=*)
            [ -n "$VIASH_PAR_MIN_CRISPR_UMI" ] && ViashError Bad arguments for option \'--min_crispr_umi=*\': \'$VIASH_PAR_MIN_CRISPR_UMI\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_MIN_CRISPR_UMI=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --gex_reference)
            [ -n "$VIASH_PAR_GEX_REFERENCE" ] && ViashError Bad arguments for option \'--gex_reference\': \'$VIASH_PAR_GEX_REFERENCE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_REFERENCE="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --gex_reference. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --gex_reference=*)
            [ -n "$VIASH_PAR_GEX_REFERENCE" ] && ViashError Bad arguments for option \'--gex_reference=*\': \'$VIASH_PAR_GEX_REFERENCE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_REFERENCE=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --gex_secondary_analysis)
            [ -n "$VIASH_PAR_GEX_SECONDARY_ANALYSIS" ] && ViashError Bad arguments for option \'--gex_secondary_analysis\': \'$VIASH_PAR_GEX_SECONDARY_ANALYSIS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_SECONDARY_ANALYSIS="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --gex_secondary_analysis. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --gex_secondary_analysis=*)
            [ -n "$VIASH_PAR_GEX_SECONDARY_ANALYSIS" ] && ViashError Bad arguments for option \'--gex_secondary_analysis=*\': \'$VIASH_PAR_GEX_SECONDARY_ANALYSIS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_SECONDARY_ANALYSIS=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --gex_generate_bam)
            [ -n "$VIASH_PAR_GEX_GENERATE_BAM" ] && ViashError Bad arguments for option \'--gex_generate_bam\': \'$VIASH_PAR_GEX_GENERATE_BAM\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_GENERATE_BAM="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --gex_generate_bam. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --gex_generate_bam=*)
            [ -n "$VIASH_PAR_GEX_GENERATE_BAM" ] && ViashError Bad arguments for option \'--gex_generate_bam=*\': \'$VIASH_PAR_GEX_GENERATE_BAM\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_GENERATE_BAM=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --tenx_cloud_token_path)
            [ -n "$VIASH_PAR_TENX_CLOUD_TOKEN_PATH" ] && ViashError Bad arguments for option \'--tenx_cloud_token_path\': \'$VIASH_PAR_TENX_CLOUD_TOKEN_PATH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_TENX_CLOUD_TOKEN_PATH="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --tenx_cloud_token_path. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --tenx_cloud_token_path=*)
            [ -n "$VIASH_PAR_TENX_CLOUD_TOKEN_PATH" ] && ViashError Bad arguments for option \'--tenx_cloud_token_path=*\': \'$VIASH_PAR_TENX_CLOUD_TOKEN_PATH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_TENX_CLOUD_TOKEN_PATH=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --cell_annotation_model)
            [ -n "$VIASH_PAR_CELL_ANNOTATION_MODEL" ] && ViashError Bad arguments for option \'--cell_annotation_model\': \'$VIASH_PAR_CELL_ANNOTATION_MODEL\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_CELL_ANNOTATION_MODEL="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --cell_annotation_model. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --cell_annotation_model=*)
            [ -n "$VIASH_PAR_CELL_ANNOTATION_MODEL" ] && ViashError Bad arguments for option \'--cell_annotation_model=*\': \'$VIASH_PAR_CELL_ANNOTATION_MODEL\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_CELL_ANNOTATION_MODEL=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --gex_expect_cells)
            [ -n "$VIASH_PAR_GEX_EXPECT_CELLS" ] && ViashError Bad arguments for option \'--gex_expect_cells\': \'$VIASH_PAR_GEX_EXPECT_CELLS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_EXPECT_CELLS="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --gex_expect_cells. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --gex_expect_cells=*)
            [ -n "$VIASH_PAR_GEX_EXPECT_CELLS" ] && ViashError Bad arguments for option \'--gex_expect_cells=*\': \'$VIASH_PAR_GEX_EXPECT_CELLS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_EXPECT_CELLS=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --gex_force_cells)
            [ -n "$VIASH_PAR_GEX_FORCE_CELLS" ] && ViashError Bad arguments for option \'--gex_force_cells\': \'$VIASH_PAR_GEX_FORCE_CELLS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_FORCE_CELLS="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --gex_force_cells. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --gex_force_cells=*)
            [ -n "$VIASH_PAR_GEX_FORCE_CELLS" ] && ViashError Bad arguments for option \'--gex_force_cells=*\': \'$VIASH_PAR_GEX_FORCE_CELLS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_FORCE_CELLS=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --gex_include_introns)
            [ -n "$VIASH_PAR_GEX_INCLUDE_INTRONS" ] && ViashError Bad arguments for option \'--gex_include_introns\': \'$VIASH_PAR_GEX_INCLUDE_INTRONS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_INCLUDE_INTRONS="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --gex_include_introns. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --gex_include_introns=*)
            [ -n "$VIASH_PAR_GEX_INCLUDE_INTRONS" ] && ViashError Bad arguments for option \'--gex_include_introns=*\': \'$VIASH_PAR_GEX_INCLUDE_INTRONS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_INCLUDE_INTRONS=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --gex_r1_length)
            [ -n "$VIASH_PAR_GEX_R1_LENGTH" ] && ViashError Bad arguments for option \'--gex_r1_length\': \'$VIASH_PAR_GEX_R1_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_R1_LENGTH="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --gex_r1_length. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --gex_r1_length=*)
            [ -n "$VIASH_PAR_GEX_R1_LENGTH" ] && ViashError Bad arguments for option \'--gex_r1_length=*\': \'$VIASH_PAR_GEX_R1_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_R1_LENGTH=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --gex_r2_length)
            [ -n "$VIASH_PAR_GEX_R2_LENGTH" ] && ViashError Bad arguments for option \'--gex_r2_length\': \'$VIASH_PAR_GEX_R2_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_R2_LENGTH="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --gex_r2_length. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --gex_r2_length=*)
            [ -n "$VIASH_PAR_GEX_R2_LENGTH" ] && ViashError Bad arguments for option \'--gex_r2_length=*\': \'$VIASH_PAR_GEX_R2_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_R2_LENGTH=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --gex_chemistry)
            [ -n "$VIASH_PAR_GEX_CHEMISTRY" ] && ViashError Bad arguments for option \'--gex_chemistry\': \'$VIASH_PAR_GEX_CHEMISTRY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_CHEMISTRY="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --gex_chemistry. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --gex_chemistry=*)
            [ -n "$VIASH_PAR_GEX_CHEMISTRY" ] && ViashError Bad arguments for option \'--gex_chemistry=*\': \'$VIASH_PAR_GEX_CHEMISTRY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_GEX_CHEMISTRY=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --vdj_reference)
            [ -n "$VIASH_PAR_VDJ_REFERENCE" ] && ViashError Bad arguments for option \'--vdj_reference\': \'$VIASH_PAR_VDJ_REFERENCE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VDJ_REFERENCE="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --vdj_reference. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --vdj_reference=*)
            [ -n "$VIASH_PAR_VDJ_REFERENCE" ] && ViashError Bad arguments for option \'--vdj_reference=*\': \'$VIASH_PAR_VDJ_REFERENCE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VDJ_REFERENCE=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --vdj_inner_enrichment_primers)
            [ -n "$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS" ] && ViashError Bad arguments for option \'--vdj_inner_enrichment_primers\': \'$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --vdj_inner_enrichment_primers. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --vdj_inner_enrichment_primers=*)
            [ -n "$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS" ] && ViashError Bad arguments for option \'--vdj_inner_enrichment_primers=*\': \'$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --vdj_r1_length)
            [ -n "$VIASH_PAR_VDJ_R1_LENGTH" ] && ViashError Bad arguments for option \'--vdj_r1_length\': \'$VIASH_PAR_VDJ_R1_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VDJ_R1_LENGTH="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --vdj_r1_length. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --vdj_r1_length=*)
            [ -n "$VIASH_PAR_VDJ_R1_LENGTH" ] && ViashError Bad arguments for option \'--vdj_r1_length=*\': \'$VIASH_PAR_VDJ_R1_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VDJ_R1_LENGTH=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --vdj_r2_length)
            [ -n "$VIASH_PAR_VDJ_R2_LENGTH" ] && ViashError Bad arguments for option \'--vdj_r2_length\': \'$VIASH_PAR_VDJ_R2_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VDJ_R2_LENGTH="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --vdj_r2_length. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --vdj_r2_length=*)
            [ -n "$VIASH_PAR_VDJ_R2_LENGTH" ] && ViashError Bad arguments for option \'--vdj_r2_length=*\': \'$VIASH_PAR_VDJ_R2_LENGTH\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VDJ_R2_LENGTH=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --vdj_denovo)
            [ -n "$VIASH_PAR_VDJ_DENOVO" ] && ViashError Bad arguments for option \'--vdj_denovo\': \'$VIASH_PAR_VDJ_DENOVO\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VDJ_DENOVO="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --vdj_denovo. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --vdj_denovo=*)
            [ -n "$VIASH_PAR_VDJ_DENOVO" ] && ViashError Bad arguments for option \'--vdj_denovo=*\': \'$VIASH_PAR_VDJ_DENOVO\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_VDJ_DENOVO=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --cell_multiplex_oligo_ids)
            if [ -z "$VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS" ]; then
              VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS="$2"
            else
              VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS="$VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --cell_multiplex_oligo_ids. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --cell_multiplex_oligo_ids=*)
            if [ -z "$VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS" ]; then
              VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS="$VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --cmo_ids)
            if [ -z "$VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS" ]; then
              VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS="$2"
            else
              VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS="$VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --cmo_ids. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --min_assignment_confidence)
            [ -n "$VIASH_PAR_MIN_ASSIGNMENT_CONFIDENCE" ] && ViashError Bad arguments for option \'--min_assignment_confidence\': \'$VIASH_PAR_MIN_ASSIGNMENT_CONFIDENCE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_MIN_ASSIGNMENT_CONFIDENCE="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --min_assignment_confidence. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --min_assignment_confidence=*)
            [ -n "$VIASH_PAR_MIN_ASSIGNMENT_CONFIDENCE" ] && ViashError Bad arguments for option \'--min_assignment_confidence=*\': \'$VIASH_PAR_MIN_ASSIGNMENT_CONFIDENCE\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_MIN_ASSIGNMENT_CONFIDENCE=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --cmo_set)
            [ -n "$VIASH_PAR_CMO_SET" ] && ViashError Bad arguments for option \'--cmo_set\': \'$VIASH_PAR_CMO_SET\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_CMO_SET="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --cmo_set. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --cmo_set=*)
            [ -n "$VIASH_PAR_CMO_SET" ] && ViashError Bad arguments for option \'--cmo_set=*\': \'$VIASH_PAR_CMO_SET\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_CMO_SET=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --barcode_sample_assignment)
            [ -n "$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT" ] && ViashError Bad arguments for option \'--barcode_sample_assignment\': \'$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --barcode_sample_assignment. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --barcode_sample_assignment=*)
            [ -n "$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT" ] && ViashError Bad arguments for option \'--barcode_sample_assignment=*\': \'$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --hashtag_ids)
            if [ -z "$VIASH_PAR_HASHTAG_IDS" ]; then
              VIASH_PAR_HASHTAG_IDS="$2"
            else
              VIASH_PAR_HASHTAG_IDS="$VIASH_PAR_HASHTAG_IDS;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --hashtag_ids. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --hashtag_ids=*)
            if [ -z "$VIASH_PAR_HASHTAG_IDS" ]; then
              VIASH_PAR_HASHTAG_IDS=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_HASHTAG_IDS="$VIASH_PAR_HASHTAG_IDS;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --ocm_barcode_ids)
            if [ -z "$VIASH_PAR_OCM_BARCODE_IDS" ]; then
              VIASH_PAR_OCM_BARCODE_IDS="$2"
            else
              VIASH_PAR_OCM_BARCODE_IDS="$VIASH_PAR_OCM_BARCODE_IDS;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --ocm_barcode_ids. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --ocm_barcode_ids=*)
            if [ -z "$VIASH_PAR_OCM_BARCODE_IDS" ]; then
              VIASH_PAR_OCM_BARCODE_IDS=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_OCM_BARCODE_IDS="$VIASH_PAR_OCM_BARCODE_IDS;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --probe_set)
            [ -n "$VIASH_PAR_PROBE_SET" ] && ViashError Bad arguments for option \'--probe_set\': \'$VIASH_PAR_PROBE_SET\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_PROBE_SET="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --probe_set. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --probe_set=*)
            [ -n "$VIASH_PAR_PROBE_SET" ] && ViashError Bad arguments for option \'--probe_set=*\': \'$VIASH_PAR_PROBE_SET\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_PROBE_SET=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --filter_probes)
            [ -n "$VIASH_PAR_FILTER_PROBES" ] && ViashError Bad arguments for option \'--filter_probes\': \'$VIASH_PAR_FILTER_PROBES\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FILTER_PROBES="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --filter_probes. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --filter_probes=*)
            [ -n "$VIASH_PAR_FILTER_PROBES" ] && ViashError Bad arguments for option \'--filter_probes=*\': \'$VIASH_PAR_FILTER_PROBES\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_FILTER_PROBES=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --probe_barcode_ids)
            if [ -z "$VIASH_PAR_PROBE_BARCODE_IDS" ]; then
              VIASH_PAR_PROBE_BARCODE_IDS="$2"
            else
              VIASH_PAR_PROBE_BARCODE_IDS="$VIASH_PAR_PROBE_BARCODE_IDS;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --probe_barcode_ids. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --probe_barcode_ids=*)
            if [ -z "$VIASH_PAR_PROBE_BARCODE_IDS" ]; then
              VIASH_PAR_PROBE_BARCODE_IDS=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_PROBE_BARCODE_IDS="$VIASH_PAR_PROBE_BARCODE_IDS;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --emptydrops_minimum_umis)
            [ -n "$VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS" ] && ViashError Bad arguments for option \'--emptydrops_minimum_umis\': \'$VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --emptydrops_minimum_umis. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --emptydrops_minimum_umis=*)
            [ -n "$VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS" ] && ViashError Bad arguments for option \'--emptydrops_minimum_umis=*\': \'$VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS=$(ViashRemoveFlags "$1")
            shift 1
            ;;
        --control_id)
            if [ -z "$VIASH_PAR_CONTROL_ID" ]; then
              VIASH_PAR_CONTROL_ID="$2"
            else
              VIASH_PAR_CONTROL_ID="$VIASH_PAR_CONTROL_ID;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --control_id. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --control_id=*)
            if [ -z "$VIASH_PAR_CONTROL_ID" ]; then
              VIASH_PAR_CONTROL_ID=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_CONTROL_ID="$VIASH_PAR_CONTROL_ID;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --mhc_allele)
            if [ -z "$VIASH_PAR_MHC_ALLELE" ]; then
              VIASH_PAR_MHC_ALLELE="$2"
            else
              VIASH_PAR_MHC_ALLELE="$VIASH_PAR_MHC_ALLELE;""$2"
            fi
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --mhc_allele. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --mhc_allele=*)
            if [ -z "$VIASH_PAR_MHC_ALLELE" ]; then
              VIASH_PAR_MHC_ALLELE=$(ViashRemoveFlags "$1")
            else
              VIASH_PAR_MHC_ALLELE="$VIASH_PAR_MHC_ALLELE;"$(ViashRemoveFlags "$1")
            fi
            shift 1
            ;;
        --check_library_compatibility)
            [ -n "$VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY" ] && ViashError Bad arguments for option \'--check_library_compatibility\': \'$VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY="$2"
            [ $# -lt 2 ] && ViashError Not enough arguments passed to --check_library_compatibility. Use "--help" to get more information on the parameters. && exit 1
            shift 2
            ;;
        --check_library_compatibility=*)
            [ -n "$VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY" ] && ViashError Bad arguments for option \'--check_library_compatibility=*\': \'$VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY=$(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
            ;;
        --dryrun)
            [ -n "$VIASH_PAR_DRYRUN" ] && ViashError Bad arguments for option \'--dryrun\': \'$VIASH_PAR_DRYRUN\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1
            VIASH_PAR_DRYRUN=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/mapping/cellranger_multi:v4.0.4'
  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_GEX_REFERENCE+x} ]; then
  ViashError '--gex_reference' 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_GEX_SECONDARY_ANALYSIS+x} ]; then
  VIASH_PAR_GEX_SECONDARY_ANALYSIS="false"
fi
if [ -z ${VIASH_PAR_GEX_GENERATE_BAM+x} ]; then
  VIASH_PAR_GEX_GENERATE_BAM="false"
fi
if [ -z ${VIASH_PAR_GEX_INCLUDE_INTRONS+x} ]; then
  VIASH_PAR_GEX_INCLUDE_INTRONS="true"
fi
if [ -z ${VIASH_PAR_GEX_CHEMISTRY+x} ]; then
  VIASH_PAR_GEX_CHEMISTRY="auto"
fi
if [ -z ${VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY+x} ]; then
  VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY="true"
fi
if [ -z ${VIASH_PAR_DRYRUN+x} ]; then
  VIASH_PAR_DRYRUN="false"
fi

# check whether required files exist
if [ ! -z "$VIASH_PAR_INPUT" ]; then
  IFS=';'
  set -f
  for file in $VIASH_PAR_INPUT; do
    unset IFS
    if [ ! -e "$file" ]; then
      ViashError "Input file '$file' does not exist."
      exit 1
    fi
  done
  set +f
fi
if [ ! -z "$VIASH_PAR_GEX_INPUT" ]; then
  IFS=';'
  set -f
  for file in $VIASH_PAR_GEX_INPUT; do
    unset IFS
    if [ ! -e "$file" ]; then
      ViashError "Input file '$file' does not exist."
      exit 1
    fi
  done
  set +f
fi
if [ ! -z "$VIASH_PAR_ABC_INPUT" ]; then
  IFS=';'
  set -f
  for file in $VIASH_PAR_ABC_INPUT; do
    unset IFS
    if [ ! -e "$file" ]; then
      ViashError "Input file '$file' does not exist."
      exit 1
    fi
  done
  set +f
fi
if [ ! -z "$VIASH_PAR_CGC_INPUT" ]; then
  IFS=';'
  set -f
  for file in $VIASH_PAR_CGC_INPUT; do
    unset IFS
    if [ ! -e "$file" ]; then
      ViashError "Input file '$file' does not exist."
      exit 1
    fi
  done
  set +f
fi
if [ ! -z "$VIASH_PAR_MUX_INPUT" ]; then
  IFS=';'
  set -f
  for file in $VIASH_PAR_MUX_INPUT; do
    unset IFS
    if [ ! -e "$file" ]; then
      ViashError "Input file '$file' does not exist."
      exit 1
    fi
  done
  set +f
fi
if [ ! -z "$VIASH_PAR_VDJ_INPUT" ]; then
  IFS=';'
  set -f
  for file in $VIASH_PAR_VDJ_INPUT; do
    unset IFS
    if [ ! -e "$file" ]; then
      ViashError "Input file '$file' does not exist."
      exit 1
    fi
  done
  set +f
fi
if [ ! -z "$VIASH_PAR_VDJ_T_INPUT" ]; then
  IFS=';'
  set -f
  for file in $VIASH_PAR_VDJ_T_INPUT; do
    unset IFS
    if [ ! -e "$file" ]; then
      ViashError "Input file '$file' does not exist."
      exit 1
    fi
  done
  set +f
fi
if [ ! -z "$VIASH_PAR_VDJ_T_GD_INPUT" ]; then
  IFS=';'
  set -f
  for file in $VIASH_PAR_VDJ_T_GD_INPUT; do
    unset IFS
    if [ ! -e "$file" ]; then
      ViashError "Input file '$file' does not exist."
      exit 1
    fi
  done
  set +f
fi
if [ ! -z "$VIASH_PAR_VDJ_B_INPUT" ]; then
  IFS=';'
  set -f
  for file in $VIASH_PAR_VDJ_B_INPUT; do
    unset IFS
    if [ ! -e "$file" ]; then
      ViashError "Input file '$file' does not exist."
      exit 1
    fi
  done
  set +f
fi
if [ ! -z "$VIASH_PAR_AGC_INPUT" ]; then
  IFS=';'
  set -f
  for file in $VIASH_PAR_AGC_INPUT; do
    unset IFS
    if [ ! -e "$file" ]; then
      ViashError "Input file '$file' does not exist."
      exit 1
    fi
  done
  set +f
fi
if [ ! -z "$VIASH_PAR_FEATURE_REFERENCE" ] && [ ! -e "$VIASH_PAR_FEATURE_REFERENCE" ]; then
  ViashError "Input file '$VIASH_PAR_FEATURE_REFERENCE' does not exist."
  exit 1
fi
if [ ! -z "$VIASH_PAR_GEX_REFERENCE" ] && [ ! -e "$VIASH_PAR_GEX_REFERENCE" ]; then
  ViashError "Input file '$VIASH_PAR_GEX_REFERENCE' does not exist."
  exit 1
fi
if [ ! -z "$VIASH_PAR_TENX_CLOUD_TOKEN_PATH" ] && [ ! -e "$VIASH_PAR_TENX_CLOUD_TOKEN_PATH" ]; then
  ViashError "Input file '$VIASH_PAR_TENX_CLOUD_TOKEN_PATH' does not exist."
  exit 1
fi
if [ ! -z "$VIASH_PAR_VDJ_REFERENCE" ] && [ ! -e "$VIASH_PAR_VDJ_REFERENCE" ]; then
  ViashError "Input file '$VIASH_PAR_VDJ_REFERENCE' does not exist."
  exit 1
fi
if [ ! -z "$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS" ] && [ ! -e "$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS" ]; then
  ViashError "Input file '$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS' does not exist."
  exit 1
fi
if [ ! -z "$VIASH_PAR_CMO_SET" ] && [ ! -e "$VIASH_PAR_CMO_SET" ]; then
  ViashError "Input file '$VIASH_PAR_CMO_SET' does not exist."
  exit 1
fi
if [ ! -z "$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT" ] && [ ! -e "$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT" ]; then
  ViashError "Input file '$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT' does not exist."
  exit 1
fi
if [ ! -z "$VIASH_PAR_PROBE_SET" ] && [ ! -e "$VIASH_PAR_PROBE_SET" ]; then
  ViashError "Input file '$VIASH_PAR_PROBE_SET' does not exist."
  exit 1
fi

# check whether parameters values are of the right type
if [ -n "$VIASH_PAR_SAMPLE_EXPECT_CELLS" ]; then
  IFS=';'
  set -f
  for val in $VIASH_PAR_SAMPLE_EXPECT_CELLS; do
    if ! [[ "${val}" =~ ^[-+]?[0-9]+$ ]]; then
      ViashError '--sample_expect_cells' 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_SAMPLE_FORCE_CELLS" ]; then
  IFS=';'
  set -f
  for val in $VIASH_PAR_SAMPLE_FORCE_CELLS; do
    if ! [[ "${val}" =~ ^[-+]?[0-9]+$ ]]; then
      ViashError '--sample_force_cells' 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_FEATURE_R1_LENGTH" ]]; then
  if ! [[ "$VIASH_PAR_FEATURE_R1_LENGTH" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--feature_r1_length' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_FEATURE_R2_LENGTH" ]]; then
  if ! [[ "$VIASH_PAR_FEATURE_R2_LENGTH" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--feature_r2_length' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_MIN_CRISPR_UMI" ]]; then
  if ! [[ "$VIASH_PAR_MIN_CRISPR_UMI" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--min_crispr_umi' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
  if [[ $VIASH_PAR_MIN_CRISPR_UMI -lt 1 ]]; then
    ViashError '--min_crispr_umi' has be more than or equal to 1. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_GEX_SECONDARY_ANALYSIS" ]]; then
  if ! [[ "$VIASH_PAR_GEX_SECONDARY_ANALYSIS" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--gex_secondary_analysis' has to be a boolean. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_GEX_GENERATE_BAM" ]]; then
  if ! [[ "$VIASH_PAR_GEX_GENERATE_BAM" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--gex_generate_bam' has to be a boolean. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_GEX_EXPECT_CELLS" ]]; then
  if ! [[ "$VIASH_PAR_GEX_EXPECT_CELLS" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--gex_expect_cells' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_GEX_FORCE_CELLS" ]]; then
  if ! [[ "$VIASH_PAR_GEX_FORCE_CELLS" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--gex_force_cells' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_GEX_INCLUDE_INTRONS" ]]; then
  if ! [[ "$VIASH_PAR_GEX_INCLUDE_INTRONS" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--gex_include_introns' has to be a boolean. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_GEX_R1_LENGTH" ]]; then
  if ! [[ "$VIASH_PAR_GEX_R1_LENGTH" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--gex_r1_length' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_GEX_R2_LENGTH" ]]; then
  if ! [[ "$VIASH_PAR_GEX_R2_LENGTH" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--gex_r2_length' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_VDJ_R1_LENGTH" ]]; then
  if ! [[ "$VIASH_PAR_VDJ_R1_LENGTH" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--vdj_r1_length' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_VDJ_R2_LENGTH" ]]; then
  if ! [[ "$VIASH_PAR_VDJ_R2_LENGTH" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--vdj_r2_length' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_VDJ_DENOVO" ]]; then
  if ! [[ "$VIASH_PAR_VDJ_DENOVO" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--vdj_denovo' has to be a boolean. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_MIN_ASSIGNMENT_CONFIDENCE" ]]; then
  if ! [[ "$VIASH_PAR_MIN_ASSIGNMENT_CONFIDENCE" =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$ ]]; then
    ViashError '--min_assignment_confidence' has to be a double. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_FILTER_PROBES" ]]; then
  if ! [[ "$VIASH_PAR_FILTER_PROBES" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--filter_probes' has to be a boolean. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS" ]]; then
  if ! [[ "$VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS" =~ ^[-+]?[0-9]+$ ]]; then
    ViashError '--emptydrops_minimum_umis' has to be an integer. Use "--help" to get more information on the parameters.
    exit 1
  fi
  if [[ $VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS -lt 1 ]]; then
    ViashError '--emptydrops_minimum_umis' has be more than or equal to 1. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY" ]]; then
  if ! [[ "$VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--check_library_compatibility' has to be a boolean. Use "--help" to get more information on the parameters.
    exit 1
  fi
fi
if [[ -n "$VIASH_PAR_DRYRUN" ]]; then
  if ! [[ "$VIASH_PAR_DRYRUN" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then
    ViashError '--dryrun' 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_LIBRARY_TYPE" ]; then
  VIASH_PAR_LIBRARY_TYPE_CHOICES=("Gene Expression;VDJ;VDJ-T;VDJ-B;VDJ-T-GD;Antibody Capture;CRISPR Guide Capture;Multiplexing Capture;Antigen Capture;Custom")
  IFS=';'
  set -f
  for val in $VIASH_PAR_LIBRARY_TYPE; do
    if ! [[ ";${VIASH_PAR_LIBRARY_TYPE_CHOICES[*]};" =~ ";${val};" ]]; then
      ViashError '--library_type' specified value of \'${val}\' is not in the list of allowed values. Use "--help" to get more information on the parameters.
      exit 1
    fi
  done
  set +f
  unset IFS
fi

if [ ! -z "$VIASH_PAR_CELL_ANNOTATION_MODEL" ]; then
  VIASH_PAR_CELL_ANNOTATION_MODEL_CHOICES=("auto;human_pca_v1_beta;mouse_pca_v1_beta")
  IFS=';'
  set -f
  if ! [[ ";${VIASH_PAR_CELL_ANNOTATION_MODEL_CHOICES[*]};" =~ ";$VIASH_PAR_CELL_ANNOTATION_MODEL;" ]]; then
    ViashError '--cell_annotation_model' specified value of \'$VIASH_PAR_CELL_ANNOTATION_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_GEX_CHEMISTRY" ]; then
  VIASH_PAR_GEX_CHEMISTRY_CHOICES=("auto;threeprime;fiveprime;SC3Pv1;SC3Pv2;SC3Pv3;SC3Pv3-polyA;SC3Pv4;SC3Pv4-polyA;SC3Pv3LT;SC3Pv3HT;SC3Pv3HT-polyA;SC5P-PE;SC5P-PE-v3;SC5P-R2;SC-FB;SC5P-R2-v3;SCP5-PE-v3;SC5PHT;MFRP;MFRP-R1;MFRP-RNA;MFRP-Ab;SFRP;MFRP-Ab-R2pos50;MFRP-RNA-R1;MFRP-Ab-R1;ARC-v1")
  IFS=';'
  set -f
  if ! [[ ";${VIASH_PAR_GEX_CHEMISTRY_CHOICES[*]};" =~ ";$VIASH_PAR_GEX_CHEMISTRY;" ]]; then
    ViashError '--gex_chemistry' specified value of \'$VIASH_PAR_GEX_CHEMISTRY\' 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_TEST_INPUT=()
  IFS=';'
  for var in $VIASH_PAR_INPUT; do
    unset IFS
    VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$var")" )
    var=$(ViashDockerAutodetectMount "$var")
    VIASH_TEST_INPUT+=( "$var" )
  done
  VIASH_PAR_INPUT=$(IFS=';' ; echo "${VIASH_TEST_INPUT[*]}")
fi
if [ ! -z "$VIASH_PAR_GEX_INPUT" ]; then
  VIASH_TEST_GEX_INPUT=()
  IFS=';'
  for var in $VIASH_PAR_GEX_INPUT; do
    unset IFS
    VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$var")" )
    var=$(ViashDockerAutodetectMount "$var")
    VIASH_TEST_GEX_INPUT+=( "$var" )
  done
  VIASH_PAR_GEX_INPUT=$(IFS=';' ; echo "${VIASH_TEST_GEX_INPUT[*]}")
fi
if [ ! -z "$VIASH_PAR_ABC_INPUT" ]; then
  VIASH_TEST_ABC_INPUT=()
  IFS=';'
  for var in $VIASH_PAR_ABC_INPUT; do
    unset IFS
    VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$var")" )
    var=$(ViashDockerAutodetectMount "$var")
    VIASH_TEST_ABC_INPUT+=( "$var" )
  done
  VIASH_PAR_ABC_INPUT=$(IFS=';' ; echo "${VIASH_TEST_ABC_INPUT[*]}")
fi
if [ ! -z "$VIASH_PAR_CGC_INPUT" ]; then
  VIASH_TEST_CGC_INPUT=()
  IFS=';'
  for var in $VIASH_PAR_CGC_INPUT; do
    unset IFS
    VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$var")" )
    var=$(ViashDockerAutodetectMount "$var")
    VIASH_TEST_CGC_INPUT+=( "$var" )
  done
  VIASH_PAR_CGC_INPUT=$(IFS=';' ; echo "${VIASH_TEST_CGC_INPUT[*]}")
fi
if [ ! -z "$VIASH_PAR_MUX_INPUT" ]; then
  VIASH_TEST_MUX_INPUT=()
  IFS=';'
  for var in $VIASH_PAR_MUX_INPUT; do
    unset IFS
    VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$var")" )
    var=$(ViashDockerAutodetectMount "$var")
    VIASH_TEST_MUX_INPUT+=( "$var" )
  done
  VIASH_PAR_MUX_INPUT=$(IFS=';' ; echo "${VIASH_TEST_MUX_INPUT[*]}")
fi
if [ ! -z "$VIASH_PAR_VDJ_INPUT" ]; then
  VIASH_TEST_VDJ_INPUT=()
  IFS=';'
  for var in $VIASH_PAR_VDJ_INPUT; do
    unset IFS
    VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$var")" )
    var=$(ViashDockerAutodetectMount "$var")
    VIASH_TEST_VDJ_INPUT+=( "$var" )
  done
  VIASH_PAR_VDJ_INPUT=$(IFS=';' ; echo "${VIASH_TEST_VDJ_INPUT[*]}")
fi
if [ ! -z "$VIASH_PAR_VDJ_T_INPUT" ]; then
  VIASH_TEST_VDJ_T_INPUT=()
  IFS=';'
  for var in $VIASH_PAR_VDJ_T_INPUT; do
    unset IFS
    VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$var")" )
    var=$(ViashDockerAutodetectMount "$var")
    VIASH_TEST_VDJ_T_INPUT+=( "$var" )
  done
  VIASH_PAR_VDJ_T_INPUT=$(IFS=';' ; echo "${VIASH_TEST_VDJ_T_INPUT[*]}")
fi
if [ ! -z "$VIASH_PAR_VDJ_T_GD_INPUT" ]; then
  VIASH_TEST_VDJ_T_GD_INPUT=()
  IFS=';'
  for var in $VIASH_PAR_VDJ_T_GD_INPUT; do
    unset IFS
    VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$var")" )
    var=$(ViashDockerAutodetectMount "$var")
    VIASH_TEST_VDJ_T_GD_INPUT+=( "$var" )
  done
  VIASH_PAR_VDJ_T_GD_INPUT=$(IFS=';' ; echo "${VIASH_TEST_VDJ_T_GD_INPUT[*]}")
fi
if [ ! -z "$VIASH_PAR_VDJ_B_INPUT" ]; then
  VIASH_TEST_VDJ_B_INPUT=()
  IFS=';'
  for var in $VIASH_PAR_VDJ_B_INPUT; do
    unset IFS
    VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$var")" )
    var=$(ViashDockerAutodetectMount "$var")
    VIASH_TEST_VDJ_B_INPUT+=( "$var" )
  done
  VIASH_PAR_VDJ_B_INPUT=$(IFS=';' ; echo "${VIASH_TEST_VDJ_B_INPUT[*]}")
fi
if [ ! -z "$VIASH_PAR_AGC_INPUT" ]; then
  VIASH_TEST_AGC_INPUT=()
  IFS=';'
  for var in $VIASH_PAR_AGC_INPUT; do
    unset IFS
    VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$var")" )
    var=$(ViashDockerAutodetectMount "$var")
    VIASH_TEST_AGC_INPUT+=( "$var" )
  done
  VIASH_PAR_AGC_INPUT=$(IFS=';' ; echo "${VIASH_TEST_AGC_INPUT[*]}")
fi
if [ ! -z "$VIASH_PAR_FEATURE_REFERENCE" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_FEATURE_REFERENCE")" )
  VIASH_PAR_FEATURE_REFERENCE=$(ViashDockerAutodetectMount "$VIASH_PAR_FEATURE_REFERENCE")
fi
if [ ! -z "$VIASH_PAR_GEX_REFERENCE" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_GEX_REFERENCE")" )
  VIASH_PAR_GEX_REFERENCE=$(ViashDockerAutodetectMount "$VIASH_PAR_GEX_REFERENCE")
fi
if [ ! -z "$VIASH_PAR_TENX_CLOUD_TOKEN_PATH" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_TENX_CLOUD_TOKEN_PATH")" )
  VIASH_PAR_TENX_CLOUD_TOKEN_PATH=$(ViashDockerAutodetectMount "$VIASH_PAR_TENX_CLOUD_TOKEN_PATH")
fi
if [ ! -z "$VIASH_PAR_VDJ_REFERENCE" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_VDJ_REFERENCE")" )
  VIASH_PAR_VDJ_REFERENCE=$(ViashDockerAutodetectMount "$VIASH_PAR_VDJ_REFERENCE")
fi
if [ ! -z "$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS")" )
  VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS=$(ViashDockerAutodetectMount "$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS")
fi
if [ ! -z "$VIASH_PAR_CMO_SET" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_CMO_SET")" )
  VIASH_PAR_CMO_SET=$(ViashDockerAutodetectMount "$VIASH_PAR_CMO_SET")
fi
if [ ! -z "$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT")" )
  VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT=$(ViashDockerAutodetectMount "$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT")
fi
if [ ! -z "$VIASH_PAR_PROBE_SET" ]; then
  VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_PROBE_SET")" )
  VIASH_PAR_PROBE_SET=$(ViashDockerAutodetectMount "$VIASH_PAR_PROBE_SET")
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-cellranger_multi-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'
from __future__ import annotations

import sys
import re
import subprocess
from multiprocessing import cpu_count
import tempfile
import pandas as pd
import yaml
from typing import Optional, Any, Union
import tarfile
from pathlib import Path
import shutil
from itertools import chain

CELL_RANGER_EXEC = shutil.which("cellranger")

## 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\'}'.split(';')"; else echo None; fi ),
  'gex_input': $( if [ ! -z ${VIASH_PAR_GEX_INPUT+x} ]; then echo "r'${VIASH_PAR_GEX_INPUT//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'abc_input': $( if [ ! -z ${VIASH_PAR_ABC_INPUT+x} ]; then echo "r'${VIASH_PAR_ABC_INPUT//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'cgc_input': $( if [ ! -z ${VIASH_PAR_CGC_INPUT+x} ]; then echo "r'${VIASH_PAR_CGC_INPUT//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'mux_input': $( if [ ! -z ${VIASH_PAR_MUX_INPUT+x} ]; then echo "r'${VIASH_PAR_MUX_INPUT//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'vdj_input': $( if [ ! -z ${VIASH_PAR_VDJ_INPUT+x} ]; then echo "r'${VIASH_PAR_VDJ_INPUT//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'vdj_t_input': $( if [ ! -z ${VIASH_PAR_VDJ_T_INPUT+x} ]; then echo "r'${VIASH_PAR_VDJ_T_INPUT//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'vdj_t_gd_input': $( if [ ! -z ${VIASH_PAR_VDJ_T_GD_INPUT+x} ]; then echo "r'${VIASH_PAR_VDJ_T_GD_INPUT//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'vdj_b_input': $( if [ ! -z ${VIASH_PAR_VDJ_B_INPUT+x} ]; then echo "r'${VIASH_PAR_VDJ_B_INPUT//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'agc_input': $( if [ ! -z ${VIASH_PAR_AGC_INPUT+x} ]; then echo "r'${VIASH_PAR_AGC_INPUT//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'library_id': $( if [ ! -z ${VIASH_PAR_LIBRARY_ID+x} ]; then echo "r'${VIASH_PAR_LIBRARY_ID//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'library_type': $( if [ ! -z ${VIASH_PAR_LIBRARY_TYPE+x} ]; then echo "r'${VIASH_PAR_LIBRARY_TYPE//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'library_subsample': $( if [ ! -z ${VIASH_PAR_LIBRARY_SUBSAMPLE+x} ]; then echo "r'${VIASH_PAR_LIBRARY_SUBSAMPLE//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'library_lanes': $( if [ ! -z ${VIASH_PAR_LIBRARY_LANES+x} ]; then echo "r'${VIASH_PAR_LIBRARY_LANES//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'library_chemistry': $( if [ ! -z ${VIASH_PAR_LIBRARY_CHEMISTRY+x} ]; then echo "r'${VIASH_PAR_LIBRARY_CHEMISTRY//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'sample_ids': $( if [ ! -z ${VIASH_PAR_SAMPLE_IDS+x} ]; then echo "r'${VIASH_PAR_SAMPLE_IDS//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'sample_description': $( if [ ! -z ${VIASH_PAR_SAMPLE_DESCRIPTION+x} ]; then echo "r'${VIASH_PAR_SAMPLE_DESCRIPTION//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'sample_expect_cells': $( if [ ! -z ${VIASH_PAR_SAMPLE_EXPECT_CELLS+x} ]; then echo "list(map(int, r'${VIASH_PAR_SAMPLE_EXPECT_CELLS//\'/\'\"\'\"r\'}'.split(';')))"; else echo None; fi ),
  'sample_force_cells': $( if [ ! -z ${VIASH_PAR_SAMPLE_FORCE_CELLS+x} ]; then echo "list(map(int, r'${VIASH_PAR_SAMPLE_FORCE_CELLS//\'/\'\"\'\"r\'}'.split(';')))"; else echo None; fi ),
  'feature_reference': $( if [ ! -z ${VIASH_PAR_FEATURE_REFERENCE+x} ]; then echo "r'${VIASH_PAR_FEATURE_REFERENCE//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'feature_r1_length': $( if [ ! -z ${VIASH_PAR_FEATURE_R1_LENGTH+x} ]; then echo "int(r'${VIASH_PAR_FEATURE_R1_LENGTH//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'feature_r2_length': $( if [ ! -z ${VIASH_PAR_FEATURE_R2_LENGTH+x} ]; then echo "int(r'${VIASH_PAR_FEATURE_R2_LENGTH//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'min_crispr_umi': $( if [ ! -z ${VIASH_PAR_MIN_CRISPR_UMI+x} ]; then echo "int(r'${VIASH_PAR_MIN_CRISPR_UMI//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'gex_reference': $( if [ ! -z ${VIASH_PAR_GEX_REFERENCE+x} ]; then echo "r'${VIASH_PAR_GEX_REFERENCE//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'gex_secondary_analysis': $( if [ ! -z ${VIASH_PAR_GEX_SECONDARY_ANALYSIS+x} ]; then echo "r'${VIASH_PAR_GEX_SECONDARY_ANALYSIS//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi ),
  'gex_generate_bam': $( if [ ! -z ${VIASH_PAR_GEX_GENERATE_BAM+x} ]; then echo "r'${VIASH_PAR_GEX_GENERATE_BAM//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi ),
  'tenx_cloud_token_path': $( if [ ! -z ${VIASH_PAR_TENX_CLOUD_TOKEN_PATH+x} ]; then echo "r'${VIASH_PAR_TENX_CLOUD_TOKEN_PATH//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'cell_annotation_model': $( if [ ! -z ${VIASH_PAR_CELL_ANNOTATION_MODEL+x} ]; then echo "r'${VIASH_PAR_CELL_ANNOTATION_MODEL//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'gex_expect_cells': $( if [ ! -z ${VIASH_PAR_GEX_EXPECT_CELLS+x} ]; then echo "int(r'${VIASH_PAR_GEX_EXPECT_CELLS//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'gex_force_cells': $( if [ ! -z ${VIASH_PAR_GEX_FORCE_CELLS+x} ]; then echo "int(r'${VIASH_PAR_GEX_FORCE_CELLS//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'gex_include_introns': $( if [ ! -z ${VIASH_PAR_GEX_INCLUDE_INTRONS+x} ]; then echo "r'${VIASH_PAR_GEX_INCLUDE_INTRONS//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi ),
  'gex_r1_length': $( if [ ! -z ${VIASH_PAR_GEX_R1_LENGTH+x} ]; then echo "int(r'${VIASH_PAR_GEX_R1_LENGTH//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'gex_r2_length': $( if [ ! -z ${VIASH_PAR_GEX_R2_LENGTH+x} ]; then echo "int(r'${VIASH_PAR_GEX_R2_LENGTH//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'gex_chemistry': $( if [ ! -z ${VIASH_PAR_GEX_CHEMISTRY+x} ]; then echo "r'${VIASH_PAR_GEX_CHEMISTRY//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'vdj_reference': $( if [ ! -z ${VIASH_PAR_VDJ_REFERENCE+x} ]; then echo "r'${VIASH_PAR_VDJ_REFERENCE//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'vdj_inner_enrichment_primers': $( if [ ! -z ${VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS+x} ]; then echo "r'${VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'vdj_r1_length': $( if [ ! -z ${VIASH_PAR_VDJ_R1_LENGTH+x} ]; then echo "int(r'${VIASH_PAR_VDJ_R1_LENGTH//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'vdj_r2_length': $( if [ ! -z ${VIASH_PAR_VDJ_R2_LENGTH+x} ]; then echo "int(r'${VIASH_PAR_VDJ_R2_LENGTH//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'vdj_denovo': $( if [ ! -z ${VIASH_PAR_VDJ_DENOVO+x} ]; then echo "r'${VIASH_PAR_VDJ_DENOVO//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi ),
  'cell_multiplex_oligo_ids': $( if [ ! -z ${VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS+x} ]; then echo "r'${VIASH_PAR_CELL_MULTIPLEX_OLIGO_IDS//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'min_assignment_confidence': $( if [ ! -z ${VIASH_PAR_MIN_ASSIGNMENT_CONFIDENCE+x} ]; then echo "float(r'${VIASH_PAR_MIN_ASSIGNMENT_CONFIDENCE//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'cmo_set': $( if [ ! -z ${VIASH_PAR_CMO_SET+x} ]; then echo "r'${VIASH_PAR_CMO_SET//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'barcode_sample_assignment': $( if [ ! -z ${VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT+x} ]; then echo "r'${VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'hashtag_ids': $( if [ ! -z ${VIASH_PAR_HASHTAG_IDS+x} ]; then echo "r'${VIASH_PAR_HASHTAG_IDS//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'ocm_barcode_ids': $( if [ ! -z ${VIASH_PAR_OCM_BARCODE_IDS+x} ]; then echo "r'${VIASH_PAR_OCM_BARCODE_IDS//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'probe_set': $( if [ ! -z ${VIASH_PAR_PROBE_SET+x} ]; then echo "r'${VIASH_PAR_PROBE_SET//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'filter_probes': $( if [ ! -z ${VIASH_PAR_FILTER_PROBES+x} ]; then echo "r'${VIASH_PAR_FILTER_PROBES//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi ),
  'probe_barcode_ids': $( if [ ! -z ${VIASH_PAR_PROBE_BARCODE_IDS+x} ]; then echo "r'${VIASH_PAR_PROBE_BARCODE_IDS//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'emptydrops_minimum_umis': $( if [ ! -z ${VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS+x} ]; then echo "int(r'${VIASH_PAR_EMPTYDROPS_MINIMUM_UMIS//\'/\'\"\'\"r\'}')"; else echo None; fi ),
  'control_id': $( if [ ! -z ${VIASH_PAR_CONTROL_ID+x} ]; then echo "r'${VIASH_PAR_CONTROL_ID//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'mhc_allele': $( if [ ! -z ${VIASH_PAR_MHC_ALLELE+x} ]; then echo "r'${VIASH_PAR_MHC_ALLELE//\'/\'\"\'\"r\'}'.split(';')"; else echo None; fi ),
  'check_library_compatibility': $( if [ ! -z ${VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY+x} ]; then echo "r'${VIASH_PAR_CHECK_LIBRARY_COMPATIBILITY//\'/\'\"\'\"r\'}'.lower() == 'true'"; else echo None; fi ),
  'output': $( if [ ! -z ${VIASH_PAR_OUTPUT+x} ]; then echo "r'${VIASH_PAR_OUTPUT//\'/\'\"\'\"r\'}'"; else echo None; fi ),
  'dryrun': $( if [ ! -z ${VIASH_PAR_DRYRUN+x} ]; then echo "r'${VIASH_PAR_DRYRUN//\'/\'\"\'\"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()

if not CELL_RANGER_EXEC:
    raise RuntimeError(
        "Could not find Cell Ranger executable. Please make sure it is installed and available in your PATH."
    )

# Tested with cellranger 7.0:
# - omitting the lane number is allowed (e.g. \`_L001\`)
# - lane number should be omitted across all files if omitted in one
# - replacing \`.fastq.\` for \`.fq.\` is NOT allowed
# - omitting \`.gz\` is allowed

fastq_regex = r"^([A-Za-z0-9\\-_\\.]+)_S(\\d+)_(L(\\d+)_)?[RI](\\d+)_(\\d+)\\.fastq(\\.gz)?\$"
# assert re.match(fastq_regex, "5k_human_GEX_1_subset_S1_L001_R1_001.fastq.gz") is not None
# assert re.match(fastq_regex, "5k_human_GEX_1_subset_S1_R1_001.fastq") is not None
# assert re.match(fastq_regex, "5k_human_GEX_1_subset_S1_R1_001.fastq.gz.txt") is None

# Invert some parameters. Keep the original ones in the config for compatibility
inverted_params = {
    "gex_no_secondary_analysis": "gex_secondary_analysis",
}
for inverted_param, param in inverted_params.items():
    par[inverted_param] = not par[param] if par[param] is not None else None
    del par[param]

GEX_CONFIG_KEYS = {
    "gex_reference": "reference",
    "gex_expect_cells": "expect-cells",
    "gex_force_cells": "force-cells",
    "gex_chemistry": "chemistry",
    "gex_no_secondary_analysis": "no-secondary",
    "gex_generate_bam": "create-bam",
    "gex_include_introns": "include-introns",
    "min_assignment_confidence": "min-assignment-confidence",
    "check_library_compatibility": "check-library-compatibility",
    "barcode_sample_assignment": "barcode-sample-assignment",
    "cmo_set": "cmo-set",
    "probe_set": "probe-set",
    "filter_probes": "filter-probes",
    "gex_r1_length": "r1-length",
    "gex_r2_length": "r2-length",
    "tenx_cloud_token_path": "tenx-cloud-token-path",
    "cell_annotation_model": "cell-annotation-model",
    "emptydrops_minimum_umis": "emptydrops_minimum_umis",
}

FEATURE_CONFIG_KEYS = {
    "feature_reference": "reference",
    "feature_r1_length": "r1-length",
    "feature_r2_length": "r2-length",
    "min_crispr_umi": "min-crispr-umi",
}

VDJ_CONFIG_KEYS = {
    "vdj_reference": "reference",
    "vdj_inner_enrichment_primers": "inner-enrichment-primers",
    "vdj_r1_length": "r1-length",
    "vdj_r2_length": "r2-length",
    "vdj_denovo": "denovo",
}


ANTIGEN_SPECIFICITY_CONFIG_KEYS = {
    "control_id": "control_id",
    "mhc_allele": "mhc_allele",
}


REFERENCE_SECTIONS = {
    "gene-expression": (GEX_CONFIG_KEYS, "index"),
    "feature": (FEATURE_CONFIG_KEYS, "index"),
    "vdj": (VDJ_CONFIG_KEYS, "index"),
    "antigen-specificity": (ANTIGEN_SPECIFICITY_CONFIG_KEYS, "columns"),
}

LIBRARY_CONFIG_KEYS = {
    "library_id": "fastq_id",
    "library_type": "feature_types",
    "library_subsample": "subsample_rate",
    "library_lanes": "lanes",
    "library_chemistry": "chemistry",
}


SAMPLE_PARAMS_CONFIG_KEYS = {
    "sample_ids": "sample_id",
    "cell_multiplex_oligo_ids": "cmo_ids",
    "sample_description": "description",
    "probe_barcode_ids": "probe_barcode_ids",
    "sample_expect_cells": "expect_cells",
    "sample_force_cells": "force_cells",
    "hashtag_ids": "hashtag_ids",
    "ocm_barcode_ids": "ocm_barcode_ids",
}


# These are derived from the dictionaries above
REFERENCES = tuple(
    reference_param
    for reference_param, cellranger_param in chain(
        GEX_CONFIG_KEYS.items(), FEATURE_CONFIG_KEYS.items(), VDJ_CONFIG_KEYS.items()
    )
    if cellranger_param == "reference"
)
LIBRARY_PARAMS = tuple(LIBRARY_CONFIG_KEYS.keys())
SAMPLE_PARAMS = tuple(SAMPLE_PARAMS_CONFIG_KEYS.keys())
HELPER_INPUT = {
    "gex_input": "Gene Expression",
    "abc_input": "Antibody Capture",
    "cgc_input": "CRISPR Guide Capture",
    "mux_input": "Multiplexing Capture",
    "vdj_input": "VDJ",
    "vdj_t_input": "VDJ-T",
    "vdj_t_gd_input": "VDJ-T-GD",
    "vdj_b_input": "VDJ-B",
    "agc_input": "Antigen Capture",
}


def infer_library_id_from_path(input_path: str) -> str:
    match = re.match(fastq_regex, input_path)
    assert match is not None, (
        f"File name of '{input_path}' should match regex {fastq_regex}."
    )
    return match.group(1)


def transform_helper_inputs(par: dict[str, Any]) -> dict[str, Any]:
    helper_input = {"input": [], "library_id": [], "library_type": []}
    for input_type, library_type in HELPER_INPUT.items():
        if par[input_type]:
            par[input_type] = resolve_input_directories_to_fastq_paths(par[input_type])

            library_ids = [
                infer_library_id_from_path(path.name) for path in par[input_type]
            ]

            library_id_dict = {}
            for fastq, library_id in zip(par[input_type], library_ids):
                library_id_dict.setdefault(library_id, []).append(fastq)

            for library_id, input in library_id_dict.items():
                helper_input["input"] += input
                helper_input["library_id"].append(library_id)
                helper_input["library_type"].append(library_type)

    assert len(helper_input["library_id"]) == len(set(helper_input["library_id"])), (
        "File names passed to feature type-specific inputs must be unique"
    )

    return helper_input


def lengths_gt1(dic: dict[str, Optional[list[Any]]]) -> dict[str, int]:
    return {
        key: len(li)
        for key, li in dic.items()
        if li is not None and isinstance(li, (list, tuple, set))
    }


def strip_margin(text: str) -> str:
    return re.sub("(\\n?)[ \\t]*\\|", "\\\\1", text)


def subset_dict(
    dictionary: dict[str, str], keys: Union[dict[str, str], list[str]]
) -> dict[str, str]:
    if isinstance(keys, (list, tuple)):
        keys = {key: key for key in keys}
    return {
        dest_key: dictionary[orig_key]
        for orig_key, dest_key in keys.items()
        if dictionary[orig_key] is not None
    }


def check_subset_dict_equal_length(
    group_name: str, dictionary: dict[str, list[str]]
) -> None:
    lens = lengths_gt1(dictionary)
    assert len(set(lens.values())) <= 1, (
        f"The number of values passed to {group_name} "
        f"arguments must be 0, 1 or all the same. Offenders: {lens}"
    )


def resolve_input_directories_to_fastq_paths(input_paths: list[str]) -> list[Path]:
    input_paths = [Path(fastq) for fastq in input_paths]
    if len(input_paths) == 1 and input_paths[0].is_dir():
        logger.info(
            "Detected a directory in input paths, "
            "traversing to see if we can detect any FASTQ files."
        )
        input_paths = [
            input_path
            for input_path in input_paths[0].rglob("*")
            if re.match(fastq_regex, input_path.name)
        ]

    # check input fastq files
    for input_path in input_paths:
        assert re.match(fastq_regex, input_path.name) is not None, (
            f"File name of --input '{input_path}' should match regex {fastq_regex}."
        )

    return input_paths


def make_paths_absolute(par: dict[str, Any], config: Path | str):
    with open(config, "r", encoding="utf-8") as open_viash_config:
        config = yaml.safe_load(open_viash_config)

    arguments = {
        arg["name"].removeprefix("-").removeprefix("-"): arg
        for group in config["argument_groups"]
        for arg in group["arguments"]
    }
    for arg_name, arg in arguments.items():
        if not par.get(arg_name) or arg["type"] != "file":
            continue
        par_value, is_multiple = par[arg_name], arg["multiple"]
        assert is_multiple in (True, False)

        def make_path_absolute(file: str | Path) -> Path:
            logger.info("Making path %s absolute", file)
            return Path(file).resolve()

        new_arg = (
            [make_path_absolute(file) for file in par_value]
            if is_multiple
            else make_path_absolute(par_value)
        )
        par[arg_name] = new_arg
    return par


def handle_integers_not_set(par: dict[str, Any], viash_config: Path | str) -> str:
    """
    Allow to use \`-1\` to define a 'not set' value for arguments of \`type: integer\` with \`multiple: true\`.
    """
    with open(viash_config, "r", encoding="utf-8") as open_viash_config:
        config = yaml.safe_load(open_viash_config)

    arguments = {
        arg["name"].removeprefix("-").removeprefix("-"): arg
        for group in config["argument_groups"]
        for arg in group["arguments"]
    }
    for arg_name, arg in arguments.items():
        if not par.get(arg_name) or arg["type"] != "integer":
            continue
        par_value, is_multiple = par[arg_name], arg["multiple"]
        assert is_multiple in (True, False)

        if not is_multiple:
            continue

        def replace_notset_values(integer_value: int) -> int | None:
            return None if integer_value == -1 else integer_value

        # Use an extension array to handle "None" values, otherwise int + NA
        # values would be converted to a "float" dtype
        new_arg = pd.array(
            [replace_notset_values(value) for value in par_value], dtype="Int64"
        )
        par[arg_name] = new_arg
    return par


def process_params(par: dict[str, Any], viash_config: Path | str) -> str:
    if par["input"]:
        assert len(par["library_type"]) > 0, (
            "--library_type must be defined when passing input to --input"
        )
        assert len(par["library_id"]) > 0, (
            "--library_id must be defined when passing input to --input"
        )

        # if par["input"] is a directory, look for fastq files
        par["input"] = resolve_input_directories_to_fastq_paths(par["input"])

    # add helper input
    helper_input = transform_helper_inputs(par)
    for key in ["input", "library_id", "library_type"]:
        par[key] = (par[key] if par[key] else []) + helper_input[key]

        assert len(par[key]) > 0, (
            f"Either --{key} or feature type-specific input (e.g. --gex_input, --abc_input, ...) must be defined"
        )

    # check lengths of libraries metadata
    library_dict = subset_dict(par, LIBRARY_PARAMS)
    check_subset_dict_equal_length("Library", library_dict)

    samples_dict = subset_dict(par, SAMPLE_PARAMS)
    check_subset_dict_equal_length("Samples", samples_dict)

    # Allow using -1 to indicate unset integers for arguments
    # that accept multiple integers.
    par = handle_integers_not_set(par, viash_config)

    # use absolute paths
    return make_paths_absolute(par, viash_config)


def generate_csv_category(name: str, args: dict[str, str], orient: str) -> list[str]:
    assert orient in ("index", "columns")
    if not args:
        return []
    title = [f"[{name}]"]
    # Which index to include in csv section is based on orientation
    to_csv_args = {"index": (orient == "index"), "header": (orient == "columns")}
    values = [pd.DataFrame.from_dict(args, orient=orient).to_csv(**to_csv_args).strip()]
    return title + values + [""]


def generate_config(par: dict[str, Any], fastq_dir: str) -> str:
    content_list = []
    par["fastqs"] = fastq_dir
    libraries = dict(LIBRARY_CONFIG_KEYS, **{"fastqs": "fastqs"})
    # TODO: use the union (|) operator when python is updated to 3.9
    all_sections = REFERENCE_SECTIONS | {
        "libraries": (libraries, "columns"),
        "samples": (SAMPLE_PARAMS_CONFIG_KEYS, "columns"),
    }
    for section_name, (section_params, orientation) in all_sections.items():
        reference_pars = subset_dict(par, section_params)
        content_list += generate_csv_category(
            section_name, reference_pars, orient=orientation
        )

    return "\\n".join(content_list)


def untar(tar_file, output_directory):
    logger.info("Looking at %s to check if it needs decompressing", tar_file)
    if tar_file and Path(tar_file).is_file() and tarfile.is_tarfile(tar_file):
        extaction_dir_name = Path(
            tar_file.stem
        ).stem  # Remove two extensions (if they exist)
        unpacked_directory = output_directory / extaction_dir_name
        logger.info("Extracting %s to %s", tar_file, unpacked_directory)

        with tarfile.open(tar_file, "r") as open_tar:
            members = open_tar.getmembers()
            root_dirs = [
                member
                for member in members
                if member.isdir() and member.name != "." and "/" not in member.name
            ]
            # if there is only one root_dir (and there are files in that directory)
            # strip that directory name from the destination folder
            if len(root_dirs) == 1:
                for mem in members:
                    mem.path = Path(*Path(mem.path).parts[1:])
            members_to_move = [mem for mem in members if mem.path != Path(".")]
            open_tar.extractall(unpacked_directory, members=members_to_move)
        return unpacked_directory
    return tar_file


def main(par: dict[str, Any], meta: dict[str, Any]):
    logger.info("Processing params")
    par = process_params(par, meta["config"])
    logger.info(par)

    with tempfile.TemporaryDirectory(
        prefix="cellranger_multi-", dir=meta["temp_dir"]
    ) as temp_dir:
        logger.info("Using temporary directory %s", temp_dir)
        temp_dir_path = Path(temp_dir)
        for reference_par_name in REFERENCES:
            par[reference_par_name] = untar(par[reference_par_name], temp_dir_path)

        logger.info("Creating symbolic links to temporary directory")
        # Creating symlinks of fastq files to tempdir
        input_symlinks_dir = temp_dir_path / "input_symlinks"
        input_symlinks_dir.mkdir()
        for fastq in par["input"]:
            destination = input_symlinks_dir / fastq.name
            destination.symlink_to(fastq)

        logger.info("Creating config file")
        config_content = generate_config(par, input_symlinks_dir)
        logger.info("Using config: \\n\\t%s", config_content.replace("\\n", "\\n\\t"))
        par["output"].mkdir(parents=True, exist_ok=True)
        config_file = par["output"] / "config.csv"
        with open(config_file, "w") as f:
            f.write(config_content)

        logger.info("Creating Cell Ranger argument list")
        temp_id = "run"
        cmd = [CELL_RANGER_EXEC, "multi", "--disable-ui", "--id", temp_id]

        command_line_parameters = {
            "--localcores": int(meta["cpus"]) if meta["cpus"] else cpu_count() - 1,
            "--csv": config_file,
        }
        if meta["memory_gb"]:
            command_line_parameters["--localmem"] = (
                int(meta["memory_gb"]) - 2
                if meta["memory_gb"] > 2
                else meta["memory_gb"]
            )
        cmd += [
            f"{param}={param_value}"
            for param, param_value in command_line_parameters.items()
        ]

        logger.info("> " + " ".join(cmd))

        if par["dryrun"]:
            logger.info("Not executing command. Dry run enabled.")
            return

        logger.info("Starting Cell Ranger")
        with (
            subprocess.Popen(
                cmd,
                text=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                bufsize=1,
                cwd=temp_dir,
            ) as process,
            (par["output"] / "cellranger_multi.log").open("w") as open_log,
        ):
            for line in process.stdout:
                print(line.strip(), flush=True)
                open_log.write(line)
        logger.info("Checking exit code.")
        # Popen objects do not have a check_exitcode method.
        if process.returncode != 0:
            raise RuntimeError("Cell Ranger returned a nonzero exitcode!")

        logger.info("Checking if expected output files are present.")
        # Sanity check the output: check for required files
        tmp_output_dir = temp_dir_path / temp_id / "outs"
        expected_files = {
            Path("per_sample_outs"): Path.is_dir,
            Path("config.csv"): Path.is_file,
            Path("filtered_feature_bc_matrix"): Path.is_dir,
            Path("filtered_feature_bc_matrix.h5"): Path.is_file,
            Path("raw_feature_bc_matrix"): Path.is_dir,
            Path("raw_feature_bc_matrix.h5"): Path.is_file,
        }
        dir_contents = map(str, tmp_output_dir.iterdir())
        logger.info("Directory contents: %s", ", ".join(dir_contents))
        for file_path, type_func in expected_files.items():
            output_path = tmp_output_dir / file_path
            if not type_func(output_path):
                raise ValueError(f"Could not find expected '{output_path}'")
        logger.info("Copying output files to %s", par["output"])
        for output_path in tmp_output_dir.rglob("*"):
            if output_path.name != "config.csv":  # Already created
                shutil.move(str(output_path), par["output"])


if __name__ == "__main__":
    logger.info("Component '%s' started.", meta["name"])
    main(par, meta)
    logger.info("Finished!")
VIASHMAIN
python -B "\$tempscript" &
wait "\$!"

VIASHEOF


if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then
  # strip viash automount from file paths
  
  if [ ! -z "$VIASH_PAR_INPUT" ]; then
    unset VIASH_TEST_INPUT
    IFS=';'
    for var in $VIASH_PAR_INPUT; do
      unset IFS
      if [ -z "$VIASH_TEST_INPUT" ]; then
      VIASH_TEST_INPUT="$(ViashDockerStripAutomount "$var")"
    else
      VIASH_TEST_INPUT="$VIASH_TEST_INPUT;""$(ViashDockerStripAutomount "$var")"
    fi
    done
    VIASH_PAR_INPUT="$VIASH_TEST_INPUT"
  fi
  if [ ! -z "$VIASH_PAR_GEX_INPUT" ]; then
    unset VIASH_TEST_GEX_INPUT
    IFS=';'
    for var in $VIASH_PAR_GEX_INPUT; do
      unset IFS
      if [ -z "$VIASH_TEST_GEX_INPUT" ]; then
      VIASH_TEST_GEX_INPUT="$(ViashDockerStripAutomount "$var")"
    else
      VIASH_TEST_GEX_INPUT="$VIASH_TEST_GEX_INPUT;""$(ViashDockerStripAutomount "$var")"
    fi
    done
    VIASH_PAR_GEX_INPUT="$VIASH_TEST_GEX_INPUT"
  fi
  if [ ! -z "$VIASH_PAR_ABC_INPUT" ]; then
    unset VIASH_TEST_ABC_INPUT
    IFS=';'
    for var in $VIASH_PAR_ABC_INPUT; do
      unset IFS
      if [ -z "$VIASH_TEST_ABC_INPUT" ]; then
      VIASH_TEST_ABC_INPUT="$(ViashDockerStripAutomount "$var")"
    else
      VIASH_TEST_ABC_INPUT="$VIASH_TEST_ABC_INPUT;""$(ViashDockerStripAutomount "$var")"
    fi
    done
    VIASH_PAR_ABC_INPUT="$VIASH_TEST_ABC_INPUT"
  fi
  if [ ! -z "$VIASH_PAR_CGC_INPUT" ]; then
    unset VIASH_TEST_CGC_INPUT
    IFS=';'
    for var in $VIASH_PAR_CGC_INPUT; do
      unset IFS
      if [ -z "$VIASH_TEST_CGC_INPUT" ]; then
      VIASH_TEST_CGC_INPUT="$(ViashDockerStripAutomount "$var")"
    else
      VIASH_TEST_CGC_INPUT="$VIASH_TEST_CGC_INPUT;""$(ViashDockerStripAutomount "$var")"
    fi
    done
    VIASH_PAR_CGC_INPUT="$VIASH_TEST_CGC_INPUT"
  fi
  if [ ! -z "$VIASH_PAR_MUX_INPUT" ]; then
    unset VIASH_TEST_MUX_INPUT
    IFS=';'
    for var in $VIASH_PAR_MUX_INPUT; do
      unset IFS
      if [ -z "$VIASH_TEST_MUX_INPUT" ]; then
      VIASH_TEST_MUX_INPUT="$(ViashDockerStripAutomount "$var")"
    else
      VIASH_TEST_MUX_INPUT="$VIASH_TEST_MUX_INPUT;""$(ViashDockerStripAutomount "$var")"
    fi
    done
    VIASH_PAR_MUX_INPUT="$VIASH_TEST_MUX_INPUT"
  fi
  if [ ! -z "$VIASH_PAR_VDJ_INPUT" ]; then
    unset VIASH_TEST_VDJ_INPUT
    IFS=';'
    for var in $VIASH_PAR_VDJ_INPUT; do
      unset IFS
      if [ -z "$VIASH_TEST_VDJ_INPUT" ]; then
      VIASH_TEST_VDJ_INPUT="$(ViashDockerStripAutomount "$var")"
    else
      VIASH_TEST_VDJ_INPUT="$VIASH_TEST_VDJ_INPUT;""$(ViashDockerStripAutomount "$var")"
    fi
    done
    VIASH_PAR_VDJ_INPUT="$VIASH_TEST_VDJ_INPUT"
  fi
  if [ ! -z "$VIASH_PAR_VDJ_T_INPUT" ]; then
    unset VIASH_TEST_VDJ_T_INPUT
    IFS=';'
    for var in $VIASH_PAR_VDJ_T_INPUT; do
      unset IFS
      if [ -z "$VIASH_TEST_VDJ_T_INPUT" ]; then
      VIASH_TEST_VDJ_T_INPUT="$(ViashDockerStripAutomount "$var")"
    else
      VIASH_TEST_VDJ_T_INPUT="$VIASH_TEST_VDJ_T_INPUT;""$(ViashDockerStripAutomount "$var")"
    fi
    done
    VIASH_PAR_VDJ_T_INPUT="$VIASH_TEST_VDJ_T_INPUT"
  fi
  if [ ! -z "$VIASH_PAR_VDJ_T_GD_INPUT" ]; then
    unset VIASH_TEST_VDJ_T_GD_INPUT
    IFS=';'
    for var in $VIASH_PAR_VDJ_T_GD_INPUT; do
      unset IFS
      if [ -z "$VIASH_TEST_VDJ_T_GD_INPUT" ]; then
      VIASH_TEST_VDJ_T_GD_INPUT="$(ViashDockerStripAutomount "$var")"
    else
      VIASH_TEST_VDJ_T_GD_INPUT="$VIASH_TEST_VDJ_T_GD_INPUT;""$(ViashDockerStripAutomount "$var")"
    fi
    done
    VIASH_PAR_VDJ_T_GD_INPUT="$VIASH_TEST_VDJ_T_GD_INPUT"
  fi
  if [ ! -z "$VIASH_PAR_VDJ_B_INPUT" ]; then
    unset VIASH_TEST_VDJ_B_INPUT
    IFS=';'
    for var in $VIASH_PAR_VDJ_B_INPUT; do
      unset IFS
      if [ -z "$VIASH_TEST_VDJ_B_INPUT" ]; then
      VIASH_TEST_VDJ_B_INPUT="$(ViashDockerStripAutomount "$var")"
    else
      VIASH_TEST_VDJ_B_INPUT="$VIASH_TEST_VDJ_B_INPUT;""$(ViashDockerStripAutomount "$var")"
    fi
    done
    VIASH_PAR_VDJ_B_INPUT="$VIASH_TEST_VDJ_B_INPUT"
  fi
  if [ ! -z "$VIASH_PAR_AGC_INPUT" ]; then
    unset VIASH_TEST_AGC_INPUT
    IFS=';'
    for var in $VIASH_PAR_AGC_INPUT; do
      unset IFS
      if [ -z "$VIASH_TEST_AGC_INPUT" ]; then
      VIASH_TEST_AGC_INPUT="$(ViashDockerStripAutomount "$var")"
    else
      VIASH_TEST_AGC_INPUT="$VIASH_TEST_AGC_INPUT;""$(ViashDockerStripAutomount "$var")"
    fi
    done
    VIASH_PAR_AGC_INPUT="$VIASH_TEST_AGC_INPUT"
  fi
  if [ ! -z "$VIASH_PAR_FEATURE_REFERENCE" ]; then
    VIASH_PAR_FEATURE_REFERENCE=$(ViashDockerStripAutomount "$VIASH_PAR_FEATURE_REFERENCE")
  fi
  if [ ! -z "$VIASH_PAR_GEX_REFERENCE" ]; then
    VIASH_PAR_GEX_REFERENCE=$(ViashDockerStripAutomount "$VIASH_PAR_GEX_REFERENCE")
  fi
  if [ ! -z "$VIASH_PAR_TENX_CLOUD_TOKEN_PATH" ]; then
    VIASH_PAR_TENX_CLOUD_TOKEN_PATH=$(ViashDockerStripAutomount "$VIASH_PAR_TENX_CLOUD_TOKEN_PATH")
  fi
  if [ ! -z "$VIASH_PAR_VDJ_REFERENCE" ]; then
    VIASH_PAR_VDJ_REFERENCE=$(ViashDockerStripAutomount "$VIASH_PAR_VDJ_REFERENCE")
  fi
  if [ ! -z "$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS" ]; then
    VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS=$(ViashDockerStripAutomount "$VIASH_PAR_VDJ_INNER_ENRICHMENT_PRIMERS")
  fi
  if [ ! -z "$VIASH_PAR_CMO_SET" ]; then
    VIASH_PAR_CMO_SET=$(ViashDockerStripAutomount "$VIASH_PAR_CMO_SET")
  fi
  if [ ! -z "$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT" ]; then
    VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT=$(ViashDockerStripAutomount "$VIASH_PAR_BARCODE_SAMPLE_ASSIGNMENT")
  fi
  if [ ! -z "$VIASH_PAR_PROBE_SET" ]; then
    VIASH_PAR_PROBE_SET=$(ViashDockerStripAutomount "$VIASH_PAR_PROBE_SET")
  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
