Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9b47b16
fix(runtime): migrate CHARLIE activation to mamba-safe flow
kopardev Jun 5, 2026
e0cc74a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 5, 2026
bf97ac9
fix(paths): replace gpfs CCBR base path with vf
kopardev Jun 5, 2026
8be54c5
fix(config): make host/additives/viruses placeholders envsubst-compat…
kopardev Jun 5, 2026
f85c985
fix(cli): default additives to blank when omitted
kopardev Jun 5, 2026
d079566
fix(slurm): remove invalid ccr partition on biowulf
kopardev Jun 5, 2026
dbf699a
fix(slurm): force biowulf partition to norm
kopardev Jun 5, 2026
56ef217
fix(slurm): change biowulf default partition from ccr,norm to norm
kopardev Jun 7, 2026
4b3bf7b
feat(workflow): add progress logging to create_index rule
kopardev Jun 8, 2026
609ccae
feat: use SIFCACHE env var for pre-downloaded SIF files
kopardev Jun 12, 2026
8f5bef1
feat: print run configuration summary before snakemake invocation
kopardev Jun 12, 2026
4a77d24
fix: call set_singularity_binds in unlock() so binds are not blank
kopardev Jun 12, 2026
5cd843c
fix: call set_singularity_binds in dryrun() and touch()
kopardev Jun 12, 2026
c6fd3fe
feat: smarter singularity bind path detection
kopardev Jun 12, 2026
a697468
docs(changelog): document SIFCACHE and singularity bind improvements
kopardev Jun 12, 2026
503600d
docs(changelog): highlight host-only circRNA mode as key new feature
kopardev Jun 12, 2026
6eb3b4e
chore(release): bump version to 0.13.0
kopardev Jun 12, 2026
d1c92a9
fix: avoid leading comma in SINGULARITY_BINDS when EXTRA_SINGULARITY_…
kopardev Jun 12, 2026
77d17ae
docs: update singcache, additives, viruses descriptions for v0.13.0
kopardev Jun 12, 2026
e88bf73
feat: enable host-only circRNA discovery mode end-to-end
kopardev Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .tests/lint_workdir/ref/dummy
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@

12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
## CHARLIE development version
## CHARLIE 0.13.0

- Migrate runtime activation to a mamba-safe flow to avoid shared-environment activation failures. (#149, @kopardev)
- **Host-only circRNA discovery is now supported.** Additives (e.g. ERCC) and viruses are now fully optional — omitting them runs the pipeline in host-only mode, a long-standing user request. Make host/additives/viruses config placeholders envsubst-compatible and default additives to blank when omitted. (#149, @kopardev)
- Replace hard-coded CCBR base paths under `/gpfs` with `/vf` for current filesystem layout compatibility. (#149, @kopardev)
- Update Biowulf partition handling by removing deprecated `ccr` usage and forcing/defaulting to `norm`. (#149, @kopardev)
- Align `onsuccess`/`onerror` completion hooks with CARLISLE behavior while preserving CHARLIE's shared hook implementation, including stricter shell setup and completion-log checks. (#153, @kopardev)
- Auto-detect `$SIFCACHE` (set by `module load ccbrpipeliner`) and use it as the singularity cache and `--singularity-prefix` so Snakemake finds pre-downloaded SIF files without pulling from Docker Hub. (#154, @kopardev)
- Print a configuration summary block (workdir, snakefile, config, singularity cache, binds, platform) to the terminal before each pipeline run. (#154, @kopardev)
- Fix `set_singularity_binds` not being called in `unlock()`, `dryrun()`, and `touch()`, which left `SINGULARITY_BINDS` empty. (#154, @kopardev)
- Smarter singularity bind path detection: walk up parents of `WORKDIR` and `PIPELINE_HOME` to find `/data/<name>` symlinks and include both the symlink and real path; filter Python-derived paths that are ancestors (too broad) or descendants (too specific) of the bash-derived explicit paths. (#154, @kopardev)

## CHARLIE 0.12.0

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,10 @@ Required Arguments:

Optional Arguments:

--singcache|-c : singularity cache directory. Default is `/data/${USER}/.singularity` if available, or falls back to `${WORKDIR}/.singularity`. Use this flag to specify a different singularity cache directory.
--singcache|-c : singularity cache directory. If `$SIFCACHE` is set in the environment (e.g. via `module load ccbrpipeliner`), it is used automatically as the cache and singularity image prefix. Otherwise defaults to `/data/${USER}/.singularity` if available, or falls back to `${WORKDIR}/.singularity`. Use this flag to override.
--host|-g : supply host at command line. hg38 or mm39. (--runmode=init only)
--additives|-a : supply comma-separated list of additives at command line. ERCC or BAC16Insert or both (--runmode=init only)
--viruses|-v : supply comma-separated list of viruses at command line (--runmode=init only)
--additives|-a : supply comma-separated list of additives at command line. ERCC or BAC16Insert or both (default: blank). Omit for host-only circRNA discovery. (--runmode=init only)
--viruses|-v : supply comma-separated list of viruses at command line. Omit for host-only circRNA discovery. (--runmode=init only)
--manifest|-s : absolute path to samples.tsv. This will be copied to output folder (--runmode=init only)
--changegrp|-z : change group to "Ziegelbauer_lab" before running anything. Biowulf-only. Useful for correctly setting permissions.
--help|-h : print this help
Expand All @@ -194,7 +194,7 @@ Example commands:
VersionInfo:
python : 3
snakemake : 7
pipeline_home : /gpfs/gsfs10/users/CCBR_Pipeliner/Pipelines/CHARLIE/.v0.11.1
pipeline_home : /vf/users/CCBR_Pipeliner/Pipelines/CHARLIE/.v0.11.1
git commit/tag : 613fb617f1ed426fb8900f98e599ca0497a67cc0 v0.11.0-49-g613fb61

##########################################################################################
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.12.0-dev
0.13.0
38 changes: 2 additions & 36 deletions bin/redirect
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# This is a wrapper for the pipeline script
# It:
# - loads require modules and conda environments
# - forwards arguments to the main pipeline script
# - parses the variables directly to the python script

SCRIPTDIRNAME=$(readlink -f $(dirname "$BASH_SOURCE"))
Expand All @@ -13,38 +13,4 @@ fi

TOOLDIR=$(dirname "$SCRIPTDIRNAME")

# find out if you are running on biowulf or frce
hpc_name=$(scontrol show config | grep ClusterName | sed "s/^.*= //")
# load conda
if [[ $hpc_name == biowulf ]]; then
. "/data/CCBR_Pipeliner/db/PipeDB/Conda/etc/profile.d/conda.sh"
conda activate py311
elif [[ $hpc_name == fnlcr ]]; then
. "/mnt/projects/CCBR-Pipelines/resources/miniconda3/etc/profile.d/conda.sh"
conda activate py311
else
echo "You are NOT running on BIOWULF or on FRCE"
echo "Please make sure that:"
echo " - py311 conda environment is activated"
echo " - singularity is in PATH"
echo " - snakemake is in PATH"
fi
# if not on biowulf or frce then
# use py311.environment.yml in resources folder to create the py311 conda environment
# and load py311

# load required modules
# if running somewhere other than biowulf or frce, then ensure that
# - singularity
# - snakemake
# are in PATH
if [[ $hpc_name == biowulf ]];then
module load singularity snakemake/7
elif [[ $hpc_name == fnlcr ]];then
# snakemake module on FRCE does not work as expected
# use the conda installed version of snakemake instead
module load singularity
export PATH="/mnt/projects/CCBR-Pipelines/bin:$PATH"
fi

${TOOLDIR}/charlie "$@" || true
${TOOLDIR}/charlie "$@"
117 changes: 104 additions & 13 deletions charlie
Original file line number Diff line number Diff line change
Expand Up @@ -52,30 +52,35 @@ GIT_COMMIT_TAG=$(get_git_commitid_tag $PIPELINE_HOME)

PYTHONVERSION="3"
SNAKEMAKEVERSION="7"
CONDA_ACTIVATE=''
ENV_ACTIVATE=''
PATH_PREPEND=''
MODULE_LOAD=''
PLATFORM=$(get_platform)
PARTITION='norm'
EXTRA_SINGULARITY_BINDS=""

export TEMP_DIR=""
export REFS_DIR=""
export CLUSTER_PROFILE="config/unknown"
if [ "$PLATFORM" == "biowulf" ]; then
CLUSTER_PROFILE="config/slurm-biowulf"
PARTITION="ccr,$PARTITION"
PARTITION="norm"
EXTRA_SINGULARITY_BINDS="/lscratch"
CONDA_ACTIVATE='. "/data/CCBR_Pipeliner/db/PipeDB/Conda/etc/profile.d/conda.sh" && conda activate py311'
MODULE_LOAD="module load python/$PYTHONVERSION snakemake/$SNAKEMAKEVERSION singularity; $CONDA_ACTIVATE"
MAMBA_ROOT_PREFIX="${MAMBA_ROOT_PREFIX:-/data/CCBR_Pipeliner/db/PipeDB/miniforge3}"
PY311_ENV_PATH="${PY311_ENV_PATH:-${MAMBA_ROOT_PREFIX%/}/envs/py3.11-8}"
ENV_ACTIVATE="if ! command -v mamba >/dev/null 2>&1; then echo \"ERROR: mamba not found in PATH. Load ccbrpipeliner module first.\"; exit 1; fi; if [ ! -x \"$PY311_ENV_PATH/bin/python\" ]; then echo \"ERROR: missing mamba environment at $PY311_ENV_PATH\"; exit 1; fi; export MAMBA_PREFIX=\"$PY311_ENV_PATH\"; export PATH=\"$PY311_ENV_PATH/bin:\$PATH\""
MODULE_LOAD="module load python/$PYTHONVERSION snakemake/$SNAKEMAKEVERSION singularity; $ENV_ACTIVATE"
TEMP_DIR='/lscratch/$SLURM_JOB_ID/'
REFS_DIR="/gpfs/gsfs10/users/CCBR_Pipeliner/db/PipeDB/charlie/fastas_gtfs/"
REFS_DIR="/vf/users/CCBR_Pipeliner/db/PipeDB/charlie/fastas_gtfs/"
elif [ "$PLATFORM" == "fnlcr" ]; then
CLUSTER_PROFILE="config/slurm-fnlcr"
EXTRA_SINGULARITY_BINDS="/scratch/local"
CONDA_ACTIVATE=". '/mnt/projects/CCBR-Pipelines/resources/miniconda3/etc/profile.d/conda.sh' && conda activate py311"
MAMBA_ROOT_PREFIX="${MAMBA_ROOT_PREFIX:-/mnt/projects/CCBR-Pipelines/resources/miniforge3}"
PY311_ENV_PATH="${PY311_ENV_PATH:-${MAMBA_ROOT_PREFIX%/}/envs/py3.11-8}"
ENV_ACTIVATE="if ! command -v mamba >/dev/null 2>&1; then echo \"ERROR: mamba not found in PATH. Load ccbrpipeliner module first.\"; exit 1; fi; if [ ! -x \"$PY311_ENV_PATH/bin/python\" ]; then echo \"ERROR: missing mamba environment at $PY311_ENV_PATH\"; exit 1; fi; export MAMBA_PREFIX=\"$PY311_ENV_PATH\"; export PATH=\"$PY311_ENV_PATH/bin:\$PATH\""
# make sure spooker is in the path
PATH_PREPEND='export PATH="/mnt/projects/CCBR-Pipelines/bin:$PATH"'
MODULE_LOAD="module load singularity; $PATH_PREPEND; $CONDA_ACTIVATE"
MODULE_LOAD="module load singularity; $PATH_PREPEND; $ENV_ACTIVATE"
TEMP_DIR="/scratch/local/"
REFS_DIR="/mnt/projects/CCBR-Pipelines/db/charlie/fastas_gtfs/"
else
Expand All @@ -85,7 +90,7 @@ fi

# set defaults
export HOST="hg38"
export ADDITIVES="ERCC"
export ADDITIVES=""
export VIRUSES="NC_009333.1"
MANIFEST="${PIPELINE_HOME}/config/samples.tsv"

Expand Down Expand Up @@ -168,7 +173,7 @@ Required Arguments:
Optional Arguments:

--host|-g : supply host at command line. hg38 or mm39. (--runmode=init only)
--additives|-a : supply comma-separated list of additives at command line. ERCC or BAC16Insert or both (--runmode=init only)
--additives|-a : supply comma-separated list of additives at command line. ERCC or BAC16Insert or both (default: blank) (--runmode=init only)
--viruses|-v : supply comma-separated list of viruses at command line (--runmode=init only)
--manifest|-s : absolute path to samples.tsv. This will be copied to output folder (--runmode=init only)
--changegrp|-z : change group to "Ziegelbauer_lab" before running anything. Biowulf-only. Useful for correctly setting permissions.
Expand Down Expand Up @@ -311,7 +316,7 @@ function check_deps() {

# load modules if available, or check whether they're in the path
function load_modules() {
eval $MODULE_LOAD
eval "$MODULE_LOAD"
check_deps
}

Expand All @@ -330,6 +335,7 @@ function runcheck(){

function dryrun() {
runcheck
set_singularity_binds
timestamp=$(date +"%y%m%d%H%M%S")
nfiles=$(find ${WORKDIR} -maxdepth 1 -name "dryrun.*.log"|wc -l)
if [ "$nfiles" != "0" ];then
Expand All @@ -342,6 +348,7 @@ function dryrun() {

function touch() {
runcheck
set_singularity_binds
timestamp=$(date +"%y%m%d%H%M%S")
run "--touch" | tee ${WORKDIR}/touch.${timestamp}.log
}
Expand All @@ -352,6 +359,7 @@ function touch() {

function unlock() {
runcheck
set_singularity_binds
run "--unlock"
}

Expand All @@ -360,8 +368,50 @@ function unlock() {
##########################################################################################

function set_singularity_binds() {
binds=$( $PIPELINE_HOME/workflow/scripts/set_singularity_bind_paths.py ${WORKDIR}/config.yaml ${WORKDIR}/samples.tsv)
SINGULARITY_BINDS="-B $EXTRA_SINGULARITY_BINDS,$binds"
# Step 1: get Python-derived paths from config + samples
python_binds=$($PIPELINE_HOME/workflow/scripts/set_singularity_bind_paths.py \
${WORKDIR}/config.yaml ${WORKDIR}/samples.tsv)

# Step 2: walk up parents of WORKDIR and PIPELINE_HOME.
# If /data/<name> is a symlink resolving to that ancestor,
# include both the symlink path and the real path.
explicit_binds=""
for src in "$WORKDIR" "$PIPELINE_HOME"; do
p=$(dirname "$src")
while [[ "$p" != "/" ]]; do
alias="/data/$(basename $p)"
if [[ -L "$alias" && "$(readlink -f $alias 2>/dev/null)" == "$p" ]]; then
explicit_binds="${explicit_binds:+${explicit_binds},}${alias},${p}"
break
fi
p=$(dirname "$p")
done
done

# Step 3: filter Python paths -- remove any that are ancestors or descendants
# of the explicit (bash-derived) paths, as those are already well-covered
filtered_python=""
IFS=',' read -ra explicit_arr <<< "$explicit_binds"
IFS=',' read -ra python_arr <<< "$python_binds"
for p in "${python_arr[@]}"; do
[[ -z "$p" ]] && continue
skip=false
for e in "${explicit_arr[@]}"; do
[[ -z "$e" ]] && continue
[[ "$e" == "$p/"* ]] && skip=true && break # p is ancestor of e (too broad)
[[ "$p" == "$e/"* ]] && skip=true && break # p is descendant of e (too specific)
done
$skip || filtered_python="${filtered_python:+${filtered_python},}${p}"
done

# Step 4: combine -- EXTRA (platform scratch) + explicit + filtered Python
# Build without leading/trailing commas to keep -B argument valid on all platforms
all_binds=""
for part in "$EXTRA_SINGULARITY_BINDS" "$explicit_binds" "$filtered_python"; do
[[ -n "$part" ]] && all_binds="${all_binds:+${all_binds},}${part}"
done

SINGULARITY_BINDS="-B ${all_binds}"
}
##########################################################################################
# PRINT SINGULARITY BINDS ... print bound singularity folders for debugging
Expand Down Expand Up @@ -470,13 +520,25 @@ function run() {

preruncleanup

echo ""
echo "========================================"
echo "Working directory : $WORKDIR"
echo "Snakefile : $SNAKEFILE"
echo "Config file : $CONFIGFILE"
echo "Singularity cache : $SING_CACHE_DIR"
echo "Singularity binds : $SINGULARITY_BINDS"
echo "Platform : $PLATFORM"
echo "========================================"
echo ""

$EXPORT_SING_CACHE_DIR_CMD

snakemake -s $SNAKEFILE\
--directory $WORKDIR \
--printshellcmds \
--use-singularity \
--singularity-args "$SINGULARITY_BINDS" \
--singularity-prefix "$SING_CACHE_DIR" \
--use-envmodules \
--latency-wait 300 \
--configfile $CONFIGFILE \
Expand All @@ -499,6 +561,19 @@ function run() {

preruncleanup

echo ""
echo "========================================"
echo "Working directory : $WORKDIR"
echo "Snakefile : $SNAKEFILE"
echo "Config file : $CONFIGFILE"
echo "Singularity cache : $SING_CACHE_DIR"
echo "Singularity binds : $SINGULARITY_BINDS"
echo "Platform : $PLATFORM"
echo "Cluster profile : $CLUSTER_PROFILE"
echo "Partition : $PARTITION"
echo "========================================"
echo ""

cat > ${WORKDIR}/submit_script.sbatch << EOF
#!/bin/bash
#SBATCH --job-name="charlie"
Expand All @@ -516,6 +591,7 @@ snakemake -s $SNAKEFILE \
--directory $WORKDIR \
--use-singularity \
--singularity-args "$SINGULARITY_BINDS" \
--singularity-prefix "$SING_CACHE_DIR" \
--use-envmodules \
--printshellcmds \
--latency-wait 300 \
Expand Down Expand Up @@ -549,11 +625,24 @@ EOF

else # dry-run and unlock

echo ""
echo "========================================"
echo "Working directory : $WORKDIR"
echo "Snakefile : $SNAKEFILE"
echo "Config file : $CONFIGFILE"
echo "Singularity cache : $SING_CACHE_DIR"
echo "Singularity binds : $SINGULARITY_BINDS"
echo "Platform : $PLATFORM"
echo "Cluster profile : $CLUSTER_PROFILE"
echo "========================================"
echo ""

snakemake $1 -s $SNAKEFILE \
--directory $WORKDIR \
--use-envmodules \
--use-singularity \
--singularity-args "$SINGULARITY_BINDS" \
--singularity-prefix "$SING_CACHE_DIR" \
--printshellcmds \
--latency-wait 300 \
--configfile $CONFIGFILE \
Expand Down Expand Up @@ -636,7 +725,9 @@ function main(){
echo "Working Dir: $WORKDIR"

if [[ -z "$SING_CACHE_DIR" ]]; then
if [[ -d "/data/$USER" ]]; then
if [[ -n "$SIFCACHE" ]]; then
SING_CACHE_DIR="$SIFCACHE"
elif [[ -d "/data/$USER" ]]; then
SING_CACHE_DIR="/data/$USER/.singularity"
else
SING_CACHE_DIR="${WORKDIR}/.singularity"
Expand Down
6 changes: 3 additions & 3 deletions config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ findcirc_params: "--noncanonical"
# host: "hg38"
# additives: "ERCC" # options are ERCC and BAC16Insert
# viruses: "NC_009333.1"
host: "HOST"
additives: "ADDITIVES"
viruses: "VIRUSES"
host: "$HOST"
additives: "$ADDITIVES"
viruses: "$VIRUSES"
# select viruses and other (ERCC/BAC): options are
# ERCC
# BAC16Insert
Expand Down
4 changes: 2 additions & 2 deletions config/samples.tsv
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
sampleName path_to_R1_fastq path_to_R2_fastq
GI1_N /gpfs/gsfs10/users/CCBR_Pipeliner/testdata/circRNA/human/GI1_N_ss.R1.fastq.gz /gpfs/gsfs10/users/CCBR_Pipeliner/testdata/circRNA/human/GI1_N_ss.R2.fastq.gz
GI1_T /gpfs/gsfs10/users/CCBR_Pipeliner/testdata/circRNA/human/GI1_T_ss.R1.fastq.gz
GI1_N /vf/users/CCBR_Pipeliner/testdata/circRNA/human/GI1_N_ss.R1.fastq.gz /vf/users/CCBR_Pipeliner/testdata/circRNA/human/GI1_N_ss.R2.fastq.gz
GI1_T /vf/users/CCBR_Pipeliner/testdata/circRNA/human/GI1_T_ss.R1.fastq.gz
2 changes: 1 addition & 1 deletion config/samples.tsv.fulltest
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
sampleName path_to_R1_fastq path_to_R2_fastq
GI1_N /data/Ziegelbauer_lab/circRNADetection/rawdata/ccbr983/fastq2/5_GI112118_norm_S4_R1_001.fastq.gz /data/Ziegelbauer_lab/circRNADetection/rawdata/ccbr983/fastq2/5_GI112118_norm_S4_R2_001.fastq.gz
GI1_T /data/Ziegelbauer_lab/circRNADetection/rawdata/ccbr983/fastq2/6_GI112118_tum_S5_R1_001.fastq.gz
GI1_T /data/Ziegelbauer_lab/circRNADetection/rawdata/ccbr983/fastq2/6_GI112118_tum_S5_R1_001.fastq.gz
2 changes: 1 addition & 1 deletion config/slurm-biowulf/cluster.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"__default__": {
"gres": "lscratch:256",
"mem": "40g",
"partition": "ccr,norm",
"partition": "norm",
"threads": "2",
"time": "4:00:00",
"name": "{rule}.{wildcards}",
Expand Down
2 changes: 1 addition & 1 deletion docker/bowtie1/environment.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bowtie=1.3.1
bowtie=1.3.1
2 changes: 1 addition & 1 deletion docker/circRNA_finder/environment.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
samtools
STAR
STAR
8 changes: 4 additions & 4 deletions docker/cutadapt_fqfilter/environment.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
channels:
- conda-forge
- bioconda
- conda-forge
- bioconda
dependencies:
- cutadapt
- fastq-filter
- cutadapt
- fastq-filter
6 changes: 3 additions & 3 deletions docker/dcc/environment.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
channels:
- conda-forge
- bioconda
- conda-forge
- bioconda
dependencies:
- bioconda::dcc=0.5.0
- bioconda::dcc=0.5.0
Loading
Loading