Skip to content
Snippets Groups Projects
app.Rmd 33.9 KiB
Newer Older
---
output: html_document
Todor Kondic's avatar
Todor Kondic committed
runtime: shiny_prerendered
author: Environmental Cheminformatics Group, LCSB, University of Luxembourg
Todor Kondic's avatar
Todor Kondic committed
title: "`r paste('Shinyscreen', packageVersion('shinyscreen'))`"
```{r, context='setup', include='false'}
Todor Kondic's avatar
Todor Kondic committed
library(data.table)
library(shinyscreen)
def_state <- new_state()
def_datafiles <- shinyscreen:::dtable(File=character(0),
                                      tag=character(0))
def_datatab <- shinyscreen:::dtable("tag"=factor(),
                                    "adduct"=factor(levels=shinyscreen:::DISP_ADDUCTS),
                                    "set"=factor())

def_summ_subset <- shinyscreen:::dtable("QA Column"=shinyscreen:::QA_FLAGS,
                                        "Select"=factor("il irrilevante",levels=c("il irrilevante",
                                                                                  "il buono",
                                                                                  "il cattivo")))
Todor Kondic's avatar
Todor Kondic committed
## RMassBank masks shiny::validate. Unmask it.
validate <- shiny::validate
## def_state$input$tab$tags <- def_datatab
rv_state <- list2rev(def_state)
compl_sets <- eventReactive(rv_state$input$tab$setid,
                            rv_state$input$tab$setid[,unique(set)])
## Reactive values to support some of the UI elements.
## rv_ui <- reactiveValues(datatab=def_tags)
Todor Kondic's avatar
Todor Kondic committed
## Update with data-files.
rv_dfiles <- reactiveVal(def_datafiles)

## Data-file table when loading.
rv_datatab <- reactiveVal(def_datatab)



# Configuration {.tabset}

## Inputs


<details>
<summary>Specify the project directory</summary>
This is where the output files and the state of the analysis will be
saved.
</details>
```{r, echo=FALSE}
actionButton(inputId = "project_b",
             label= "Project")

```

Current project directory is `r textOutput("project", inline=T)`

<details><summary>Load the compound list(s)</summary>
A compound list is composed of entries describing compounds. This
description is used to search for its spectrum in the data file. The
list is a table in the ***CSV*** format and contains these columns,

* ***ID*** : required column, must be filled; this is a user-defined
  ID, uniquely associated with a compound
  
* ***Name*** : this column can be left blank; if not, it should contain the
  names of the compounds
  
* ***SMILES*** : a _SMILES_ string, describing the structure of the
  compound; this entry can be left empty only if one of either
  ***Formula***, or ***mz*** entries are not
  
* ***Formula*** : a chemical formula of a compound; this field can be
  empty only if one of either ***SMILES***, or ***mz*** entries are
  not
  
* ***mz*** : mass of the ionised compound; this field can be left
  empty only if one of either ***SMILES***, or ***Formula*** is not
  
* ***CAS*** : the CAS number of the compound; it can be left empty

* ***RT*** : retention time of the MS1 peak in minutes, if known; can
  be left empty.
  
Only ***ID*** and one of ***SMILES***, ***Formula*** or ***mz*** must
be filled. When structure, or a formula of a compound is known, it is
also possible to look for various adducts in the sample. Of course,
scanning for completely unknown compounds is also supported by the
***mz*** column. In this case, ***mz*** is the mass of the ion.

It is strongly recommended to quote SMILES, names and formulas in the
CSV file used with Shinyscreen.
</details>
```{r, echo=FALSE}
actionButton(inputId = "comp_list_b",
             label= "Compound list(s)")

```

`r htmlOutput("comp_lists")`

<details><summary>Load compound set list (_setid_ table)</summary>
The compound lists can contain more entries than is necessary. Using
the _setid_ lists, it is possible to create _compound sets_ which
contain only those compounds that will actually be searched for in the
data files. A _setid table_ is a _CSV_ containing at least two
columns,

* ***ID*** : the ID entry from the compound list

* ***set*** : an user-defined set name.
</details>
```{r, echo=FALSE}
actionButton(inputId = "setid_b",
             label= "Load the setid table")

```

`r htmlOutput("setids", inline=T)`

## Data files
<details><summary>Load data files</summary>
Shinyscreen currently supports only the **mzML** file format. After
loading the files, set file tags in the file table (column
**tag**). Additionally, specify a set of compounds that is supposed
to be extracted from the file using the **set** column. Finally,
specify the **adduct** in the adduct column. In case of compounds
with unknown structure and formula, the adduct is ignored for obvious
reasons.
</details>
```{r, echo=FALSE}
actionButton(inputId = "datafiles_b",
             label= "Load data files.")

```




<details><summary>Assign tags to data files.</summary>
Each tag designates an unique file. Use the table below to assign
tags.
</details>

```{r, echo=FALSE}
rhandsontable::rHandsontableOutput("datafiles")

```




<details><summary>Assign sets to tags.</summary>
For each tag, assign a set and an adduct (if the structure information
exists, otherwise _adduct_ column is ignored).
</details>

```{r, echo=F}
rhandsontable::rHandsontableOutput("datatab")
```

## Extraction

### Spectra extraction based settings

Todor Kondic's avatar
Todor Kondic committed
<details><summary>MS1 coarse error</summary>

Extract all entries matching the target mass within this error in the
precursor table.
</details>
```{r, echo=F}
shinyscreen::mz_input(input_mz = "ms1_coarse",
Todor Kondic's avatar
Todor Kondic committed
                       input_unit = "ms1_coarse_unit",
                       def_mz = def_state$conf$tolerance[["ms1 coarse"]],
                       def_unit = "Da")
Todor Kondic's avatar
Todor Kondic committed
<details><summary>MS1 fine error</summary>

The precursor table masses can be of lower accuracy. Once there is a
match within the coarse error, it can be further checked versus the
fine error bounds directly in the mass spectrum.

</details>
```{r, echo=F}
shinyscreen::mz_input(input_mz = "ms1_fine",
                      input_unit = "ms1_fine_unit",
                      def_mz = def_state$conf$tolerance[["ms1 fine"]],
                      def_unit = "ppm")
```

Todor Kondic's avatar
Todor Kondic committed
<details><summary>MS1 EIC window</summary>

The mz interval over which the intensities are aggregated to generate
a chromatogram.

</details>
```{r, echo=F}
shinyscreen::mz_input(input_mz = "ms1_eic",
                      input_unit = "ms1_eic_unit",
                      def_mz = def_state$conf$tolerance[["eic"]],
                      def_unit = "Da")
```

Todor Kondic's avatar
Todor Kondic committed
<details><summary>Retention time window</summary>

If the expected retention time has been specified for the compound,
then search for the MS1 signature inside the window defined by this
range.

</details>
```{r, echo=F}
shinyscreen::rt_input(input_rt = "ms1_rt_win",
                      input_unit = "ms1_rt_win_unit",
                      def_rt = def_state$conf$tolerance[["rt"]],
                      def_unit = "min")
```

## Prescreening

Todor Kondic's avatar
Todor Kondic committed
<details><summary>MS1 intensity threshold</summary>

Ignore MS1 signal below the threshold.

</details>
```{r, echo=F}

numericInput(inputId = "ms1_int_thresh",
             label = NULL,
             value = def_state$conf$prescreen$ms1_int_thresh)
```

Todor Kondic's avatar
Todor Kondic committed
<details><summary>MS2 intensity threshold</summary>

Ignore MS2 signal below the threshold.

</details>
```{r, echo=F}

numericInput(inputId = "ms2_int_thresh",
             label = NULL,
             value = def_state$conf$prescreen$ms2_int_thresh)
```


MS1 signal-to-noise ratio.

```{r, echo=F}

numericInput(inputId = "s2n",
             label = NULL,
             value = def_state$conf$prescreen$s2n)
```


Todor Kondic's avatar
Todor Kondic committed
<details><summary>MS1/MS2 retention delay.</summary>

Look for associated MS2 spectrum within this window around the MS1
peak.

</details>
```{r, echo=F}
shinyscreen::rt_input(input_rt = "ret_time_shift_tol",
                      input_unit = "ret_time_shift_tol_unit",
                      def_rt = def_state$conf$prescreen[["ret_time_shift_tol"]],
                      def_unit = "min")
```

Todor Kondic's avatar
Todor Kondic committed
## Filter and order the summary table
<div style= "display: flex; vertical-align:top; ">

<div style="padding-right: 0.5em">
Todor Kondic's avatar
Todor Kondic committed
<details><summary>Filter summary table</summary>

Filter entries in the summary table according to the QA criteria.
Todor Kondic's avatar
Todor Kondic committed

* **qa_pass** : entries that passed all checks

* **qa_ms1_exists** : MS1 intensity is above the MS1 threshold

* **qa_ms2_exists** : those entries for which some MS2 spectra have been found

* **qa_ms1_above_noise** : MS1 is intense enough and above the noise level

* **qa_ms2_good_int** : MS2 intensity is above the MS2 threshold

* **qa_ms2_near** : MS2 spectrum is close enough to the MS1 peak

For those who do not speak Italian (and do not dig the bad Sergio
Leone pun):

* **l'irrelevante** : ignore QA criterion
* **il buono** : entry passed QA
* **il cattivo** : entry failed QA

Todor Kondic's avatar
Todor Kondic committed
</details>
```{r, echo=F}

rhandsontable::rHandsontableOutput("summ_subset")

Todor Kondic's avatar
Todor Kondic committed
```
</div>

<div style="padding-left: 0.5em">

Todor Kondic's avatar
Todor Kondic committed
<details><summary>Ordering by columns</summary>
It is possible to order the summary table using columns (keys): 
*`r paste(gsub("^-(.+)","\\1",shinyscreen:::DEF_INDEX_SUMM), collapse = ',')`*.
The sequence of columns in the table below describes the
sequence of ordering steps -- the key in the first row sorts the
entire summary table and subsequent keys break the ties.

</details>

```{r, echo=F}
rhandsontable::rHandsontableOutput("order_summ")
```

</div>

</div>

### Logarithmic axis

```{r, echo=F}
checkboxGroupInput("plot_log",
                   label=NULL,
Todor Kondic's avatar
Todor Kondic committed
                   choices = c("MS1 EIC","MS2 EIC","MS2 Spectrum"),
                   selected = character(0))
```

### Global retention time range
```{r, echo=F}
shinyscreen::rt_input(input_rt = "plot_rt_min",
                      input_unit = "plot_rt_min_unit",
                      def_rt = NA_real_,
                      def_unit = "min",
                      pref = "min:")

shinyscreen::rt_input(input_rt = "plot_rt_max",
                      input_unit = "plot_rt_max_unit",
                      def_rt = NA_real_,
                      def_unit = "min",
                      pref = "max:")
```

### Grouping plots

<details><summary>How to group plots?</summary> 

The _Select plot group_ and _Select plot label_ controls control how
the data is visually grouped together. The _plot group_ groups
together multiple curves in a single graph. Each curve in a graph is
designated by the _plot label_.

</details>

<div style= "display: flex; vertical-align:top; ">

<div style="padding-right:0.5em;">
```{r, echo=F}
p_feats <- 1:length(shinyscreen:::PLOT_FEATURES)
names(p_feats) <- shinyscreen:::PLOT_FEATURES
selectInput(inputId = "plot_grp_plot",
            label = "Select plot group",
            choices = p_feats,
            selected = p_feats[[shinyscreen:::FIG_DEF_CONF$grouping[["plot"]]]],
            width  = "100%")
```
</div>

<div style="padding-left:0.5em;">
```{r, echo=F}
p_feats <- 1:length(shinyscreen:::PLOT_FEATURES)
names(p_feats) <- shinyscreen:::PLOT_FEATURES
selectInput(inputId = "plot_label",
            label = "Select plot label",
            choices = p_feats,
            selected = p_feats[[shinyscreen:::FIG_DEF_CONF$grouping[["label"]]]],
            width = "100%")
```
</div>

</div>
```{r, echo=F}
shiny::textInput(inputId = "rep_aut", label = "Report author", value = def_state$conf$report$author)
shiny::textInput(inputId = "rep_tit", label = "Report title", value = def_state$conf$report$title)
```

# View compound Lists and Sets {.tabset}

## Compound List

```{r, echo=F}
DT::dataTableOutput("comp_table")
```

## Setid Table
```{r, echo=F}
DT::dataTableOutput("setid_table")
```

# Save and Restore
Shinyscreen can start from either a previously saved _state_ file (in
RDS format), or from a _YAML_ config file. States saved using GUI can
also be used from the script.

```{r, echo=FALSE}
actionButton(inputId = "state_file_load_b",
             label= "Restore project state")

```{r, echo=FALSE}
actionButton(inputId = "state_file_save_b",
             label= "Save project state")
# Extract Data and Prescreen
<details><summary>Extract spectra from data files.</summary>

After Shinyscreen is configured, the compound and setid lists loaded, it
is possible to proceed with extracting the data. This is potentially a
time-intensive step, so some patience might be needed.

Once the data is extracted, it will be possible to quality check the
spectra associated with the compounds specified in the _setid_ list,
to subset that data, look at the plots and publish a report.

</details>
```{r, echo=FALSE}
Todor Kondic's avatar
Todor Kondic committed
actionButton(inputId = "extract_b",
             label = "Extract")
```

<details><summary>Prescreen extracted spectra.</summary>

After the data extraction is finished, the quality of the retrieved
spectra can be checked using the criteria defined in the
_Prescreening_ tab of the _Configuration_ Section. The resulting
_summary table_ is given below and is based on the prescreening
criteria and filter and ordering setup specified in _Filter and order
the summary table_ configuration subsection.

</details>

</details>
```{r, echo=FALSE}
actionButton(inputId = "presc_b",
             label = "Prescreen and filter")
```

```{r, echo=FALSE}
DT::dataTableOutput("summ_table")
```


# Browse Results
Generate plots.

```{r, echo=F}

uiOutput("plot_b_ctrl")

```
<div style="display: flex; ">

<div>
```{r, echo=F}

uiOutput("plot_set_b_ctrl")

## selectInput(inputId = "plot_set_b",
##             label = "Select set",
##             choices = c("uninitialised"=0))
```
</div>

<div style="vertical-align: bottom; ">
```{r, echo=F}

uiOutput("plot_id_b_ctrl")
## selectInput(inputId = "plot_id_b",
##             label = "Select ID",
##             choices = c("uninitialised"=0))
```
</div>

</div>


<div style="display: flex; ">

<div style="vertical-align: bottom; ">
```{r, echo=F}
actionButton(inputId = "plot_next_b",
             label = "Previous")
```
</div>

<div style="vertical-align: bottom; ">
```{r, echo=F}
actionButton(inputId = "plot_prev_b",
             label = "Next")
```
</div>


</div>
Todor Kondic's avatar
Todor Kondic committed

<!-- ENGINE -->

<!-- setup is here  -->
Todor Kondic's avatar
Todor Kondic committed

```{r, include="false", context='setup'}
Todor Kondic's avatar
Todor Kondic committed
ord_nms <- gsub("^-(.+)","\\1",shinyscreen:::DEF_INDEX_SUMM)
ord_asc <- grepl("^-.+",shinyscreen:::DEF_INDEX_SUMM)
ord_asc <- factor(ifelse(ord_asc, "descending", "ascending"),levels = c("ascending","descending"))
def_ord_summ <- shinyscreen:::dtable("Column Name"=ord_nms,"Direction"=ord_asc)
update_gui <- function(in_conf, session) {
    upd_unit <- function(entry,inp_val,inp_unit,choices) {
        if (isTruthy(entry)) {
            cntnt <- strsplit(entry,split = "[[:space:]]+")[[1]]
            cntnt <- cntnt[nchar(cntnt) > 0]
            if (length(cntnt)!=2) stop("(upd_unit) ","Unable to interpret ", entry)
            val <- cntnt[[1]]
            unit <- cntnt[[2]]
            updateNumericInput(session = session,
                               inputId = inp_val,
                               value = as.numeric(val))
            updateSelectInput(session = session,
                              inputId = inp_unit,
                              selected = unit,
                              choices = choices)
        }
    }

    upd_num <- function(entry,inp_val) {
        if (isTruthy(entry)) {
            updateNumericInput(session = session,
                               inputId = inp_val,
                               value = as.numeric(entry))
        }
    }

    upd_sel <- function(inputId,selected,choices) {
        if (isTruthy(selected)) {
            updateSelectInput(session = session,
                              inputId = inputId,
                              selected = selected,
                              choices = choices)
        }
    }

    isolate({
        rv_state$conf$project <- in_conf$project
        rv_state$conf$data <- in_conf$data
        ## Lists
        rv_state$conf$compounds$lists <- in_conf$compounds$lists
        rv_state$conf$compounds$sets <- in_conf$compounds$sets
        
        ## Tolerance
        
        upd_unit(in_conf$tolerance[["ms1 fine"]],
                 "ms1_fine",
                 "ms1_fine_unit",
                 choices=c("ppm","Da"))
        upd_unit(in_conf$tolerance[["ms1 coarse"]],
                 "ms1_coarse",
                 "ms1_coarse_unit",
                 choices=c("ppm","Da"))

        upd_unit(in_conf$tolerance[["eic"]],
                 "ms1_eic",
                 "ms1_eic_unit",
                 choices=c("ppm","Da"))
        upd_unit(in_conf$tolerance[["rt"]],
                 "ms1_rt_win",
                 "ms1_rt_win_unit",
                 choices=c("min","s"))

        ## Prescreen
        upd_num(in_conf$prescreen[["ms1_int_thresh"]],
                "ms1_int_thresh")
        upd_num(in_conf$prescreen[["ms2_int_thresh"]],
                "ms2_int_thresh")
        upd_num(in_conf$prescreen[["s2n"]],
                "s2n")
        upd_unit(in_conf$prescreen[["ret_time_shift_tol"]],
                 "ret_time_shift_tol",
                 "ret_time_shift_tol_unit",
                 choices=c("min","s"))

        ## Files
        df <- shinyscreen:::file2tab(in_conf$data)
        df[,tag:=as.character(tag),with=T]
        rv_dfiles(df[,.(File=Files,tag),by=c("Files","tag"),mult="first"])
        nms <- colnames(df)
        nms <- nms[nms!="Files"]
        fdt <- df[,..nms]
        rv_datatab(fdt)

        ## figures
        upd_unit(in_conf$figures$rt_min,
                 "plot_rt_min",
                 "plot_rt_min_unit",
                 choices=c("min","s"))
        
        upd_unit(in_conf$figures$rt_max,
                 "plot_rt_max",
                 "plot_rt_max_unit",
                 choices=c("min","s"))

        logentry <- in_conf$figures$logaxes
        logchoice <- logical(0)
        logchoice <- mapply(function(cn,uin) if (cn %in% logentry) uin else NA,
                            c("ms1_eic_int","ms2_eic_int","ms2_spec_int"),
                            c("MS1 EIC","MS2 EIC","MS2 Spectrum"),USE.NAMES = F)
        logchoice <- logchoice[!is.na(logchoice)]
        
        updateCheckboxGroupInput(session = session,
                                 inputId = "plot_log",
                                 choices = c("MS1 EIC",
                                             "MS2 EIC",
                                             "MS2 Spectrum"),
                                 selected = logchoice)
        ## Report
        if (isTruthy(in_conf$report$author)) updateTextInput(session,"rep_aut",value = in_conf$report$author)
        if (isTruthy(in_conf$report$title)) updateTextInput(session,"rep_tit",value = in_conf$report$title)

        
    })
}

```{r, include="false", context='server'}
## reactive functions

observeEvent(input$setid_b, {
    filters <- matrix(c("CSV files", ".csv",
                        "All files", "*"),
Todor Kondic's avatar
Todor Kondic committed
                      2, 2, byrow = TRUE)
    setids <- tcltk::tk_choose.files(filters=filters)
    message("(config) Selected compound sets (setid): ", paste(setids,collapse = ","))
    rv_state$conf$compounds$sets <- if (length(setids)>0 && nchar(setids[[1]])>0) setids else "Nothing selected."
})



rf_compound_input_state <- reactive({
    sets <- rv_state$conf$compounds$sets
    lst <- as.list(rv_state$conf$compounds$lists)
    validate(need(length(lst)>0,
                  message = "Load the compound lists(s) first."))
Todor Kondic's avatar
Todor Kondic committed
    validate(need(length(sets)>0 && nchar(sets)>0,
                  message = "Load the setid table first."))
    isolate({
        state <- rev2list(rv_state)
        m <- load_compound_input(state)
        ## Side effect! This is because my pipeline logic does not
        ## work nicely with reactive stuff.
        rv_state$input$tab$cmpds <- list2rev(m$input$tab$cmpds)
        rv_state$input$tab$setid <- m$input$tab$setid
        m
Todor Kondic's avatar
Todor Kondic committed
    })

rf_conf_proj <- reactive({
    state <- rev2list(rv_state)
    dir.create(state$conf$project,showWarnings = F)
    state
    
})

rf_conf_state <- reactive({
    state <- rf_conf_proj()
    ## mzml1 <- rf_get_inp_datatab()
    ## mzml1[,`:=`(tag=as.character(tag),
    ##             set=as.character(set),
    ##             adduct=as.character(adduct))]
    ## mzml2 <- rf_get_inp_datafiles()
    
    ## mzml <- mzml1[mzml2,on="tag"]
    ftab <- get_fn_ftab(state)
    state$conf$data <- ftab
    state$conf[["summary table"]]$filter <- rf_get_subset()
    state$conf[["summary table"]]$order <- rf_get_order()
    state
})

rf_get_subset <- reactive({
    dt <- tryCatch(rhandsontable::hot_to_r(input$summ_subset),
                   error = function(e) def_summ_subset)
    dt[Select == "il buono", extra := T]
    dt[Select == "il cattivo", extra := F]
    sdt <- dt[!is.na(extra)]
    if (NROW(sdt) > 0) {
        sdt[,paste0(`QA Column`," == ",extra)]
    } else NULL
})

rf_get_order <- reactive({
    dt <- tryCatch(rhandsontable::hot_to_r(input$order_summ),error = function(e) def_ord_summ)
    tmp <- dt[Direction == "descending",.(`Column Name`=paste0("-",`Column Name`))]
    tmp[,`Column Name`]
Todor Kondic's avatar
Todor Kondic committed

rf_get_inp_datatab <- eventReactive(input$datatab,{
    z <- data.table::as.data.table(tryCatch(rhandsontable::hot_to_r(input$datatab)),
                                   error = function(e) def_datatab)

Todor Kondic's avatar
Todor Kondic committed
    z[,.(tag=as.character(tag),
         adduct=as.character(adduct),
         set=as.character(set)), with = T]
})

rf_get_inp_datafiles <- eventReactive(input$datafiles,{
    z <- data.table::as.data.table(tryCatch(rhandsontable::hot_to_r(input$datafiles)),
                                   error = function(e) def_datafiles)

    
    z[,.(File,
         tag=as.character(tag)), with = T]
})
Todor Kondic's avatar
Todor Kondic committed
```
Todor Kondic's avatar
Todor Kondic committed
```{r, include="false", context='server'}

observeEvent(input$project_b,{
    wd <- tcltk::tk_choose.dir(default = getwd(),
                               caption = "Choose project directory")
    message("Set project dir to ", wd)
    rv_state$conf$project <- wd
})

observeEvent(input$comp_list_b, {
    filters <- matrix(c("CSV files", ".csv",
                        "All files", "*"),
Todor Kondic's avatar
Todor Kondic committed
                      2, 2, byrow = TRUE)
    compfiles <- tcltk::tk_choose.files(filters=filters)
    message("(config) Selected compound lists: ", paste(compfiles,collapse = ","))
    rv_state$conf$compounds$lists <- if (length(compfiles)>0 && nchar(compfiles[[1]])>0) compfiles else "Nothing selected."
})

Todor Kondic's avatar
Todor Kondic committed
observeEvent(input$datafiles_b,{
    filters <- matrix(c("mzML files", ".mzML",
                        "All files", "*"),
                      2, 2, byrow = TRUE)
    fns <- tcltk::tk_choose.files(filters=filters)
    message("(config) Selected data files: ", paste(fns,collapse = ","))
    ## Did the user choose any files?
    if (length(fns) > 0) {
        oldtab <- rf_get_inp_datafiles()
Todor Kondic's avatar
Todor Kondic committed
        
        newf <- setdiff(fns,oldtab$File)
        nr <- NROW(oldtab)
        tmp <- if (length(newf)>0) shinyscreen:::dtable(File=newf,tag=paste0('F',(nr+1):(nr + length(newf)))) else shinyscreen:::dtable(File=character(),tag=character())

        z <- rbind(oldtab, tmp)
        z[,tag:=as.character(tag)]
        rv_dfiles(z)
    }
})

observe({
    df_tab <- rf_get_inp_datafiles()
Todor Kondic's avatar
Todor Kondic committed
    state <- rf_compound_input_state()
    isolate(oldtab <- rf_get_inp_datatab())
Todor Kondic's avatar
Todor Kondic committed
    oldt <- oldtab$tag
    tagl <- df_tab$tag
    diff <- setdiff(tagl,
                    oldt)
    
    res <- if (length(diff)!=0) {
               ## Only change the tag names in the old ones.
               pos_tag <- 1:length(tagl)
               pos_old <- 1:NROW(oldtab)
               pos_mod <- intersect(pos_tag,pos_old)
               new_tag <- tagl[pos_mod]
               if (NROW(oldtab)>0) oldtab[pos_mod,tag := ..new_tag]

               ## Now add tags for completely new files, if any.
               rest_new <- if (NROW(oldtab) > 0) setdiff(diff,new_tag) else diff
               tmp <- shinyscreen:::dtable(tag=rest_new,
                                           adduct=character(0),
                                           set=character(0))

               dt <-data.table::as.data.table(rbind(as.data.frame(oldtab),
                                                    as.data.frame(tmp)))
               dt[tag %in% df_tab$tag,]
           } else oldtab
    
    rv_datatab(res)
})

observe({
    dtab <- rv_datatab()
    dfiles <- rv_dfiles()
    message("(config) Generating mzml from rv.")
    isolate(rv_state$input$tab$mzml <- dtab[dfiles,on="tag"])
    
}, label = "mzml_from_rv")

observe({
    dtab <- rf_get_inp_datatab()
    dfiles <- rf_get_inp_datafiles()

    message("(config) Generating mzml from inputs.")
    res <- dtab[dfiles,on="tag"]
    data.table::setnames(res,"File","Files")
    isolate(rv_state$input$tab$mzml <- res)

    
}, label = "mzml_from_inp")
Todor Kondic's avatar
Todor Kondic committed

observeEvent(input$extract_b,{
    m <- rf_conf_state()
    fn_c_state <- file.path(m$conf$project,
Todor Kondic's avatar
Todor Kondic committed
                            paste0("extract.",shinyscreen:::FN_CONF))
    yaml::write_yaml(x=m$conf,file=fn_c_state)
    message("(extract) Config written to ", fn_c_state)
    state <- withr::with_dir(new=m$conf$project,
Todor Kondic's avatar
Todor Kondic committed
                             code = {
                                 m <- setup_phase(m)
                                 m <- mk_comp_tab(m)
                                 extr_data(m)
Todor Kondic's avatar
Todor Kondic committed
                             })
    message("(extract) Done extracting.")
    z <- shinyscreen::merge2rev(rv_state,lst = state)
    eval(z)
    ## rv_state <<- list2rev(state)
    
})

observeEvent(input$presc_b,{
    validate(need(NROW(rv_state$extr$ms) > 0,
                  message = "Perform extraction first."))
    m <- rev2list(rv_state)

    fn_c_state <- file.path(m$conf$project,
                            paste0("presc.",shinyscreen:::FN_CONF))
    yaml::write_yaml(x=m$conf,file=fn_c_state)
    message("(prescreen) Config written to ", fn_c_state)
    state <- withr::with_dir(new=m$conf$project,
                             code = {
                                 m <- prescreen(m)
                                 m <- sort_spectra(m)
                                 subset_summary(m)
                             })
    message("(prescreen) Done prescreening.")
    
    z <- shinyscreen::merge2rev(rv_state,lst = state)
    eval(z)
    
observeEvent(input$plot_b,{
    validate(need(NROW(rv_state$out$tab$flt_summ) > 0,
                  message = "Perform prescreening first."))
    m <- rev2list(rv_state)

    fn_c_state <- file.path(m$conf$project,
                            paste0("genplot.",shinyscreen:::FN_CONF))
    yaml::write_yaml(x=m$conf,file=fn_c_state)
    message("(generate plots) Config written to ", fn_c_state)
    state <- withr::with_dir(new=m$conf$project,
                             code = {
                                 m <- create_plots(m)
                                 save_plots(m)
                             })
    message("(generate plots) Done generating plots.")
    
    z <- shinyscreen::merge2rev(rv_state,lst = state)
    eval(z)
})

observeEvent(input$state_file_load_b,{
    filters <- matrix(c("RDS files", ".rds",
                        "YAML config files", ".yaml",
    fn <- tcltk::tk_choose.files(filters=filters,
                                 multi = F)
    
    message("(config) Loading state from: ", paste(fn,collapse = ","))
    fn <- if (length(fn)>0 && nchar(fn[[1]])>0) fn else ""
        if (grepl("yaml",fn)) {
            state <- new_state_fn_conf(fn)
            conf <- state$conf
            update_gui(conf,session=session)
        } else {
            state <- readRDS(file=fn)
            z <- shinyscreen::merge2rev(rv_state,lst = state)
            eval(z)
            update_gui(rv_state$conf, session=session)
        }
observeEvent(input$state_file_save_b,{
    filters <- matrix(c("RDS files", ".rds",
                        "All files", "*"),
                      2, 2, byrow = TRUE)
    fn <- tk_save_file(filters=filters,                       
                       default = "state.rds")
    message("(config) Saving state to: ", paste(fn,collapse = ","))
    fn <- if (length(fn)>0 && nchar(fn[[1]])>0) fn else ""

    if (nchar(fn) > 0) {
        m <- rev2list(rv_state)
        ftab <- get_fn_ftab(m)
        fconf <- get_fn_conf(m)
        yaml::write_yaml(m$conf,
                         file = fconf)
        shinyscreen:::tab2file(tab=m$input$tab$mzml,file=ftab)
        m$conf$data <- ftab
```

<!-- Tolerance -->
```{r, include='false', context = 'server'}
uni_ass <- function(val,unit) {
    paste(input[[val]],
          input[[unit]])
}
observe({
    
    rv_state$conf$tolerance[["ms1 fine"]] <- uni_ass("ms1_fine",
                                                     "ms1_fine_unit")
    
    rv_state$conf$tolerance[["ms1 coarse"]] <- uni_ass("ms1_coarse",
                                                       "ms1_coarse_unit")

    rv_state$conf$tolerance[["eic"]] <- uni_ass("ms1_eic",
                                                "ms1_eic_unit")

    rv_state$conf$tolerance[["rt"]] <- uni_ass("ms1_rt_win",
                                               "ms1_rt_win_unit")


})
```

<!-- Prescreen -->
```{r, include='false', context = 'server'}
## uni_ass <- function(val,unit) {
##     paste(input[[val]],
##           input[[unit]])
## }
observe({
    
    rv_state$conf$prescreen[["ms1_int_thresh"]] <- input[["ms1_int_thresh"]]
    rv_state$conf$prescreen[["ms2_int_thresh"]] <- input[["ms2_int_thresh"]]
    rv_state$conf$prescreen[["s2n"]] <- input$s2n
    rv_state$conf$prescreen[["ret_time_shift_tol"]] <- uni_ass("ret_time_shift_tol",
                                                               "ret_time_shift_tol_unit")

})
Todor Kondic's avatar
Todor Kondic committed
<!-- Plotting -->
```{r, include='false', context = 'server'}
observe({
    vals <- input$plot_log
    checked <- c("MS1 EIC"=F,
                 "MS2 EIC"=F,
                 "MS2 Spectrum"=F)
    if (length(vals)!=0) checked[vals] <- T
    l <- list()
    l <- c(if (checked[["MS1 EIC"]]) "ms1_eic_int" else NULL,l)