Skip to content
Snippets Groups Projects
app.Rmd 10.8 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', echo=F}
def_state <- new_state()
rv_state <- list2rev(def_state)
```

# 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)`



Load the config file if needed.

```{r, echo=FALSE}
actionButton(inputId = "conf_file_b",
             label= "Load config")

```

<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)")

```

<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")

```

<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.")

```

```{r, context='server', echo=FALSE}
## b_project <- eventReactive(input$project, {
##     ""
## })
#rv_conf$project
#print(rv_conf)
## rv_conf$project <- b_project()
Todor Kondic's avatar
Todor Kondic committed
session$onSessionEnded(function () stopApp())
```

## 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$tolerance[["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>
Todor Kondic's avatar
Todor Kondic committed
<details><summary>Filter summary table</summary>
Selection criteria for filtering entries in the summary table
according to the QA criteria.

* **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
</details>
```{r, echo=F}
checkboxGroupInput("summ_subset",
                   label=NULL,
                   choiceNames = shinyscreen:::QA_FLAGS,
                   choiceValues = shinyscreen:::QA_FLAGS)


```
</div>
<div>
<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>




<!-- <details><summary>Order entries</summary> -->

<!-- Sequence of column a -->

<!-- </details> -->
<!-- ```{r, echo=F} -->
<!-- checkboxGroupInput("summ_subset", -->
<!--                    label=NULL, -->
<!--                    choiceNames = shinyscreen:::QA_FLAGS, -->
<!--                    choiceValues = 1:length(shinyscreen:::QA_FLAGS)) -->

<!-- ``` -->

### Logarithmic axis

```{r, echo=F}
checkboxGroupInput("plot_log",
                   label=NULL,
                   choiceNames = c("MS1 EIC","MS2 EIC","MS2 Spectrum"),
                   choiceValues = c(F,F,F))
```

### 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:")
```

```{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)
```

# 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}
actionButton(inputId = "extract",
             label = "Extract")
```


# Browse Results
Todor Kondic's avatar
Todor Kondic committed

<!-- Server comes here  -->

```{r, include="false", context='setup'}
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 names"=ord_nms,"Direction"=ord_asc)
```
```{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$extract,{
    tmp <- rev2list(rv_state)
    fn_c_state <- file.path(tmp$conf$project,
                            shinyscreen:::FN_CONF)
    yaml::write_yaml(x=tmp$conf,file=fn_c_state)
    message("(extract) Config written to ", fn_c_state)
})



```

<!-- Render -->
```{r, include="false", context="server"}
output$project <- renderText(rv_state$conf$project)

Todor Kondic's avatar
Todor Kondic committed
output$order_summ <- rhandsontable::renderRHandsontable(rhandsontable::rhandsontable(def_ord_summ,
                                                                                     manualRowMove = T))
```