---
title: "`r batch_title`"
subtitle: "Assemblycomparator2 Report"
date: "`r Sys.time()`"
output:
  html_document:
    toc: true
    toc_depth: 2
  #prettydoc::html_pretty:
    theme: flatly
    #highlight: github
    center: false
editor_options: 
  chunk_output_type: console
#css: "max-width: 5000px; margin: auto; padding: 1em; line-height: 20px"
---
<style>

.main-container {
    margin-left: 60px; /* was auto */
    margin-top: 37px; /* was 0 */
}

table {
  white-space: nowrap; /* Do not wrap table cell contents. */
}

/* Use serif fonts for text. Not in tables. */
p {
    color: black;
    font-family: Georgia,"Times New Roman",Times,serif;
    font-size: 16px;
}


.shaded {
    color: #929292;
}

</style>

```{r setu3p-dependencies, echo=F, message=F, warning=F}
varbi=32
```


```{r setup-dependencies, echo=F, message=F, warning=F}

# Dependencies

library(tidyverse)
library(DT)
library(ape)
#library(gridExtra) # Not sure if I'm still using this? Think it was only the checkm2 figure.

# I failed trying looking for a package that would robustly midpoint root the tree.
#library(prettydoc) # Rmarkdown themes?
#library(phytools)
#library(phangorn)



```




```{r setup-debug, echo=F, message=F, warning=F, error = F}



# DEBUG setup for vscode on KTFL running R on ssh to saga
debug = F
if (debug) {
    # strachan_campylo on threadripper through posit workbench
    # strachan_campylo on threadripper
    base_variable = "~/evo/asscom2"
    results_directory = "results_ac2"
    setwd("~/asscom2/tests/strachan_campylo")
    setwd("~/evo/asscom2/tests/MAGs/")
    
    batch_title = basename(getwd())
    
    # strachan_campylo on threadripper
    base_variable = "~/asscom2"
    results_directory = "results_ac2"
    setwd("~/asscom2/tests/strachan_campylo")
    batch_title = basename(getwd())


    # E._faecium_30 on thylakoid
    base_variable = "~/assemblycomparator2"
    results_directory = "results_ac2"
    setwd("~/assemblycomparator2/tests/E._faecium_30")
    batch_title = basename(getwd())

    # MAGs on thylakoid
    base_variable = "~/assemblycomparator2"
    results_directory = "results_ac2"
    setwd("~/assemblycomparator2/tests/MAGs")
    batch_title = basename(getwd())

    # MAGs on axodines
    base_variable = "~/axodines/assemblycomparator2"
    results_directory = "results_ac2"
    setwd("~/axodines/assemblycomparator2/tests/MAGs")
    batch_title = basename(getwd())

    # synth rumen on axodines
    base_variable = "~/axodines/assemblycomparator2"
    results_directory = "results_ac2"
    setwd("~/axodines/assemblycomparator2/tests/synth_rumen")
    batch_title = basename(getwd())
    
    
    # synth rumen copied to local
    base_variable = "~/assemblycomparator2"
    results_directory = "results_ac2"
    setwd("~/assemblycomparator2/tests/synth_rumen")
    batch_title = basename(getwd())
    
    # strachans on macbook
    base_variable = "~/assemblycomparator2"
    results_directory = "results_ac2"
    setwd("~/assemblycomparator2/tests/strachan_campylo")
    batch_title = basename(getwd())
    
    # student bins on macbook
    base_variable = "~/assemblycomparator2"
    results_directory = "results_ac2"
    setwd("~/assemblycomparator2/tests/student")
    batch_title = basename(getwd())
    
}

```


`r paste0("This report was generated using the results located at ", results_directory, " using the installation at ", base_variable, ".")`


```{r setup-globals, echo=F, message=F, warning=F}


## Global variables
#base_variable = "~/assemblycomparator2/" # I need to find a way of pulling this out of thin air. Maybe there's a way of passing commands through the render call, or I can
report_scripts = paste0(base_variable, "/report_subpipeline/scripts/")




## Global functions

# A function that returns a new global table enumerator for each call
tableno_var = 0
tableno = function() {
    tableno_var <<- tableno_var + 1
    tableno_var
}

# Same, but for figures
figno_var = 0
figno = function() {
    figno_var <<- figno_var + 1
    figno_var
}

custom_dt = function(x, filename = "viewer_", dom = "Blfrtip", ordering = T, width = NULL, show_n = 10) {
    
    name = paste(batch_title, filename, sep = "__")
    
    write_tsv(x, paste0(results_directory, "/tables/", name, ".tsv")) # Save a copy on the harddisk for people without browsers.
    
    DT::datatable(
        x,
        options = list(
            dom = dom,
            ordering = ordering,
            #buttons = c('copy', 'csv', 'excel')
            buttons = list(
                list(extend = "csv", filename = name),
                list(extend = "excel", filename = name)
            ),
            lengthMenu = list(
                c(show_n ,25, 50, -1),
                c(show_n ,25, 50, "All")
            )
        ),
        rownames = F,
        width = width,
        extensions = 'Buttons',

    )
}




```


## Samples

```{r sample-overview, echo=FALSE, message=F, warning=F, error = T}

# Import the metadata table
# metadata_translate makes it easy for us later to convert the long paths to short and simple sample names, also highlights potential missing sample analyses

metadata_file = paste0(results_directory, "/metadata.tsv")

metadata_df = read_tsv(metadata_file) %>%
    arrange(sample)  # Alphabetical

N = metadata_df %>% nrow() # Global variable.

# Generate a very simple table which can be used to convert long paths or their basenames to sample names
metadata_translate_lexicographic = metadata_df %>% 
    select(sample, file_long = input_file_fasta) %>%
    mutate(
        file = basename(file_long),
        index = 1:n() # Using a numerical index is so much easier I think.
        #index = n():1 # Using a numerical index is so much easier I think. Since the tree is drawn from the bottom we should reverse the direction of the index.
        
    ) %>% 
    relocate(index)

ARRANGEMENT = "lexicographic" # Global variable.

# If mashtree has been run, we might as well order the samples by the order of the tree. This is of course only a luxury, and not a dependency. In case the user has trouble running mashtree -which is unlikely- it is great to have a workaround which is to use the alphabetical order which is already defined above.

mashtree_voluntary_dependency = paste0(results_directory, "/mashtree/mashtree.newick")
if (file.exists(mashtree_voluntary_dependency)) {
    
    # Overwrite metadata_translate in case the newick file from mashtree exists.
    # But 
    metadata_translate = read_lines(mashtree_voluntary_dependency) %>% 
        str_split(",") %>% unlist() %>% 
        str_remove("^\\(+") %>% # Remove head
        str_remove("\\:.+$")  %>% # Remove tail
        enframe(name = "index", value = "sample") %>% 
        mutate(index = rev(index)) %>%
        arrange(index) %>% 
        
        left_join(metadata_translate_lexicographic %>% select(-index), by = "sample") # add metadata_translate without its lexicographic index.
    
    ARRANGEMENT = "phylogenetic"
        
} else { # In case mashtree didn't succeed (for instance, if one file is not a genome and thus crashes mashtree), we want to continue with a simple lexicographic ordering of the samples.
    metadata_translate = metadata_translate_lexicographic
}



    
if(ARRANGEMENT == "lexicographic") {
    arrangement_text = "Because mashtree has not run (successfully), the samples are arranged alphabetically." # Lexicographically sounds so nerdy.
} else { # == "phylogenetic"
    arrangement_text = "Because mashtree has run, the samples are arranged by the order of the mashtree output."
}


# Present the metadata in the report
metadata_translate  %>% 
    select(index, sample, file) %>% 
    custom_dt("samples")

    


### Sections below
```

*Table `r tableno()`: Overview of the samples analysed in this batch. `r paste(arrangement_text)`*


### Report sections

Here is an overview of the number of result files that have been found for each analysis. A report section is only rendered if relevant result files are present for that analysis. Each section can be triggered to run by calling assemblycomparator2 with a trailing `--until <section>`

```{r sample-switchboard, echo=FALSE, message=F, warning=F, error = T}

# Pull all globs and show which are done/presentable

# glob = list()

# glob$assembly_stats = Sys.glob(paste0(results_directory, "/assembly-stats/assembly-stats.tsv"))
# glob$prokka = Sys.glob(paste0(results_directory, "/samples/*/prokka/*.txt"))
# glob$busco = Sys.glob(paste0(results_directory, "/samples/*/busco/*_omesnatoehsnatoe_extract.tsv"))

# Each section of this report is rendered on the basis of the presence of relevant result files.
# In the table below, the globs, and expected number of globs are defined. 
section_definition_table = tribble(

    ~section,            ~expectation,                         ~glob,

    "assembly_stats",    1, Sys.glob(paste0(results_directory, "/assembly-stats/assembly-stats.tsv")),
    "sequence_lengths",  N, Sys.glob(paste0(results_directory, "/samples/*/sequence_lengths/*.tsv")),
    "busco",             N, Sys.glob(paste0(results_directory, "/samples/*/busco/short_summary_extract.tsv")),
    "checkm2",           1, Sys.glob(paste0(results_directory, "/checkm2/quality_report.tsv")),
    "gtdbtk",            1, Sys.glob(paste0(results_directory, "/gtdbtk/gtdbtk.summary.tsv")),
    "mlst",              1, Sys.glob(paste0(results_directory, "/mlst/mlst.tsv")),
    "abricate",          4, Sys.glob(
        c(
            paste0(results_directory, "/abricate/ncbi_detailed.tsv"),
            paste0(results_directory, "/abricate/card_detailed.tsv"),
            paste0(results_directory, "/abricate/plasmidfinder_detailed.tsv"),
            paste0(results_directory, "/abricate/vfdb_detailed.tsv")
        )
    ),
    "prokka",            N, Sys.glob(paste0(results_directory, "/samples/*/prokka/*.txt")),
    "kegg_pathway",      1, Sys.glob(paste0(results_directory, "/kegg_pathway/kegg_pathway_enrichment_analysis.tsv")),
    "dbcan",             N, Sys.glob(paste0(results_directory, "/samples/*/dbcan/dbcan-sub.hmm.out")),
    "roary",             1, Sys.glob(paste0(results_directory, "/roary/gene_presence_absence.Rtab")), # This also counts for the roary summary file.
    "snp_dists",         1, Sys.glob(paste0(results_directory, "/snp-dists/snp-dists.tsv")),
    "mashtree",          1, Sys.glob(mashtree_voluntary_dependency) # Reuse from earlier.
    
    ) %>%
    mutate(n_files = lengths(glob))






# This list is used out in the individual sections to access the correct files.
glob_list = section_definition_table %>%
    select(section, glob) %>%
    deframe() # Convert to list

# The render variable is finally used to toggle the rendering of each section in the report.
render = lapply(glob_list, function(x) {length(x) > 0}) # Anything more than one file, will trigger the rendering.


section_definition_table %>%
    mutate(
        render = case_when(
            n_files > expectation ~ "🟢 yes, extra", # This should only happen if samples are deleted from the input directory. But isn't a problem as we're left joining onto the metadata table.
            n_files == expectation ~ "🟢 yes",
            n_files > 0 ~ "🟡 yes, partially",
            n_files == 0 ~ "🟠 no"),
        `n / expected` = paste0(n_files, " / ", expectation)
    ) %>%
    select(section, `n / expected`, render) %>%
    custom_dt("sections", dom = "t", ordering = F, width = 500, show_n = nrow(section_definition_table))
    #custom_dt("sections", ordering = F, width = 500)

# Define a variable that can be used to query whether each section of the report should be rendered


# By the way: Remember to have double new lines between the dash-lines (---) and the r child chunks. Otherwise the parsing gets weird, with figure texts becoming headers.

```


*Table `r tableno()`: Overview of sections that are rendered in this report. "n / expected" shows the number of analysis files versus how many are expected to be present. Sections are only rendered if relevant files exist. Analyses that perform comparisons between samples generally only output one set of results independent on the number of input files*



---



```{r section_assembly_stats, child = paste0(report_scripts, "section_assembly_stats.rmd"), eval = render$assembly_stats}
```

```{r section_sequence_lengths, child = paste0(report_scripts, "section_sequence_lengths.rmd"), eval = render$sequence_lengths}
```

```{r section_busco, child = paste0(report_scripts, "section_busco.rmd"), eval = render$busco}
```

```{r section_checkm2, child = paste0(report_scripts, "section_checkm2.rmd"), eval = render$checkm2}
```

```{r section_gtdbtk, child = paste0(report_scripts, "section_gtdbtk.rmd"), eval = render$gtdbtk}
```

```{r section_mlst, child = paste0(report_scripts, "section_mlst.rmd"), eval = render$mlst}
```

```{r section_abricate, child = paste0(report_scripts, "section_abricate.rmd"), eval = render$abricate}
```

```{r section_prokka, child = paste0(report_scripts, "section_prokka.rmd"), eval = render$prokka}
```

```{r section_kegg_pathway, child = paste0(report_scripts, "section_kegg_pathway.rmd"), eval = render$kegg_pathway}
```

```{r section_dbcan, child = paste0(report_scripts, "section_dbcan.rmd"), eval = render$dbcan}
```

```{r section_roary, child = paste0(report_scripts, "section_roary.rmd"), eval = render$roary}
```

```{r section_snp_dists, child = paste0(report_scripts, "section_snp_dists.rmd"), eval = render$snp_dists}
```

```{r section_mashtree, child = paste0(report_scripts, "section_mashtree.rmd"), eval = render$mashtree}
```

















<p class = "shaded">[assemblycomparator2 v`r version_string`](https://github.com/cmkobel/assemblycomparator2#assemblycomparator2) genomes to report pipeline. Copyright (C) 2019-2024 [Carl M. Kobel](https://github.com/cmkobel) [GNU GPL v3](https://github.com/cmkobel/assemblycomparator2/blob/master/LICENSE)</p>

