# Fully Customed Venn Diagram

    library(ggVennDiagram)

## Comprehensive customization by using helper functions

The main function `ggVennDiagram()` accepts a list input, and output a ggplot object. By measuring the length of input list, it automatically applies internal functions to build a plot in two steps: data preparation and visualization.

Data preparation was packaged into one function `process_data()`. Its output is a S4 `VennPlotData` class object, which contains three slots, `setEdge`, `setLabel` and `region`. These slot data then can be further plotted with `ggplot` functions.

See below for a better understanding.

Generate example data.

    genes <- paste0("gene",1:1000)
    set.seed(20210302)
    gene_list <- list(A = sample(genes,100),
                      B = sample(genes,200),
                      C = sample(genes,300),
                      D = sample(genes,200))

    library(ggVennDiagram)
    library(ggplot2)
    #> Warning: package 'ggplot2' was built under R version 4.2.3

Then we can reproduce the plot of `ggVennDiagram()` with several lines.

    venn <- Venn(gene_list)
    data <- process_data(venn)
    ggplot() +
      # 1. region count layer
      geom_sf(aes(fill = count), data = venn_region(data)) +
      # 2. set edge layer
      geom_sf(aes(color = id), data = venn_setedge(data), show.legend = FALSE) +
      # 3. set label layer
      geom_sf_text(aes(label = name), data = venn_setlabel(data)) +
      # 4. region label layer
      geom_sf_label(aes(label = count), data = venn_region(data)) +
      theme_void()

The variable `data` is a S4 class object that has three slots.

    data
    #> An object of class "VennPlotData"
    #> Slot "setEdge":
    #> Simple feature collection with 4 features and 5 fields
    #> Geometry type: LINESTRING
    #> Dimension:     XY
    #> Bounding box:  xmin: 0.0649949 ymin: 0.1849949 xmax: 0.9350051 ymax: 0.8391534
    #> CRS:           NA
    #> # A tibble: 4 × 6
    #>   id                                        geometry component item  count name
    #>   <chr>                                 <LINESTRING> <chr>     <nam> <int> <chr>
    #> 1 1     (0.1025126 0.7174874, 0.09412107 0.7081191,… setEdge   <chr>   100 A
    #> 2 2     (0.2525126 0.8174874, 0.246341 0.8103391, 0… setEdge   <chr>   200 B
    #> 3 3     (0.7333452 0.8033452, 0.7262248 0.8095447, … setEdge   <chr>   300 C
    #> 4 4     (0.8974874 0.7174874, 0.8881191 0.7258789, … setEdge   <chr>   200 D
    #>
    #> Slot "setLabel":
    #> Simple feature collection with 4 features and 3 fields
    #> Geometry type: POINT
    #> Dimension:     XY
    #> Bounding box:  xmin: 0.08 ymin: 0.78 xmax: 0.93 ymax: 0.86
    #> CRS:           NA
    #> # A tibble: 4 × 4
    #>   id       geometry component name
    #>   <chr>     <POINT> <chr>     <chr>
    #> 1 1     (0.08 0.78) setLabel  A
    #> 2 2     (0.26 0.86) setLabel  B
    #> 3 3     (0.71 0.85) setLabel  C
    #> 4 4     (0.93 0.78) setLabel  D
    #>
    #> Slot "region":
    #> Simple feature collection with 15 features and 5 fields
    #> Geometry type: POLYGON
    #> Dimension:     XY
    #> Bounding box:  xmin: 0.0649949 ymin: 0.1849949 xmax: 0.9350051 ymax: 0.8391534
    #> CRS:           NA
    #> # A tibble: 15 × 6
    #>    id                                       geometry component item  count name
    #>    <chr>                                   <POLYGON> <chr>     <lis> <int> <chr>
    #>  1 1     ((0.1025126 0.7174874, 0.1118809 0.7258789… region    <chr>    43 A
    #>  2 2     ((0.2525126 0.8174874, 0.2596609 0.823659,… region    <chr>    99 B
    #>  3 3     ((0.7333452 0.8033452, 0.7395447 0.7962248… region    <chr>   174 C
    #>  4 4     ((0.8974874 0.7174874, 0.9058789 0.7081191… region    <chr>   107 D
    #>  5 12    ((0.2494531 0.7508377, 0.266399 0.7472201,… region    <chr>    10 A..B
    #>  6 13    ((0.3598131 0.3161471, 0.3466157 0.3144203… region    <chr>    22 A..C
    #>  7 14    ((0.6341476 0.306281, 0.6321686 0.2919527,… region    <chr>    12 A..D
    #>  8 23    ((0.4087951 0.6905086, 0.4240163 0.7044756… region    <chr>    48 B..C
    #>  9 24    ((0.7013464 0.5605964, 0.7121743 0.5437184… region    <chr>    25 B..D
    #> 10 34    ((0.7562978 0.7359764, 0.7555797 0.7233843… region    <chr>    41 C..D
    #> 11 123   ((0.4254307 0.668526, 0.4425419 0.6552909,… region    <chr>     5 A..B…
    #> 12 124   ((0.6020164 0.4567956, 0.6098817 0.4389429… region    <chr>     5 A..B…
    #> 13 134   ((0.4966178 0.374675, 0.4805314 0.3646387,… region    <chr>     2 A..C…
    #> 14 234   ((0.5085786 0.6114214, 0.5243976 0.6266822… region    <chr>     7 B..C…
    #> 15 1234  ((0.5066822 0.5956024, 0.5213246 0.5792878… region    <chr>     1 A..B…

`ggVennDiagram` export functions to get these data, and they can be used for comprehensive customization in user-side.

- `Venn()`: Venn object constructor, use this to construct a Venn object from list.
- `process_data()`: process data with a Venn object
- `venn_region()`: get region data to plot
- `venn_setedge()`: get setedge data to plot
- `venn_setlabel()`: get setlabel data to plot

For example, you may change edge/fill/label properties as you will.

    ggplot() +
      # change mapping of color filling
      geom_sf(aes(fill = id), data = venn_region(data), show.legend = FALSE) +
      # adjust edge size and color
      geom_sf(color="grey", size = 3, data = venn_setedge(data), show.legend = FALSE) +
      # show set label in bold
      geom_sf_text(aes(label = name), fontface = "bold", data = venn_setlabel(data)) +
      # add a alternative region name
      geom_sf_label(aes(label = name), data = venn_region(data), alpha = 0.5) +
      theme_void()

## Stepwise `plotly`

This is for issue #26.

    venn <- Venn(gene_list)
    data <- process_data(venn)
    items <- venn_region(data) %>%
      dplyr::rowwise() %>%
      dplyr::mutate(text = yulab.utils::str_wrap(paste0(.data$item, collapse = " "),
                                             width = 40)) %>%
      sf::st_as_sf()
    label_coord = sf::st_centroid(items$geometry) %>% sf::st_coordinates()
    p <- ggplot(items) +
      geom_sf(aes_string(fill="count")) +
      geom_sf_text(aes_string(label = "name"),
                   data = data@setLabel,
                   inherit.aes = F) +
      geom_text(aes_string(label = "count", text = "text"),
                x = label_coord[,1],
                y = label_coord[,2],
                show.legend = FALSE) +
      theme_void() +
      scale_fill_distiller(palette = "RdBu")
    #> Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
    #> ℹ Please use tidy evaluation idioms with `aes()`.
    #> ℹ See also `vignette("ggplot2-in-packages")` for more information.
    #> This warning is displayed once every 8 hours.
    #> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
    #> generated.
    #> Warning in geom_text(aes_string(label = "count", text = "text"), x =
    #> label_coord[, : Ignoring unknown aesthetics: text
    ax <- list(
      showline = FALSE
    )
    plotly::ggplotly(p, tooltip = c("text")) %>%
      plotly::layout(xaxis = ax, yaxis = ax)

Note: Please be aware that due to the poor compatibility between plotly and ggplot, this feature is only experimental.