(defproject tservice/quartet-rnaseq-report "v0.1.0" | |||||
:description "FIXME: write description" | |||||
:url "http://example.com/FIXME" | |||||
(defproject tservice-plugins/quartet-rnaseq-report "v0.1.0" | |||||
:description "QC Report for Quartet RNA-Seq." | |||||
:url "https://github.com/tservice-plugins/quartet-rnaseq-report" | |||||
:license {:name "Eclipse Public License" | :license {:name "Eclipse Public License" | ||||
:url "http://www.eclipse.org/legal/epl-v10.html"} | :url "http://www.eclipse.org/legal/epl-v10.html"} | ||||
:min-lein-version "2.5.0" | :min-lein-version "2.5.0" | ||||
{:provided | {:provided | ||||
{:dependencies | {:dependencies | ||||
[[org.clojure/clojure "1.10.1"] | [[org.clojure/clojure "1.10.1"] | ||||
[tservice "0.3.1"]]} | |||||
[org.clojars.yjcyxky/tservice "0.5.6"]]} | |||||
:uberjar | :uberjar | ||||
{:auto-clean true | {:auto-clean true |
library/ | |||||
python/ | |||||
staging/ |
local({ | |||||
# the requested version of renv | |||||
version <- "0.12.0" | |||||
# the project directory | |||||
project <- getwd() | |||||
# avoid recursion | |||||
if (!is.na(Sys.getenv("RENV_R_INITIALIZING", unset = NA))) | |||||
return(invisible(TRUE)) | |||||
# signal that we're loading renv during R startup | |||||
Sys.setenv("RENV_R_INITIALIZING" = "true") | |||||
on.exit(Sys.unsetenv("RENV_R_INITIALIZING"), add = TRUE) | |||||
# signal that we've consented to use renv | |||||
options(renv.consent = TRUE) | |||||
# load the 'utils' package eagerly -- this ensures that renv shims, which | |||||
# mask 'utils' packages, will come first on the search path | |||||
library(utils, lib.loc = .Library) | |||||
# check to see if renv has already been loaded | |||||
if ("renv" %in% loadedNamespaces()) { | |||||
# if renv has already been loaded, and it's the requested version of renv, | |||||
# nothing to do | |||||
spec <- .getNamespaceInfo(.getNamespace("renv"), "spec") | |||||
if (identical(spec[["version"]], version)) | |||||
return(invisible(TRUE)) | |||||
# otherwise, unload and attempt to load the correct version of renv | |||||
unloadNamespace("renv") | |||||
} | |||||
# load bootstrap tools | |||||
bootstrap <- function(version, library) { | |||||
# read repos (respecting override if set) | |||||
repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA) | |||||
if (is.na(repos)) | |||||
repos <- getOption("repos") | |||||
# fix up repos | |||||
on.exit(options(repos = repos), add = TRUE) | |||||
repos[repos == "@CRAN@"] <- "https://cloud.r-project.org" | |||||
options(repos = repos) | |||||
# attempt to download renv | |||||
tarball <- tryCatch(renv_bootstrap_download(version), error = identity) | |||||
if (inherits(tarball, "error")) | |||||
stop("failed to download renv ", version) | |||||
# now attempt to install | |||||
status <- tryCatch(renv_bootstrap_install(version, tarball, library), error = identity) | |||||
if (inherits(status, "error")) | |||||
stop("failed to install renv ", version) | |||||
} | |||||
renv_bootstrap_download_impl <- function(url, destfile) { | |||||
mode <- "wb" | |||||
# https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715 | |||||
fixup <- | |||||
Sys.info()[["sysname"]] == "Windows" && | |||||
substring(url, 1L, 5L) == "file:" | |||||
if (fixup) | |||||
mode <- "w+b" | |||||
download.file( | |||||
url = url, | |||||
destfile = destfile, | |||||
mode = mode, | |||||
quiet = TRUE | |||||
) | |||||
} | |||||
renv_bootstrap_download <- function(version) { | |||||
methods <- list( | |||||
renv_bootstrap_download_cran_latest, | |||||
renv_bootstrap_download_cran_archive, | |||||
renv_bootstrap_download_github | |||||
) | |||||
for (method in methods) { | |||||
path <- tryCatch(method(version), error = identity) | |||||
if (is.character(path) && file.exists(path)) | |||||
return(path) | |||||
} | |||||
stop("failed to download renv ", version) | |||||
} | |||||
renv_bootstrap_download_cran_latest <- function(version) { | |||||
# check for renv on CRAN matching this version | |||||
db <- as.data.frame(available.packages(), stringsAsFactors = FALSE) | |||||
entry <- db[db$Package %in% "renv" & db$Version %in% version, ] | |||||
if (nrow(entry) == 0) { | |||||
fmt <- "renv %s is not available from your declared package repositories" | |||||
stop(sprintf(fmt, version)) | |||||
} | |||||
message("* Downloading renv ", version, " from CRAN ... ", appendLF = FALSE) | |||||
info <- tryCatch( | |||||
download.packages("renv", destdir = tempdir()), | |||||
condition = identity | |||||
) | |||||
if (inherits(info, "condition")) { | |||||
message("FAILED") | |||||
return(FALSE) | |||||
} | |||||
message("OK") | |||||
info[1, 2] | |||||
} | |||||
renv_bootstrap_download_cran_archive <- function(version) { | |||||
name <- sprintf("renv_%s.tar.gz", version) | |||||
repos <- getOption("repos") | |||||
urls <- file.path(repos, "src/contrib/Archive/renv", name) | |||||
destfile <- file.path(tempdir(), name) | |||||
message("* Downloading renv ", version, " from CRAN archive ... ", appendLF = FALSE) | |||||
for (url in urls) { | |||||
status <- tryCatch( | |||||
renv_bootstrap_download_impl(url, destfile), | |||||
condition = identity | |||||
) | |||||
if (identical(status, 0L)) { | |||||
message("OK") | |||||
return(destfile) | |||||
} | |||||
} | |||||
message("FAILED") | |||||
return(FALSE) | |||||
} | |||||
renv_bootstrap_download_github <- function(version) { | |||||
enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE") | |||||
if (!identical(enabled, "TRUE")) | |||||
return(FALSE) | |||||
# prepare download options | |||||
pat <- Sys.getenv("GITHUB_PAT") | |||||
if (nzchar(Sys.which("curl")) && nzchar(pat)) { | |||||
fmt <- "--location --fail --header \"Authorization: token %s\"" | |||||
extra <- sprintf(fmt, pat) | |||||
saved <- options("download.file.method", "download.file.extra") | |||||
options(download.file.method = "curl", download.file.extra = extra) | |||||
on.exit(do.call(base::options, saved), add = TRUE) | |||||
} else if (nzchar(Sys.which("wget")) && nzchar(pat)) { | |||||
fmt <- "--header=\"Authorization: token %s\"" | |||||
extra <- sprintf(fmt, pat) | |||||
saved <- options("download.file.method", "download.file.extra") | |||||
options(download.file.method = "wget", download.file.extra = extra) | |||||
on.exit(do.call(base::options, saved), add = TRUE) | |||||
} | |||||
message("* Downloading renv ", version, " from GitHub ... ", appendLF = FALSE) | |||||
url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version) | |||||
name <- sprintf("renv_%s.tar.gz", version) | |||||
destfile <- file.path(tempdir(), name) | |||||
status <- tryCatch( | |||||
renv_bootstrap_download_impl(url, destfile), | |||||
condition = identity | |||||
) | |||||
if (!identical(status, 0L)) { | |||||
message("FAILED") | |||||
return(FALSE) | |||||
} | |||||
message("Done!") | |||||
return(destfile) | |||||
} | |||||
renv_bootstrap_install <- function(version, tarball, library) { | |||||
# attempt to install it into project library | |||||
message("* Installing renv ", version, " ... ", appendLF = FALSE) | |||||
dir.create(library, showWarnings = FALSE, recursive = TRUE) | |||||
# invoke using system2 so we can capture and report output | |||||
bin <- R.home("bin") | |||||
exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" | |||||
r <- file.path(bin, exe) | |||||
args <- c("--vanilla", "CMD", "INSTALL", "-l", shQuote(library), shQuote(tarball)) | |||||
output <- system2(r, args, stdout = TRUE, stderr = TRUE) | |||||
message("Done!") | |||||
# check for successful install | |||||
status <- attr(output, "status") | |||||
if (is.numeric(status) && !identical(status, 0L)) { | |||||
header <- "Error installing renv:" | |||||
lines <- paste(rep.int("=", nchar(header)), collapse = "") | |||||
text <- c(header, lines, output) | |||||
writeLines(text, con = stderr()) | |||||
} | |||||
status | |||||
} | |||||
renv_bootstrap_prefix <- function() { | |||||
# construct version prefix | |||||
version <- paste(R.version$major, R.version$minor, sep = ".") | |||||
prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-") | |||||
# include SVN revision for development versions of R | |||||
# (to avoid sharing platform-specific artefacts with released versions of R) | |||||
devel <- | |||||
identical(R.version[["status"]], "Under development (unstable)") || | |||||
identical(R.version[["nickname"]], "Unsuffered Consequences") | |||||
if (devel) | |||||
prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r") | |||||
# build list of path components | |||||
components <- c(prefix, R.version$platform) | |||||
# include prefix if provided by user | |||||
prefix <- Sys.getenv("RENV_PATHS_PREFIX") | |||||
if (nzchar(prefix)) | |||||
components <- c(prefix, components) | |||||
# build prefix | |||||
paste(components, collapse = "/") | |||||
} | |||||
renv_bootstrap_library_root <- function(project) { | |||||
path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA) | |||||
if (!is.na(path)) | |||||
return(path) | |||||
path <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA) | |||||
if (!is.na(path)) | |||||
return(file.path(path, basename(project))) | |||||
file.path(project, "renv/library") | |||||
} | |||||
renv_bootstrap_validate_version <- function(version) { | |||||
loadedversion <- utils::packageDescription("renv", fields = "Version") | |||||
if (version == loadedversion) | |||||
return(TRUE) | |||||
# assume four-component versions are from GitHub; three-component | |||||
# versions are from CRAN | |||||
components <- strsplit(loadedversion, "[.-]")[[1]] | |||||
remote <- if (length(components) == 4L) | |||||
paste("rstudio/renv", loadedversion, sep = "@") | |||||
else | |||||
paste("renv", loadedversion, sep = "@") | |||||
fmt <- paste( | |||||
"renv %1$s was loaded from project library, but renv %2$s is recorded in lockfile.", | |||||
"Use `renv::record(\"%3$s\")` to record this version in the lockfile.", | |||||
"Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library.", | |||||
sep = "\n" | |||||
) | |||||
msg <- sprintf(fmt, loadedversion, version, remote) | |||||
warning(msg, call. = FALSE) | |||||
FALSE | |||||
} | |||||
renv_bootstrap_load <- function(project, libpath, version) { | |||||
# try to load renv from the project library | |||||
if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) | |||||
return(FALSE) | |||||
# warn if the version of renv loaded does not match | |||||
renv_bootstrap_validate_version(version) | |||||
# load the project | |||||
renv::load(project) | |||||
TRUE | |||||
} | |||||
# construct path to library root | |||||
root <- renv_bootstrap_library_root(project) | |||||
# construct library prefix for platform | |||||
prefix <- renv_bootstrap_prefix() | |||||
# construct full libpath | |||||
libpath <- file.path(root, prefix) | |||||
# attempt to load | |||||
if (renv_bootstrap_load(project, libpath, version)) | |||||
return(TRUE) | |||||
# load failed; attempt to bootstrap | |||||
bootstrap(version, libpath) | |||||
# exit early if we're just testing bootstrap | |||||
if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA))) | |||||
return(TRUE) | |||||
# try again to load | |||||
if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { | |||||
message("Successfully installed and loaded renv ", version, ".") | |||||
return(renv::load()) | |||||
} | |||||
# failed to download or load renv; warn the user | |||||
msg <- c( | |||||
"Failed to find an renv installation: the project will not be loaded.", | |||||
"Use `renv::activate()` to re-initialize the project." | |||||
) | |||||
warning(paste(msg, collapse = "\n"), call. = FALSE) | |||||
}) |
{ | |||||
"R": { | |||||
"Version": "3.6.3", | |||||
"Repositories": [ | |||||
{ | |||||
"Name": "CRAN", | |||||
"URL": "https://cloud.r-project.org" | |||||
} | |||||
] | |||||
}, | |||||
"Packages": { | |||||
"renv": { | |||||
"Package": "renv", | |||||
"Version": "0.13.0", | |||||
"Source": "Repository", | |||||
"Repository": "CRAN", | |||||
"Hash": "9f10d9db5b50400c348920c5c603385e" | |||||
} | |||||
} | |||||
} |
external.libraries: | |||||
ignored.packages: | |||||
package.dependency.fields: Imports, Depends, LinkingTo | |||||
snapshot.type: all | |||||
use.cache: TRUE | |||||
vcs.ignore.library: TRUE |
git+git://github.com/chinese-quartet/quartet-rnaseq-report#egg=quartet-rnaseq-report |
info: | info: | ||||
name: FIXME: write name | |||||
name: QC Report for Quartet RNA-Seq | |||||
version: v0.1.0 | version: v0.1.0 | ||||
description: FIXME: write description | |||||
description: Generate the QC Report for Quartet RNA-Seq data. | |||||
category: Report | |||||
home: https://github.com/clinico-omics/tservice-plugins | |||||
source: PGx | |||||
short_name: quartet-rnaseq-report | |||||
icons: | |||||
- src: "" | |||||
type: image/png | |||||
sizes: 192x192 | |||||
author: PGx | |||||
plugin: | plugin: | ||||
name: quartet-rnaseq-report | name: quartet-rnaseq-report | ||||
display-name: FIXME: write display name | |||||
display-name: QC Report for Quartet RNA-Seq | |||||
lazy-load: false | lazy-load: false | ||||
init: | init: | ||||
# Unpack environment file to the directory, repository/envs/quartet-rnaseq-report | |||||
- step: unpack-env | |||||
envname: quartet-rnaseq-report | |||||
postunpack: clone-env /opt/local/quartet-rnaseq-report {{ ENV_DEST_DIR }} | |||||
- step: load-namespace | - step: load-namespace | ||||
namespace: tservice.plugins.quartet-rnaseq-report | namespace: tservice.plugins.quartet-rnaseq-report | ||||
- step: register-plugin | - step: register-plugin |
(ns tservice.plugins.quartet-rnaseq-report | (ns tservice.plugins.quartet-rnaseq-report | ||||
(:require [clojure.core.async :as async] | |||||
[clojure.data.json :as json] | |||||
(:require [clojure.data.json :as json] | |||||
[clojure.spec.alpha :as s] | [clojure.spec.alpha :as s] | ||||
[clojure.tools.logging :as log] | [clojure.tools.logging :as log] | ||||
[tservice.lib.commons :as comm :refer [get-path-variable]] | |||||
[tservice.plugins.quartet-rnaseq-report.exp2qcdt :as exp2qcdt] | |||||
[tservice.plugins.quartet-rnaseq-report.merge-exp :as me] | |||||
[spec-tools.core :as st] | [spec-tools.core :as st] | ||||
[spec-tools.json-schema :as json-schema] | |||||
[tservice.config :refer [get-workdir env]] | |||||
[tservice.events :as events] | |||||
[tservice.lib.filter-files :as ff] | |||||
[tservice.lib.fs :as fs-lib] | |||||
[tservice.util :as u] | |||||
[tservice.util.files :as files] | |||||
[clojure.java.io :as io] | |||||
[tservice.db.handler :as db-handler] | |||||
[clojure.java.shell :as shell :refer [sh]] | [clojure.java.shell :as shell :refer [sh]] | ||||
[tservice.vendor.multiqc :as mq])) | |||||
[tservice.lib.files :as ff] | |||||
[tservice.lib.fs :as fs-lib] | |||||
[tservice.vendor.multiqc :as mq] | |||||
[tservice.api.config :refer [add-env-to-path]] | |||||
[tservice.api.storage.fs :as fs-api] | |||||
[tservice.api.data.csv :refer [write-csv!]] | |||||
[tservice.api.task :refer [publish-event! make-plugin-metadata make-events-init create-task! update-process!]] | |||||
[tservice.plugins.quartet-rnaseq-report.exp2qcdt :as exp2qcdt] | |||||
[tservice.plugins.quartet-rnaseq-report.merge-exp :as me] | |||||
[tservice.plugins.quartet-rnaseq-report.util :refer [gen-multiqc-config]])) | |||||
;;; ------------------------------------------------ Event Specs ------------------------------------------------ | ;;; ------------------------------------------------ Event Specs ------------------------------------------------ | ||||
(s/def ::name | (s/def ::name | ||||
:swagger/default "" | :swagger/default "" | ||||
:reason "Not a valid description."})) | :reason "Not a valid description."})) | ||||
(s/def ::project_id | |||||
(st/spec | |||||
{:spec #(some? (re-matches #"[a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8}" %)) | |||||
:type :string | |||||
:description "project-id" | |||||
:swagger/default "40644dec-1abd-489f-a7a8-1011a86f40b0" | |||||
:reason "Not valid a project-id."})) | |||||
(s/def ::filepath | (s/def ::filepath | ||||
(st/spec | (st/spec | ||||
{:spec (s/and string? #(re-matches #"^[a-zA-Z0-9]+:\/\/(\/|\.\/)?[a-zA-Z0-9_\/]+.*" %)) | |||||
{:spec (s/and string? #(re-matches #"^oss:\/\/[a-zA-Z0-9_\/]+.*" %)) | |||||
:type :string | :type :string | ||||
:description "File path for covertor." | :description "File path for covertor." | ||||
:swagger/default nil | :swagger/default nil | ||||
(def quartet-rna-report-params-body | (def quartet-rna-report-params-body | ||||
"A spec for the body parameters." | "A spec for the body parameters." | ||||
(s/keys :req-un [::name ::description ::filepath ::metadata ::parameters] | (s/keys :req-un [::name ::description ::filepath ::metadata ::parameters] | ||||
:opt-un [::project_id])) | |||||
:opt-un [::description])) | |||||
;;; ------------------------------------------------ Event Metadata ------------------------------------------------ | ;;; ------------------------------------------------ Event Metadata ------------------------------------------------ | ||||
(def metadata | (def metadata | ||||
{:route ["/report/quartet-rnaseq-report" | |||||
{:tags ["Report"] | |||||
:post {:summary "Parse the results of the quartet-rnaseq-qc app and generate the report." | |||||
:parameters {:body quartet-rna-report-params-body} | |||||
:responses {201 {:body {:results string? :log string? :report string? :id string?}}} | |||||
:handler (fn [{{{:keys [name description project_id filepath metadata parameters]} :body} :parameters}] | |||||
(let [workdir (get-workdir) | |||||
from-path (u/replace-path filepath workdir) | |||||
uuid (u/uuid) | |||||
relative-dir (fs-lib/join-paths "download" uuid) | |||||
to-dir (fs-lib/join-paths workdir relative-dir) | |||||
log-path (fs-lib/join-paths to-dir "log")] | |||||
(fs-lib/create-directories! to-dir) | |||||
(spit log-path (json/write-str {:status "Running" :msg ""})) | |||||
(events/publish-event! :quartet_rnaseq_report-convert | |||||
{:datadir from-path | |||||
:parameters parameters | |||||
:metadata metadata | |||||
:dest-dir to-dir}) | |||||
(db-handler/create-report! {:id (u/uuid) | |||||
:report_name name | |||||
:project_id project_id | |||||
:app_name "quartet_rnaseq_report" | |||||
:description description | |||||
:report_path (fs-lib/join-paths relative-dir "multiqc.html") | |||||
:started_time (u/time->int (u/now)) | |||||
:finished_time nil | |||||
:archived_time nil | |||||
:report_type "multireport" | |||||
:status "Started" | |||||
:log (fs-lib/join-paths relative-dir "log")}) | |||||
{:status 201 | |||||
:body {:results (fs-lib/join-paths relative-dir) | |||||
:report (fs-lib/join-paths relative-dir "multiqc_report.html") | |||||
:log (fs-lib/join-paths relative-dir "log") | |||||
:id uuid}}))} | |||||
:get {:summary "A json shema for quartet-rnaseq-report." | |||||
:parameters {} | |||||
:responses {200 {:body map?}} | |||||
:handler (fn [_] | |||||
{:status 200 | |||||
:body (json-schema/transform quartet-rna-report-params-body)})}}] | |||||
:manifest {:description "Parse the results of the quartet-rna-qc app and generate the report." | |||||
:category "Report" | |||||
:home "https://github.com/clinico-omics/quartet-rnaseq-report" | |||||
:name "Quartet RNA-Seq Report" | |||||
:source "PGx" | |||||
:short_name "quartet-rnaseq-report" | |||||
:icons [{:src "", :type "image/png", :sizes "192x192"} | |||||
{:src "", :type "image/png", :sizes "192x192"}] | |||||
:author "Jun Shang" | |||||
:hidden false | |||||
:id "f65d87fd3dd2213d91bb15900ba57c11" | |||||
:app_name "shangjun/quartet-rnaseq-report"}}) | |||||
(def ^:const quartet-rnaseq-report-topics | |||||
"The `Set` of event topics which are subscribed to for use in quartet-rnaseq-report tracking." | |||||
#{:quartet_rnaseq_report-convert}) | |||||
(def ^:private quartet-rnaseq-report-channel | |||||
"Channel for receiving event quartet-rnaseq-report we want to subscribe to for quartet-rnaseq-report events." | |||||
(async/chan)) | |||||
(make-plugin-metadata | |||||
{:name "quartet-rnaseq-report" | |||||
:summary "Generate the QC Report for Quartet RNA-Seq data." | |||||
:params-schema quartet-rna-report-params-body | |||||
:handler (fn [{:keys [name description filepath metadata parameters] :as payload}] | |||||
(let [workdir (ff/get-workdir) | |||||
report-file (fs-lib/join-paths workdir "multireport.html") | |||||
log-path (fs-lib/join-paths workdir "log") | |||||
response {:report report-file | |||||
:log log-path | |||||
:response-type :data2report} | |||||
task-id (create-task! {:name name | |||||
:description (or description "Generate the QC Report for Quartet RNA-Seq data.") | |||||
:payload payload | |||||
:plugin-name "quartet-rnaseq-report" | |||||
:plugin-type "ReportPlugin" | |||||
:plugin-version "v0.1.0" | |||||
:response response})] | |||||
(fs-lib/create-directories! workdir) | |||||
(spit log-path (json/write-str {:status "Running" :msg ""})) | |||||
(update-process! task-id 0) | |||||
(publish-event! "quartet_rnaseq_report" | |||||
{:data-dir filepath | |||||
:parameters parameters | |||||
:metadata metadata | |||||
:dest-dir workdir | |||||
:task-id task-id}) | |||||
response)) | |||||
:plugin-type :ReportPlugin | |||||
:response-type :data2report})) | |||||
;;; ------------------------------------------------ Event Processing ------------------------------------------------ | ;;; ------------------------------------------------ Event Processing ------------------------------------------------ | ||||
(defn- decompression-tar | (defn- decompression-tar | ||||
[filepath] | [filepath] | ||||
(shell/with-sh-env {:PATH (get-path-variable) | |||||
(shell/with-sh-env {:PATH (add-env-to-path "quartet-rnaseq-report") | |||||
:LC_ALL "en_US.utf-8" | :LC_ALL "en_US.utf-8" | ||||
:LANG "en_US.utf-8"} | :LANG "en_US.utf-8"} | ||||
(let [command ["bash" "-c" | (let [command ["bash" "-c" | ||||
(defn- filter-mkdir-copy | (defn- filter-mkdir-copy | ||||
[fmc-datadir fmc-patterns fmc-destdir fmc-newdir] | [fmc-datadir fmc-patterns fmc-destdir fmc-newdir] | ||||
(let [files-keep (ff/batch-filter-files fmc-datadir fmc-patterns) | |||||
(let [files-keep (fs-api/batch-filter-files fmc-datadir fmc-patterns) | |||||
files-keep-dir (fs-lib/join-paths fmc-destdir fmc-newdir)] | files-keep-dir (fs-lib/join-paths fmc-destdir fmc-newdir)] | ||||
(fs-lib/create-directories! files-keep-dir) | (fs-lib/create-directories! files-keep-dir) | ||||
(ff/copy-files! files-keep files-keep-dir {:replace-existing true}))) | |||||
(defn- extract-config-file | |||||
[filename dest-path] | |||||
(when (io/resource filename) | |||||
(files/with-open-path-to-resource [filepath filename] | |||||
(files/copy-files! filepath dest-path)))) | |||||
(fs-api/copy-files! files-keep files-keep-dir {:replace-existing true}))) | |||||
(defn- quartet-rnaseq-report! | (defn- quartet-rnaseq-report! | ||||
"Chaining Pipeline: filter-files -> copy-files -> merge_exp_file -> exp2qcdt -> multiqc." | "Chaining Pipeline: filter-files -> copy-files -> merge_exp_file -> exp2qcdt -> multiqc." | ||||
[datadir parameters metadata dest-dir] | |||||
[datadir parameters metadata dest-dir task-id] | |||||
(log/info "Generate quartet rnaseq report: " datadir parameters metadata dest-dir) | (log/info "Generate quartet rnaseq report: " datadir parameters metadata dest-dir) | ||||
(let [metadata-file (fs-lib/join-paths dest-dir | (let [metadata-file (fs-lib/join-paths dest-dir | ||||
"results" | "results" | ||||
(filter-mkdir-copy datadir [".*call-qualimapRNAseq/.*tar.gz"] dest-dir "results/post_alignment_qc/rnaseq_qc") | (filter-mkdir-copy datadir [".*call-qualimapRNAseq/.*tar.gz"] dest-dir "results/post_alignment_qc/rnaseq_qc") | ||||
(filter-mkdir-copy datadir [".*call-fastqc/.*.zip"] dest-dir "results/rawqc/fastqc") | (filter-mkdir-copy datadir [".*call-fastqc/.*.zip"] dest-dir "results/rawqc/fastqc") | ||||
(filter-mkdir-copy datadir [".*call-fastqscreen/.*.txt"] dest-dir "results/rawqc/fastq_screen") | (filter-mkdir-copy datadir [".*call-fastqscreen/.*.txt"] dest-dir "results/rawqc/fastq_screen") | ||||
(me/merge-exp-files! (ff/list-files ballgown-dir {:mode "file"}) exp-fpkm-filepath) | |||||
(me/merge-exp-files! (ff/list-files count-dir {:mode "file"}) exp-count-filepath) | |||||
(update-process! task-id 10) | |||||
(me/merge-exp-files! (fs-api/list-files ballgown-dir {:mode "file"}) exp-fpkm-filepath) | |||||
(me/merge-exp-files! (fs-api/list-files count-dir {:mode "file"}) exp-count-filepath) | |||||
(spit parameters-file (json/write-str parameters)) | (spit parameters-file (json/write-str parameters)) | ||||
(comm/write-csv! metadata-file metadata) | |||||
(write-csv! metadata-file metadata) | |||||
;;(decompression-tar files-qualimap-bam) | ;;(decompression-tar files-qualimap-bam) | ||||
;;(decompression-tar files-qualimap-RNA) | ;;(decompression-tar files-qualimap-RNA) | ||||
(doseq [files-qualimap-bam-tar (ff/batch-filter-files (fs-lib/join-paths dest-dir "results/post_alignment_qc/bam_qc") [".*tar.gz"])] | |||||
(doseq [files-qualimap-bam-tar (fs-api/batch-filter-files (fs-lib/join-paths dest-dir "results/post_alignment_qc/bam_qc") [".*tar.gz"])] | |||||
(decompression-tar files-qualimap-bam-tar)) | (decompression-tar files-qualimap-bam-tar)) | ||||
(doseq [files-qualimap-RNA-tar (ff/batch-filter-files (fs-lib/join-paths dest-dir "results/post_alignment_qc/rnaseq_qc") [".*tar.gz"])] | |||||
(doseq [files-qualimap-RNA-tar (fs-api/batch-filter-files (fs-lib/join-paths dest-dir "results/post_alignment_qc/rnaseq_qc") [".*tar.gz"])] | |||||
(decompression-tar files-qualimap-RNA-tar)) | (decompression-tar files-qualimap-RNA-tar)) | ||||
(extract-config-file "quartet_rnaseq_report.yaml" config-path) | |||||
(update-process! task-id 50) | |||||
(gen-multiqc-config config-path) | |||||
(let [exp2qcdt-result (exp2qcdt/call-exp2qcdt! exp-fpkm-filepath exp-count-filepath metadata-file result-dir) | (let [exp2qcdt-result (exp2qcdt/call-exp2qcdt! exp-fpkm-filepath exp-count-filepath metadata-file result-dir) | ||||
multiqc-result (if (= (:status exp2qcdt-result) "Success") | multiqc-result (if (= (:status exp2qcdt-result) "Success") | ||||
(mq/multiqc result-dir dest-dir {:config config-path :template "default" :title "Quartet RNA report"}) | (mq/multiqc result-dir dest-dir {:config config-path :template "default" :title "Quartet RNA report"}) | ||||
log (json/write-str result)] | log (json/write-str result)] | ||||
(log/info "Status: " result) | (log/info "Status: " result) | ||||
(spit log-path log)) | (spit log-path log)) | ||||
(update-process! task-id 100) | |||||
(catch Exception e | (catch Exception e | ||||
(update-process! task-id -1) | |||||
(let [log (json/write-str {:status "Error" :msg (.toString e)})] | (let [log (json/write-str {:status "Error" :msg (.toString e)})] | ||||
(log/info "Status: " log) | (log/info "Status: " log) | ||||
(spit log-path log)))))) | (spit log-path log)))))) | ||||
(defn- process-quartet-rnaseq-report-event! | |||||
"Handle processing for a single event notification received on the quartet-rnaseq-report-channel" | |||||
[quartet-rnaseq-report-event] | |||||
;; try/catch here to prevent individual topic processing exceptions from bubbling up. better to handle them here. | |||||
(try | |||||
(when-let [{topic :topic object :item} quartet-rnaseq-report-event] | |||||
;; TODO: only if the definition changed?? | |||||
(case (events/topic->model topic) | |||||
"quartet_rnaseq_report" (quartet-rnaseq-report! (:datadir object) (:parameters object) (:metadata object) (:dest-dir object)))) | |||||
(catch Throwable e | |||||
(log/warn (format "Failed to process quartet-rnaseq-report event. %s" (:topic quartet-rnaseq-report-event)) e)))) | |||||
;;; --------------------------------------------------- Lifecycle ---------------------------------------------------- | ;;; --------------------------------------------------- Lifecycle ---------------------------------------------------- | ||||
(defn events-init | |||||
"Automatically called during startup; start event listener for quartet-rnaseq-report events." | |||||
[] | |||||
(events/start-event-listener! quartet-rnaseq-report-topics quartet-rnaseq-report-channel process-quartet-rnaseq-report-event!)) | |||||
(def events-init | |||||
"Automatically called during startup; start event listener for quartet_rnaseq_report events." | |||||
(make-events-init "quartet_rnaseq_report" quartet-rnaseq-report!)) |
(ns tservice.plugins.quartet-rnaseq-report.exp2qcdt | (ns tservice.plugins.quartet-rnaseq-report.exp2qcdt | ||||
"A wrapper for exp2qcdt tool." | "A wrapper for exp2qcdt tool." | ||||
(:require [tservice.lib.commons :refer [get-path-variable]] | |||||
[tservice.config :refer [get-plugin-dir]] | |||||
[tservice.lib.fs :as fs] | |||||
(:require [tservice.api.config :refer [add-env-to-path]] | |||||
[clojure.java.shell :as shell :refer [sh]])) | [clojure.java.shell :as shell :refer [sh]])) | ||||
(defn add-env-to-path | |||||
"Add the path of the plugin's environment into the PATH and return the PATH" | |||||
[] | |||||
(let [env-bin-path (fs/join-paths (get-plugin-dir) "plugins" "repository" "quartet-rnaseq-report" "bin") | |||||
path (get-path-variable)] | |||||
(str env-bin-path ":" path))) | |||||
(defn call-exp2qcdt! | (defn call-exp2qcdt! | ||||
"Call exp2qcdt bash script. | "Call exp2qcdt bash script. | ||||
exp-file: FPKM file , each row is the expression values of a gene and each column is a library. | exp-file: FPKM file , each row is the expression values of a gene and each column is a library. | ||||
result-dir: A directory for result files. | result-dir: A directory for result files. | ||||
" | " | ||||
[exp-file cnt-file meta-file result-dir] | [exp-file cnt-file meta-file result-dir] | ||||
(shell/with-sh-env {:PATH (add-env-to-path) | |||||
(shell/with-sh-env {:PATH (add-env-to-path "quartet-rnaseq-report") | |||||
:LC_ALL "en_US.utf-8" | :LC_ALL "en_US.utf-8" | ||||
:LANG "en_US.utf-8"} | :LANG "en_US.utf-8"} | ||||
(let [command ["bash" "-c" | (let [command ["bash" "-c" |
(ns tservice.plugins.quartet-rnaseq-report.merge-exp | (ns tservice.plugins.quartet-rnaseq-report.merge-exp | ||||
"Merge expression files." | "Merge expression files." | ||||
(:require [tservice.lib.commons :refer [read-csv write-csv! vec-remove write-csv-by-cols!]])) | |||||
(:require [tservice.api.data.csv :refer [read-csv vec-remove write-csv-by-cols!]])) | |||||
(set! *warn-on-reflection* true) | (set! *warn-on-reflection* true) | ||||
(ns tservice.plugins.quartet-rnaseq-report.util | |||||
(:require [clj-yaml.core :as yaml])) | |||||
(defn gen-multiqc-config | |||||
[config-file] | |||||
(let [config (yaml/generate-string | |||||
{:run_modules ["rnaseq_data_generation_information" | |||||
"rnaseq_performance_assessment" | |||||
"rnaseq_raw_qc" | |||||
"rnaseq_post_alignment_qc" | |||||
"rnaseq_quantification_qc" | |||||
"rnaseq_supplementary"] | |||||
:skip_generalstats true} | |||||
:dumper-options {:flow-style :block})] | |||||
(spit config-file config))) |