---
title: "AQUAMIS QC report"
date: "Last updated on `r format(Sys.time(), '%d %B, %Y')`"
output: html_document
theme: default
---

<style type="text/css">
.main-container {
max-width: 2400px;
margin-left: auto;
margin-right: auto;
}
</style>

```{r setup, include = FALSE}

knitr::opts_chunk$set(out.width = '80%',
                      fig.asp= 0.5,
                      fig.align='center',
                      echo = FALSE,
                      warning = FALSE,
                      message = FALSE)
options(markdown.HTML.header = system.file("misc", "datatables.html", package = "knitr"))

library(tidyverse, quietly = T)
library(rrapply, quietly = T)
library(urltools, quietly = T)
library(DT, quietly = T)

executor <- Sys.info()["user"]

```

---
author: `r paste0(executor)`
---

```{r HelperFunctions, echo = FALSE}

currentScript <- function() {
  .getSourcedScriptName <- function() {
    for (i in sys.nframe():1) {
      x <- sys.frame(i)$ofile
      if (!is.null(x)) {return(normalizePath(x))}
    }
  }
  if (is.null(.getSourcedScriptName())) {
    return(normalizePath(rstudioapi::getActiveDocumentContext()$path))
  } else {
    .getSourcedScriptName()
  }
}

```


```{r  DEBUG: Override Snakemake, echo = FALSE}

if (!exists("snakemake")) {
  source(file = file.path(dirname(currentScript()), gsub("\\.Rmd", "_debug.R", basename(currentScript()))))
} else {
  # Activate Logging
  logfile <- file(snakemake@log[["log"]], open = "wt")
  sink(file = logfile, type = c("output", "message"))
}

```


```{r Import Sample JSONs and Deserialize, echo = FALSE}

setwd(dir = snakemake@config$workdir)

samples <- gsub(pattern = "(.*)\\.json$", replacement = "\\1", basename(snakemake@input$json_in))

json_sample_str <- purrr::set_names(
  x = purrr::map(snakemake@input$json_in,
                 function(.x)readr::read_file(file = .x)),
  nm = samples)

json_sample_obj <- purrr::set_names(
  x = purrr::map(json_sample_str,
                 function(.x)jsonlite::fromJSON(
                   txt = .x,
                   simplifyVector = TRUE,
                   simplifyDataFrame = TRUE,
                   simplifyMatrix = TRUE,
                   flatten = FALSE)) %>%
    rrapply::rrapply(object = .,
                     classes = c("list", "data.frame"),
                     f = function(.x) {
                       if (!is_null(names(.x))) {names(.x) <- urltools::url_decode(names(.x))}
                       return(.x)
                     },
                     how = "recurse") %>%
    rrapply::rrapply(object = .,  # this eliminates NULL fields and mitigates conversion errors into data.frames, this error only happens in R v3.5.1
                     classes = "NULL",
                     f = function(.x) if (is_null(.x)) {.x <- NA},
                     how = "recurse"),
  nm = names(json_sample_str))

```


```{r fastp_table, echo = FALSE}

fastp_table <- purrr::map_dfr(.x = json_sample_obj,
                              .f = function(.x)purrr::pluck(.x = .x, "pipelines", "fastp", "summary", "before_filtering"),
                              .id = "sample") %>%
  select(sample, total_reads, total_bases) %>% 
  rename(total_reads_before = "total_reads",
         total_bases_before = "total_bases") %>% 
  left_join(x = .,
            y = purrr::map_dfr(.x = json_sample_obj,
                               .f = function(.x)purrr::pluck(.x = .x, "pipelines", "fastp", "summary", "after_filtering"),
                               .id = "sample") %>% 
              select(sample, total_reads, total_bases, q20_rate, q30_rate) %>% 
              rename(total_reads_after = "total_reads",
                     total_bases_after = "total_bases",
                     q20_rate_after = "q20_rate",
                     q30_rate_after = "q30_rate"),
            by = c("sample" = "sample")) %>% 
  left_join(x = .,
            y = purrr::map(.x = json_sample_obj,
                           .f = function(.x)purrr::pluck(.x = .x, "pipelines", "fastp", "duplication", "rate")) %>% 
              tibble::enframe() %>%
              tidyr::unnest(cols = c(value)) %>% 
              rename(sample = "name",
                     duplication_rate = "value"),
            by = c("sample" = "sample")) %>% 
  left_join(x = .,
            y = purrr::map(.x = json_sample_obj,
                           .f = function(.x)purrr::pluck(.x = .x, "pipelines", "fastp", "insert_size", "peak")) %>% 
              tibble::enframe() %>%
              tidyr::unnest(cols = c(value)) %>% 
              rename(sample = "name",
                     insert_size_peak = "value"),
            by = c("sample" = "sample")) %>% 
  mutate(link_to_report = purrr::map_chr(.x = sample,
                                         .f = function(.x)paste0("<a href=",
                                                                 file.path("..", "trimmed", "reports", paste0(.x, ".html")),
                                                                 "> QC report </a>")))

```


```{r confindr_table, echo = FALSE}

confindr_table <- json_sample_obj %>%
  purrr::map_dfr(.x = .,
                 .f = function(.x)purrr::pluck(.x = .x, "pipelines", "confindr"),
                 .id = NULL) %>% 
  select(-version)

```


```{r bracken_table, echo = FALSE}

# read kraken2 data - parsing either on species or genus level depends on user choice in config.yaml, default is genus
kraken_taxon_ranks = c(
  "K" = "kingdom",  # NOTE: Currently, only genus and species are supported
  "P" = "phylum",
  "C" = "class",
  "O" = "order",
  "F" = "family",
  "G" = "genus",
  "S" = "species"
)
taxon_qc_level <- as.character(kraken_taxon_ranks[snakemake@config$params$kraken2$taxonomic_qc_level])

kraken2_reads_species <- json_sample_obj %>%
  purrr::map(.x = .,
             .f = function(.x)purrr::pluck(.x = .x, "pipelines", "kraken2", "read_based", "bracken_summary_species") %>%
               as_tibble() %>%
               {if (names(.)[[1]] == .[1, 1, drop = TRUE]) slice(.data = ., -1) else .} %>% # failsafe if first row is not a duplicate of column names
               arrange(desc(fraction_total_reads)) %>% 
               slice_head(n = 3)) %>%
  bind_rows(., .id = "sample") %>% 
  select(sample, name, fraction_total_reads) %>% 
  group_by(sample) %>% 
  mutate(rank_name = paste0("read_hit", row_number(), "_species"),
         rank_fraction = paste0("read_hit", row_number(), "_species_fraction")) %>% 
  pivot_longer(cols = c(name, fraction_total_reads), names_to = "key", values_to = "value") %>% 
  mutate(key = ifelse(test = key == "name", yes = rank_name, no = rank_fraction)) %>% 
  pivot_wider(id_cols = sample, names_from = key, values_from = value) %>% 
  mutate_at(.vars = vars(ends_with("_fraction")), .funs = ~ as.double(.))

kraken2_reads_genus <- json_sample_obj %>%
  purrr::map(.x = .,
             .f = function(.x)purrr::pluck(.x = .x, "pipelines", "kraken2", "read_based", "bracken_summary_genus") %>%
               as_tibble() %>%
               {if (names(.)[[1]] == .[1, 1, drop = TRUE]) slice(.data = ., -1) else .} %>% # failsafe if first row is not a duplicate of column names
               arrange(desc(fraction_total_reads)) %>% 
               slice_head(n = 3)) %>%
  bind_rows(., .id = "sample") %>% 
  select(sample, name, fraction_total_reads) %>% 
  group_by(sample) %>% 
  mutate(rank_name = paste0("read_hit", row_number(), "_genus"),
         rank_fraction = paste0("read_hit", row_number(), "_genus_fraction")) %>% 
  pivot_longer(cols = c(name, fraction_total_reads), names_to = "key", values_to = "value") %>% 
  mutate(key = ifelse(test = key == "name", yes = rank_name, no = rank_fraction)) %>% 
  pivot_wider(id_cols = sample, names_from = key, values_from = value) %>% 
  mutate_at(.vars = vars(ends_with("_fraction")), .funs = ~ as.double(.))

```


```{r export_tables}

fastp_table %>%
  select(-link_to_report) %>%
  write.table(., file = file.path(snakemake@config$workdir, snakemake@params[["csv_fastp"]]),
              sep = "\t", row.names = FALSE)

confindr_table %>%
  select(-timestamp) %>%
  write.table(., file = file.path(snakemake@config$workdir, snakemake@params[["csv_confindr"]]),
              sep = ",", row.names = FALSE)

get(x = paste0("kraken2_reads_", taxon_qc_level))  %>%
  write.table(., file = file.path(snakemake@config$workdir, snakemake@params[["csv_bracken"]]),
              sep = "\t", row.names = FALSE)

```


```{r output, echo = FALSE}

DT::datatable(fastp_table,
              filter = 'top',
              rownames= FALSE,
              escape = FALSE,
              extensions = list("ColReorder" = NULL,
                                "Buttons" = NULL,
                                "FixedColumns" = list(leftColumns = 1)),
              options = list(
                dom = 'BRrltpi',
                autoWidth = FALSE,
                scrollX = TRUE,
                fixedColumns = TRUE,
                lengthMenu = list(
                  c(5, 10, 50, -1),
                  c("5", "10", "50", "All")),
                pageLength = 10,
                ColReorder = TRUE,
                searchHighlight = TRUE,
                scrollCollapse = TRUE,
                buttons = list(
                  list(extend = 'copy',
                       title = NULL,
                       exportOptions = list(columns = ":visible")),
                  list(extend = 'print',
                       title = NULL,
                       exportOptions = list(columns = ":visible")),
                  list(text = 'Download',
                       extend = 'collection',
                       title = NULL,
                       buttons = list(list(extend = 'csv',
                                           title = NULL,
                                           exportOptions = list(columns = ":visible")),
                                      list(extend = 'excel',
                                           title = NULL,
                                           exportOptions = list(columns = ":visible")),
                                      list(extend = 'pdf',
                                           title = NULL,
                                           exportOptions = list(columns = ":visible")))),
                  I('colvis'))
              ))

```
