---
title: "Adding third party plots"
author: 
- name: Samuel Wieczorek
- name: Thomas Burger
package: omXplore
abstract: >
    The package `omXplore` is able to embed third party plots. This vignette aims to explain how to add an external plot to the main UI of `omXplore`.
date: "`r Sys.Date()`"
output:
    BiocStyle::html_document:
        toc_float: true
vignette: >
    %\VignetteIndexEntry{Adding third party plots}
    %%\VignetteKeywords{Softmware}
    %\VignetteEncoding{UTF-8}
    %\VignetteEngine{knitr::rmarkdown}
editor_options: 
  markdown: 
    wrap: 72
---

```{r style, echo = FALSE, results = 'asis'}
BiocStyle::markdown()
```

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE)
```

```{r env, message = FALSE, warning = FALSE, echo = FALSE}
library("omXplore")
```

# Introduction

An interesting feature about `omXplore` is the capacity to insert custom
plots into the collection of vignettes of the Shiny app
`view_dataset()`. This is useful to complete the panel of built-in plots
of `omXplore` and the main UI (See ?view_dataset).

This vignette aims to describe how to (i) develop a plot function
compliant with `omXplore` and (ii) add a new plot in the main app of the
package `omXplore`.

# Develop a plot module for `omXplore`

Any plot function, to be compatible with `omXplore`, must be written as
a [shiny module](https://shiny.posit.co/r/articles/improve/modules/) to
allow for better code organisation and re-usability. Let suppose one
wants to write a plot called "myFirstPlot". As usual, the code of this
shiny app is divided into two parts:

-   User interface (UI): function "myFirstPlot_ui()"
-   Server: function "myFirstPlot_server()"

Moreover, the parameters of these two functions must have the same name
and class as the built-in plot functions in `omXplore` . For more
details, see ?extFoo1 which is a simple example of what a generic plot
function should looks like.

Following Bioconductor's recommendations about [Running shiny
apps](https://contributions.bioconductor.org/shiny.html#running-app),
the source code for this plot function should look as follows:

```{r, eval=FALSE}
myFirstPlot <- function(obj, i) {
    ui <- myFirstPlot_ui(id)
    server <- myFirstPlot_server(id, obj, i)
    app <- shinyApp(ui = ui, server = server)
}
```

These three functions (myFirstPlot_ui(), myFirstPlot_server() and
myFirstPlot()) can be written in the same source file (e.g.
myFirstPlot.R)

# Adding an existing module

## From a R package

When one wants to add an external plot from a R package, it is by means
of the parameter 'addons' of the function `view_dataset()`. This
parameter is a list structured as follows:

-   the name of each slot is the name of a R package in which a plot
    module is implemented,

-   the content of the slot is a vector of modules names.

It is necessary that the functions \*_ui() and \*_server are defined outside the global app function myFirstPlot(). This is because the function "view_dataset" cannot use the function myFirstPlot() and it must use the two functions myFirstPlot_ui(), myFirstPlot_server().

Thus, the following code **will not work**:

```{r, eval=FALSE}
myFirstPlot <- function(obj, i) {
    ui <- function(id) {
        ...
    }
    server <- function(id, obj, i) {
        moduleServer(
            id,
            function(input, output, session) {
                ...
            }
        )
    }

    app <- shinyApp(ui = ui, server = server)
}
```


A functional code is as follows:
```{r, eval=FALSE}
myFirstPlot_ui <- function(id) {
    ...
}


myFirstPlot_server <- function(id, obj, i) {
    moduleServer(
        id,
        function(input, output, session) {
            ...
        }
    )
}

myFirstPlot <- function(obj, i) {
    ui <- myFirstPlot_ui(id)
    server <- myFirstPlot_server(id, obj, i)
    app <- shinyApp(ui = ui, server = server)
}
```


As an example, the code below will add three external plots:

-   package `myPkgA`: the plot functions "extFoo1" and "extFoo2",

-   package `myPkgB`: the plot function "extFoo1".

The corresponding R code is the following:

```{r eval = FALSE}
addons <- list(
    myPkgA = c("extFoo1", "extFoo2"),
    myPkgB = c("extFoo1")
)
view_dataset(myData, addons)
```

Functions can have same names if they are part of different packages.

With this procedure, it is not necessary to load the entire package in
order to user the plot module. `omXplore` loads only the necessary code for the plot fucntions.

**Icon for clickable vignette**

If the plot function is part of a R package, it is possible to store a
\*.png image that serves as icon for the clickable vignette displayed in
the (B) area of the main app of `omXplore`. For that purpose,
the file should be stored in the 'images' directory of the corresponding
package and its name should be the same as the function it refers to.

The global file structure for the plot function of the example is the
following:

```         
MyPackage/
|-- R/
|   |-- myFirstPlot.R
|-- inst/
|   |-- images/
|       |-- myFirstPlot.png
```

## From R console

If the plot function is written in a R script nor console, the same rules are used to write the three functions described in the previous section. 

However, there are two important modifications:

-   the name of the three functions must be prefixed by "omXplore_'

-   so as to let `omXplore` find the plot function, it must already be loaded in the global R environment before running the app `view_dataset()`. Please note that in this case, there is to need to set the parameter "addons".

```{r, eval=FALSE}
omXplore_mySecondPlot <- function(obj, i) {
    ui <- omXplore_mySecondPlot_ui(id)
    server <- omXplore_mySecondPlot_server(id, obj, i)
    app <- shinyApp(ui = ui, server = server)
}
```



## Session information

```{r}
sessionInfo()
```
