diff --git a/.github/workflows/build-push-container.yml b/.github/workflows/build-push-container.yml new file mode 100644 index 0000000..4a929bf --- /dev/null +++ b/.github/workflows/build-push-container.yml @@ -0,0 +1,58 @@ +# +name: build-push-container + +# Configures this workflow to run every time a change is pushed to the branch called `release`. +on: + push: + paths: + - 'docker/scratch-annotation.Dockerfile' + - '.github/workflows/build-push-container.yml' + workflow_dispatch: + +# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu. +jobs: + build-and-push-image: + runs-on: ubuntu-latest + # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. + permissions: + contents: read + packages: write + attestations: write + id-token: write + # + steps: + - name: Checkout repository + uses: actions/checkout@v4 + # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GHCR_TOKEN }} + # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=sha,format=short,prefix= # Generates a tag like '860c190' + main + # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. + # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. + # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. + - name: Build and push Docker image + id: push + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + file: docker/scratch-annotation.Dockerfile + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..6dbd57b --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,34 @@ +#inspired by https://docs.cirro.bio/pipelines/development/#automated-testing +name: test + +on: + pull_request: + branches: + - 'main' + workflow_dispatch: +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + lfs: true + + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + + - name: install nextflow + run: | + wget -qO- get.nextflow.io | bash + sudo mv nextflow /usr/local/bin/ + + - name: install nf-test + run: | + wget -qO- https://get.nf-test.com | bash + sudo mv nf-test /usr/local/bin + + - name: run tests + run: nf-test test diff --git a/.gitignore b/.gitignore index 146ec77..a773372 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ figures/ *.zip *.tar.gz *.sif +_nf-test* # temporary files for nf-test - quarto does not produce _freeze and _report if testdir starts with dot + +/.quarto/ diff --git a/bin/sceasy_converter.R b/bin/sceasy_converter.R old mode 100644 new mode 100755 diff --git a/bin/seurat_subset.R b/bin/seurat_subset.R old mode 100644 new mode 100755 diff --git a/docker/scratch-annotation.Dockerfile b/docker/scratch-annotation.Dockerfile index a58da26..f26dfab 100644 --- a/docker/scratch-annotation.Dockerfile +++ b/docker/scratch-annotation.Dockerfile @@ -6,11 +6,11 @@ WORKDIR /opt # Timezone settings ENV TZ=US/Central -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \ - echo $TZ > /etc/timezone -# pass your PAT at build time so remotes::install_github can auth -ARG GITHUB_PAT -ENV GITHUB_PAT=${GITHUB_PAT} +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \ + && echo $TZ > /etc/timezone + + +ENV R_REPOS="https://packagemanager.posit.co/cran/latest" # Install system dependencies RUN apt-get update && apt-get install -y \ @@ -31,136 +31,111 @@ RUN apt-get update && apt-get install -y \ libpng-dev \ libtiff5-dev \ zlib1g-dev \ - libxt-dev + libxt-dev \ + + jags \ + python3 \ + python3-pip \ + python3-venv \ + libhdf5-dev \ + libgsl-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* # Updating quarto to Quarto v1.4.553 RUN wget https://github.com/quarto-dev/quarto-cli/releases/download/v1.4.553/quarto-1.4.553-linux-amd64.deb -O quarto-1.4.553-linux-amd64.deb RUN dpkg -i quarto-1.4.553-linux-amd64.deb -# # Install remotes package -# RUN R -e "install.packages('remotes')" - - -RUN apt-get update && apt-get install -y python3 python3-pip python3-venv # Install core R packages -RUN Rscript -e "install.packages(c('R.utils','rmarkdown','devtools','tidyverse','readr', 'dplyr', 'ggplot2', 'cowplot', 'remotes', 'BiocManager','reticulate', 'HGNChelper', 'optparse'), repos='http://cran.us.r-project.org')" - - -RUN Rscript -e "BiocManager::install(c('S4Vectors','DelayedMatrixStats','BiocGenerics','Biobase', 'SummarizedExperiment', 'AnnotationDbi', 'org.Hs.eg.db'), ask=FALSE, update=TRUE)" +RUN Rscript -e "install.packages(c( \ + 'R.utils', \ + 'rmarkdown', \ + 'devtools', \ + 'tidyverse', \ + 'readr', \ + 'dplyr', \ + 'ggplot2', \ + 'cowplot', \ + 'remotes', \ + 'BiocManager',\ + 'reticulate', \ + 'HGNChelper', \ + 'hdf5r', \ + 'optparse' \ + ), repos='${R_REPOS}')" + +# Bioconductor packages RUN Rscript -e "BiocManager::install(c( \ - 'HDF5Array','rhdf5','rhdf5lib', \ + 'S4Vectors', \ + 'DelayedMatrixStats', \ + 'BiocGenerics',\ + 'Biobase', \ + 'SummarizedExperiment', \ + 'AnnotationDbi', \ + 'org.Hs.eg.db' \ + ), ask=FALSE, update=TRUE)" \ + && Rscript -e "BiocManager::install(c( \ + 'HDF5Array', \ + 'rhdf5', \ + 'rhdf5lib', \ 'SingleCellExperiment', \ - 'GOSemSim','MatrixGenerics','treeio','DOSE','ggtree','enrichplot', \ - 'clusterProfiler','DirichletMultinomial','rtracklayer','GenomicFeatures', \ - 'BSgenome','ensembldb','TFBSTools', \ - 'BSgenome.Hsapiens.UCSC.hg38','EnsDb.Hsapiens.v86' \ - ), \ - ask=FALSE, update=FALSE )" - -# Setting repository URL -ARG R_REPO="http://cran.us.r-project.org" + 'GOSemSim', \ + 'MatrixGenerics', \ + 'treeio', \ + 'DOSE',\ + 'ggtree',\ + 'enrichplot', \ + 'clusterProfiler',\ + 'DirichletMultinomial',\ + 'rtracklayer',\ + 'GenomicFeatures', \ + 'BSgenome',\ + 'ensembldb',\ + 'TFBSTools', \ + 'BSgenome.Hsapiens.UCSC.hg38', \ + 'EnsDb.Hsapiens.v86' \ + ), ask=FALSE, update=FALSE )" -# # Install BiocManager -# RUN Rscript -e "BiocManager::install(${R_BIOC_DEPS})" RUN Rscript -e 'remotes::install_github("ctlab/fgsea")' - - -# Install Seurat Wrappers -RUN wget https://github.com/satijalab/seurat/archive/refs/heads/seurat5.zip -O /opt/seurat-v5.zip -RUN wget https://github.com/satijalab/seurat-data/archive/refs/heads/seurat5.zip -O /opt/seurat-data.zip -RUN wget https://github.com/satijalab/seurat-wrappers/archive/refs/heads/seurat5.zip -O /opt/seurat-wrappers.zip - -RUN Rscript -e "devtools::install_local('/opt/seurat-v5.zip')" -RUN Rscript -e "devtools::install_local('/opt/seurat-data.zip')" -RUN Rscript -e "devtools::install_local('/opt/seurat-wrappers.zip')" - - +# Seurat and wrappers +RUN wget https://github.com/satijalab/seurat/archive/refs/tags/v5.3.1.zip -O /opt/seurat-v5.zip \ + && wget https://github.com/satijalab/seurat-data/archive/refs/heads/seurat5.zip -O /opt/seurat-data.zip \ + && wget https://github.com/satijalab/seurat-wrappers/archive/refs/heads/seurat5.zip -O /opt/seurat-wrappers.zip \ + && Rscript -e "devtools::install_local('/opt/seurat-v5.zip')" \ + && Rscript -e "devtools::install_local('/opt/seurat-data.zip')" \ + && Rscript -e "devtools::install_local('/opt/seurat-wrappers.zip')" \ + && rm /opt/seurat-v5.zip /opt/seurat-data.zip /opt/seurat-wrappers.zip \ + && Rscript -e "devtools::install_github('satijalab/azimuth', ref = 'master', dependencies=TRUE, upgrade='never')" # Install SCP package from GitHub -# RUN Rscript -e "remotes::install_github('bnprks/BPCells/r')" -RUN Rscript -e "devtools::install_github('PaulingLiu/ROGUE', dependencies = TRUE, force = TRUE)" -# RUN Rscript -e "devtools::install_github('zhanghao-njmu/SCP', dependencies = TRUE, force = TRUE)" -RUN Rscript -e "remotes::install_github('zhanghao-njmu/SCP', upgrade = 'always', dependencies = TRUE, force = TRUE)" -RUN Rscript -e "remotes::install_github('cellgeni/sceasy', upgrade = 'always', dependencies = TRUE, force = TRUE)" - - +RUN Rscript -e "devtools::install_github('PaulingLiu/ROGUE', dependencies = TRUE, upgrade = 'never', force = TRUE)" \ + && Rscript -e "devtools::install_github('zhanghao-njmu/SCP', dependencies = TRUE, upgrade = 'never', force = TRUE)" \ + && Rscript -e "devtools::install_github('cellgeni/sceasy', dependencies = TRUE, upgrade = 'never', force = TRUE)" \ + # uninstall reactome.db that SCP pulls (1.7Gb) + && Rscript -e "remove.packages('reactome.db')" +# Install annotables +RUN Rscript -e "devtools::install_github('stephenturner/annotables')" \ + && Rscript -e "devtools::install_github('miccec/yaGST', dependencies = TRUE, upgrade = 'never')" -# Create and activate virtual environment -RUN python3 -m venv /opt/venv -ENV PATH="/opt/venv/bin:$PATH" - -# # Upgrade pip and install Python packages in venv -# RUN pip install --upgrade pip && \ -# pip install numpy pandas scikit-learn matplotlib seaborn jupyter jupyter-cache papermill - -# Create and activate a virtual environment before installing Python packages +# Create and activate a virtual environment before installing Python packages +# Note the no-gpu version of torch to avoid ~5Gb dependencies and keep image size smaller RUN python3 -m venv /opt/venv \ - && /opt/venv/bin/pip install --no-cache-dir numpy pandas scikit-learn matplotlib seaborn jupyter jupyter-cache papermill anndata scanpy scipy session_info scSpectra metatime celltypist \ + && /opt/venv/bin/pip install --no-cache-dir --upgrade pip \ + && /opt/venv/bin/pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cpu \ + && /opt/venv/bin/pip install --no-cache-dir numpy pandas scikit-learn \ + matplotlib seaborn jupyter jupyter-cache papermill anndata scanpy scipy \ + session_info scSpectra metatime celltypist \ && ln -s /opt/venv/bin/python /usr/local/bin/python \ && ln -s /opt/venv/bin/pip /usr/local/bin/pip -# Create and activate virtual environment -RUN python -m venv /opt/venv -ENV PATH="/opt/venv/bin:$PATH" -# Setting celltypist variable +ENV PATH="/opt/venv/bin:$PATH" ENV CELLTYPIST_FOLDER=/opt/celltypist -# Installing celltypist models -COPY setup.py /opt/ -RUN python3 /opt/setup.py - -# Additional packages -RUN apt-get install -y libhdf5-dev -RUN Rscript -e "install.packages('hdf5r')" - - -# Java + Fortran -RUN apt-get update && apt-get install -y default-jre libgfortran5 - -# JAGS -RUN apt-get install -y jags - - -# Install annotables -RUN Rscript -e "devtools::install_github('stephenturner/annotables')" -# RUN Rscript -e "install.packages('rJava', repos = 'http://cran.us.r-project.org')" -RUN Rscript -e "devtools::install_github('miccec/yaGST', dependencies = TRUE, upgrade = 'never')" - -# RUN Rscript -e "devtools::install_github('AntonioDeFalco/SCEVAN', dependencies = TRUE, upgrade = 'never')" -# install SCP -RUN Rscript -e "remotes::install_github( \ - 'zhanghao-njmu/SCP', \ - dependencies=TRUE, \ - upgrade='always', \ - auth_token = Sys.getenv('GITHUB_PAT'))" - - -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - libgsl-dev \ - && rm -rf /var/lib/apt/lists/* - # Install DirichletMultinomial + TFBSTools (and all of their R & Bioc deps) - -RUN Rscript -e "install.packages(c('DirichletMultinomial','TFBSTools'), dependencies = TRUE, repos = BiocManager::repositories())" - -# install Azimuth -RUN Rscript -e "remotes::install_github( \ - 'satijalab/azimuth', ref = 'master', \ - dependencies=TRUE, \ - upgrade='always', \ - auth_token = Sys.getenv('GITHUB_PAT'))" - - -# Cleaning apt-get cache -RUN apt-get clean -RUN rm -rf /var/lib/apt/lists/* - - # Command to run on container start CMD ["bash"] diff --git a/modules/local/helpers/convert/resources/usr/bin/sceasy_converter.R b/modules/local/helpers/convert/resources/usr/bin/sceasy_converter.R old mode 100644 new mode 100755 index 4c65a22..b86ac2e --- a/modules/local/helpers/convert/resources/usr/bin/sceasy_converter.R +++ b/modules/local/helpers/convert/resources/usr/bin/sceasy_converter.R @@ -47,7 +47,8 @@ if(opt$type == "Seurat") { sce_object <- as.SingleCellExperiment( seurat_object) - output <- file.path(opt$outdir, gsub(".RDS", ".h5ad", basename(opt$file))) + output <- file.path(opt$outdir, gsub(".RDS", ".h5ad", basename(opt$file), + ignore.case = TRUE)) convertFormat(sce_object, from = "sce", to = "anndata", outFile = output) diff --git a/modules/local/helpers/subset/resources/usr/bin/seurat_subset.R b/modules/local/helpers/subset/resources/usr/bin/seurat_subset.R old mode 100644 new mode 100755 index 7708aa5..2e4655e --- a/modules/local/helpers/subset/resources/usr/bin/seurat_subset.R +++ b/modules/local/helpers/subset/resources/usr/bin/seurat_subset.R @@ -48,5 +48,7 @@ seurat_object <- subset( # -saveRDS( - seurat_object, file = file.path(opt$outdir, gsub(".RDS", "_filtered.RDS", basename(opt$file)))) +saveRDS(seurat_object, + file = file.path(opt$outdir, gsub(".RDS", "_filtered.RDS", + basename(opt$file), + ignore.case = TRUE))) \ No newline at end of file diff --git a/nf-test.config b/nf-test.config new file mode 100644 index 0000000..44be616 --- /dev/null +++ b/nf-test.config @@ -0,0 +1,7 @@ +config { + testsDir "tests" + workDir "_nf-test" + configFile "tests/nextflow.config" + profile "docker" +} + diff --git a/tests/data/create_data.nf b/tests/data/create_data.nf new file mode 100644 index 0000000..3a09969 --- /dev/null +++ b/tests/data/create_data.nf @@ -0,0 +1,16 @@ +process CREATE_DATA { + + tag 'Creating test data for annotation' + label 'process_medium' + + input: + path(cell_markers_database) + + output: + path('sr_tiny.rds') , emit: sr_tiny + path('sr_ref_tiny.rds') , emit: sr_ref_tiny + path('cell_status.csv') , emit: cell_status + + script: + template 'make-test-seurat.r' +} \ No newline at end of file diff --git a/tests/data/templates/make-test-seurat.r b/tests/data/templates/make-test-seurat.r new file mode 100644 index 0000000..a856fcf --- /dev/null +++ b/tests/data/templates/make-test-seurat.r @@ -0,0 +1,111 @@ +#!/usr/bin/env Rscript + +library(Seurat) + +set.seed(42) + +# get the cell_markers_database (normally from assets) +cmdb <- read.csv("${cell_markers_database}", stringsAsFactors = FALSE) + +# create a tiny Seurat object for testing purposes +make_small_seurat <- function(cmdb, ncell_each = 100) { + # below 2500 genes Seurat AddModuleScore fails with error described below + # https://github.com/satijalab/seurat/issues/4819#issuecomment-2825615354 + + lineage <- cmdb[cmdb["parent_level"] == "Lineage_markers", + c("parent_level", "cell_annotation", "markers")] + detailed <- cmdb[cmdb["parent_level"] != "Lineage_markers", + c("parent_level", "cell_annotation", "markers")] + cell_types <- unique(detailed[["cell_annotation"]]) + + # add cells that are in the lineage but not in the detailed list + missing <- setdiff(unique(lineage[["cell_annotation"]]), + unique(detailed[["parent_level"]])) + cell_types <- c(cell_types, missing) + + # create counts from negative binomial based on the cell types in the cmdb + counts_list <- lapply(cell_types, function(cell_type) { + cell_type_genes <- detailed[detailed[["cell_annotation"]] == cell_type, + "markers"] + + parent <- detailed[["parent_level"]][detailed[["cell_annotation"]]==cell_type] + parent <- unique(parent) + + #check that the detailed cell type has only one parent in the cmdb + if(length(parent) > 1) { + stop(paste("Cell type", cell_type, "has multiple parents in the cmdb")) + } else if (length(parent)==0) { + parent <- cell_type # if the cell type is not in the lineage, it is its own parent + } + + lineage_genes <- lineage[lineage[["cell_annotation"]] == parent, + "markers"] + cell_type_genes <- unique(c(lineage_genes, cell_type_genes)) + + ct <- matrix( + data = rnbinom(length(cell_type_genes) * ncell_each, size = 1, mu = 100), + nrow = length(cell_type_genes), + ncol = ncell_each, + dimnames = list( + cell_type_genes, + paste0("Cell", 1:ncell_each) + ) + ) |> t() |> as.data.frame() + ct[["major_type"]] <- parent # preserve cell names for after rbind.fill + ct + }) + + counts <- do.call(plyr::rbind.fill, counts_list) + counts[is.na(counts)] <- 0 + rownames(counts) <- paste0(counts[["major_type"]], 1:nrow(counts)) + counts["major_type"] <- NULL + + # if resulting counts has less than 2500 genes, add random genes to reach 2500 + if (ncol(counts) < 2500) { + n_genes_to_add <- 2500 - ncol(counts) + random_genes <- paste0("DUMMY", seq_len(n_genes_to_add)) + random_counts_matrix <- matrix( + data = rnbinom(nrow(counts) * n_genes_to_add, size = 1, mu = 100), + nrow = nrow(counts), + ncol = n_genes_to_add, + dimnames = list(rownames(counts), random_genes) + ) + # set 80% of the random counts to 0 to make them more realistic + n_elements <- length(random_counts_matrix) + zeroes <- sample(n_elements, size = floor(n_elements * 0.8)) + random_counts_matrix[zeroes] <- 0 + random_counts <- as.data.frame(random_counts_matrix) + counts <- cbind(counts, random_counts) + } + + sr <- CreateSeuratObject(counts = t(as.matrix(counts))) + sr <- NormalizeData(sr) + sr <- FindVariableFeatures(sr) + sr <- ScaleData(sr, features = VariableFeatures(sr)) + sr <- RunPCA(sr, features = VariableFeatures(sr)) + sr <- FindNeighbors(sr, dims = 1:10) + sr <- FindClusters(sr, resolution = 0.5) #create seurat_clusters sctype needs + + sr +} + +# a small input Seurat object for testing +sr <- make_small_seurat(cmdb, ncell_each = 100) +# sctype module wants patient_id in the metadata +sr[["patient_id"]] <- "Patient1" +saveRDS(sr, file = "sr_tiny.rds") + +# simulate cell malignancy status metadata for testing +cell_status <- data.frame( + barcode = colnames(sr), + cell_status = sample(c("TME", "Malignant"), size = ncol(sr), replace = TRUE) +) +write.csv(cell_status, file = "cell_status.csv", row.names = FALSE) + +# a small ref Seurat object for testing +sr_ref <- make_small_seurat(cmdb, ncell_each = 100) + +# azimuth needs seurat_annotations, make one from original cell names +sr_ref[["seurat_annotations"]] <- gsub("[0-9]+", "", rownames(sr_ref@meta.data)) +saveRDS(sr_ref, file = "sr_ref_tiny.rds") + diff --git a/tests/modules/local/azimuth/main.nf.test b/tests/modules/local/azimuth/main.nf.test new file mode 100644 index 0000000..262cd89 --- /dev/null +++ b/tests/modules/local/azimuth/main.nf.test @@ -0,0 +1,44 @@ +nextflow_process{ + name 'azimuth_test' + script 'modules/local/azimuth/main.nf' + process 'AZIMUTH_ANNOTATION' + + + + + setup { + run("CREATE_DATA"){ + script "tests/data/create_data.nf" + params { + max_cpus = 2 + max_memory = '4 GB' + } + process { + """ + input[0] = file("${projectDir}/assets/cell_markers_database.csv") + """ + } + } + } + + test("Run Azimuth") { + + tag 'azimuth' + config 'tests/nextflow.config' + + when { + process { + """ + input[0] = file("${projectDir}/modules/local/azimuth/notebook_azimuth.qmd") + input[1] = CREATE_DATA.out.sr_tiny + input[2] = CREATE_DATA.out.sr_ref_tiny + input[3] = file(params.page_config) + """ + } + } + + then { + assert process.success + } + } +} \ No newline at end of file diff --git a/tests/modules/local/helpers/convert/main.nf.test b/tests/modules/local/helpers/convert/main.nf.test new file mode 100644 index 0000000..be98cf9 --- /dev/null +++ b/tests/modules/local/helpers/convert/main.nf.test @@ -0,0 +1,42 @@ +nextflow_process{ + name 'helpers_convert_test' + script 'modules/local/helpers/convert/main.nf' + process 'HELPER_SCEASY_CONVERTER' + + + + + setup { + run("CREATE_DATA"){ + script "tests/data/create_data.nf" + params { + max_cpus = 2 + max_memory = '4 GB' + } + process { + """ + input[0] = file("${projectDir}/assets/cell_markers_database.csv") + """ + } + } + } + + test("Run Converter") { + tag 'helpers' + tag 'sceasy' + tag 'convert' + config 'tests/nextflow.config' + + when { + process { + """ + input[0] = CREATE_DATA.out.sr_tiny + """ + } + } + + then { + assert process.success + } + } +} \ No newline at end of file diff --git a/tests/modules/local/helpers/subset/main.nf.test b/tests/modules/local/helpers/subset/main.nf.test new file mode 100644 index 0000000..09991a4 --- /dev/null +++ b/tests/modules/local/helpers/subset/main.nf.test @@ -0,0 +1,43 @@ +nextflow_process{ + name 'helpers_subset_test' + script 'modules/local/helpers/subset/main.nf' + process 'HELPER_SEURAT_SUBSET' + + + + + setup { + run("CREATE_DATA"){ + script "tests/data/create_data.nf" + params { + max_cpus = 2 + max_memory = '4 GB' + } + process { + """ + input[0] = file("${projectDir}/assets/cell_markers_database.csv") + """ + } + } + } + + test("Run Subset") { + + tag 'helpers' + tag 'subset' + config 'tests/nextflow.config' + + when { + process { + """ + input[0] = CREATE_DATA.out.sr_tiny + input[1] = CREATE_DATA.out.cell_status + """ + } + } + + then { + assert process.success + } + } +} \ No newline at end of file diff --git a/tests/modules/local/sctype/aggregate/main.nf.test b/tests/modules/local/sctype/aggregate/main.nf.test new file mode 100644 index 0000000..081b469 --- /dev/null +++ b/tests/modules/local/sctype/aggregate/main.nf.test @@ -0,0 +1,67 @@ +nextflow_process{ + name 'sctype_test' + script 'modules/local/sctype/aggregate/main.nf' + process 'SCYTPE_AGGREGATE_ANNOTATION' + + setup { + run("CREATE_DATA"){ + script "tests/data/create_data.nf" + params { + max_cpus = 2 + max_memory = '4 GB' + } + process { + """ + input[0] = file("${projectDir}/assets/cell_markers_database.csv") + """ + } + } + run("SCYTPE_MAJOR_ANNOTATION"){ + script "modules/local/sctype/major/main.nf" + process { + """ + input[0] = file("${projectDir}/modules/local/sctype/major/notebook_sctype_major.qmd") + input[1] = CREATE_DATA.out.sr_tiny + input[2] = file("${projectDir}/assets/cell_markers_database.csv") + input[3] = file(params.page_config) + """ + } + } + run("SCYTPE_STATE_ANNOTATION"){ + script "modules/local/sctype/state/main.nf" + process { + """ + input[0] = file("${projectDir}/modules/local/sctype/state/notebook_sctype_states.qmd") + input[1] = SCYTPE_MAJOR_ANNOTATION.out.seurat_rds + input[2] = file("${projectDir}/assets/cell_markers_database.csv") + input[3] = SCYTPE_MAJOR_ANNOTATION.out.major_list.splitText().map{ iter -> iter.split(":") } + .filter{ !(it[0] =~ "Unknown|Epithelial|Fibroblast|NK_Cells") } + .map{ it[0].trim() } + input[4] = file(params.page_config) + """ + } + } + } + + test("Run Sctype Aggregate") { + + tag 'sctype' + tag 'sctype-aggregate' + config 'tests/nextflow.config' + + when { + process { + """ + input[0] = file("${projectDir}/modules/local/sctype/aggregate/notebook_sctype_aggregate.qmd") + input[1] = SCYTPE_MAJOR_ANNOTATION.out.seurat_rds + input[2] = SCYTPE_STATE_ANNOTATION.out.annotation.collect() + input[3] = file(params.page_config) + """ + } + } + + then { + assert process.success + } + } +} \ No newline at end of file diff --git a/tests/modules/local/sctype/major/main.nf.test b/tests/modules/local/sctype/major/main.nf.test new file mode 100644 index 0000000..73ecd73 --- /dev/null +++ b/tests/modules/local/sctype/major/main.nf.test @@ -0,0 +1,42 @@ +nextflow_process{ + name 'sctype_test' + script 'modules/local/sctype/major/main.nf' + process 'SCYTPE_MAJOR_ANNOTATION' + + setup { + run("CREATE_DATA"){ + script "tests/data/create_data.nf" + params { + max_cpus = 2 + max_memory = '4 GB' + } + process { + """ + input[0] = file("${projectDir}/assets/cell_markers_database.csv") + """ + } + } + } + + test("Run Sctype") { + + tag 'sctype' + tag 'sctype-major' + config 'tests/nextflow.config' + + when { + process { + """ + input[0] = file("${projectDir}/modules/local/sctype/major/notebook_sctype_major.qmd") + input[1] = CREATE_DATA.out.sr_tiny + input[2] = file("${projectDir}/assets/cell_markers_database.csv") + input[3] = file(params.page_config) + """ + } + } + + then { + assert process.success + } + } +} \ No newline at end of file diff --git a/tests/modules/local/sctype/state/main.nf.test b/tests/modules/local/sctype/state/main.nf.test new file mode 100644 index 0000000..96dfaa1 --- /dev/null +++ b/tests/modules/local/sctype/state/main.nf.test @@ -0,0 +1,56 @@ +nextflow_process{ + name 'sctype_test' + script 'modules/local/sctype/state/main.nf' + process 'SCYTPE_STATE_ANNOTATION' + + setup { + run("CREATE_DATA"){ + script "tests/data/create_data.nf" + params { + max_cpus = 2 + max_memory = '4 GB' + } + process { + """ + input[0] = file("${projectDir}/assets/cell_markers_database.csv") + """ + } + } + run("SCYTPE_MAJOR_ANNOTATION"){ + script "modules/local/sctype/major/main.nf" + process { + """ + input[0] = file("${projectDir}/modules/local/sctype/major/notebook_sctype_major.qmd") + input[1] = CREATE_DATA.out.sr_tiny + input[2] = file("${projectDir}/assets/cell_markers_database.csv") + input[3] = file(params.page_config) + """ + } + } + } + + test("Run Sctype States") { + + tag 'sctype' + tag 'sctype-state' + config 'tests/nextflow.config' + + when { + process { + """ + input[0] = file("${projectDir}/modules/local/sctype/state/notebook_sctype_states.qmd") + input[1] = SCYTPE_MAJOR_ANNOTATION.out.seurat_rds + input[2] = file("${projectDir}/assets/cell_markers_database.csv") + input[3] = SCYTPE_MAJOR_ANNOTATION.out.major_list.splitText().map{ iter -> iter.split(":") } + .filter{ !(it[0] =~ "Unknown|Epithelial|Fibroblast|NK_Cells") } + .map{ it[0].trim() } + input[4] = file(params.page_config) + """ + } + } + + then { + assert process.success + } + } +} \ No newline at end of file diff --git a/tests/nextflow.config b/tests/nextflow.config new file mode 100644 index 0000000..efb34a9 --- /dev/null +++ b/tests/nextflow.config @@ -0,0 +1,29 @@ +/* +======================================================================================== + Nextflow config file for running tests +======================================================================================== +*/ + +process { + withName: 'SCYTPE_MAJOR_ANNOTATION' { + container = 'ghcr.io/break-through-cancer/scratch-annotation:945c406' + } + withName: 'SCYTPE_STATE_ANNOTATION' { + container = 'ghcr.io/break-through-cancer/scratch-annotation:945c406' + } + withName: 'AZIMUTH_ANNOTATION' { + container = 'ghcr.io/break-through-cancer/scratch-annotation:945c406' + } + withName: 'CREATE_DATA' { + container = 'ghcr.io/break-through-cancer/scratch-annotation:945c406' + } + withName: 'SCYTPE_AGGREGATE_ANNOTATION' { + container = 'ghcr.io/break-through-cancer/scratch-annotation:945c406' + } + withName: 'HELPER_SEURAT_SUBSET' { + container = 'ghcr.io/break-through-cancer/scratch-annotation:945c406' + } + withName: 'HELPER_SCEASY_CONVERTER' { + container = 'ghcr.io/break-through-cancer/scratch-annotation:945c406' + } +} \ No newline at end of file