# Help for ggplot extenders

## Your old ggplot extension can learn new tricks

The beauty of the broad solution `ggdibbler` provides is that it always works. It might not always look good or be exactly what you were looking for, but it always produces… something. To illustrate this, I included the `ggraph` example in the introduction to `ggdibbler`, but the idea can be implemented with extensions as well.

In the `ggraph` example, I illustrated how you can use the `ggdibbler` approach with a ggplot extension that isn’t even aware `ggdibbler` exists. While that method works (well enough) it can be somewhat annoying to implement, and it doesn’t give you access to the nested positions (as they use internal variables). I can understand fellow ggplot extenders might be chomping at the bit to see what their plots look like with uncertainty and nested positions.

Sometimes, when making a `ggdibbler` version of a `ggplot2` base function, I would think to myself “What is the point of this, who on earth needs an uncertain version of `stat_unique`?”. I still sometimes think that, but the reason we implemented it with ALL ggplot2 functions, is not for the users, but rather for the extenders. If there is a ggplot2 extension that is the child of a base `stat` or base position, a geom_*_sample variation of their function will simply be the child of the `ggdibbler` variation of the ggplot2 stat, instead of the original ggplot2 code. The only ggplot2 extension that might not work with `ggdibbler` is `ggdist` (for the obvious reason that is is the only other ggplot extension that is designed to take distributional input).

Now, I have made all functions in base `ggplot2` accept uncertain inputs, go me, but the real power of ggplot2 comes from the wealth of extension packages. Now, as fun as I am sure it would be, I am not about to spend the next 5 years making pull requests on every `ggplot2` extension package so that they can all accept random variables. Largely because:

1. Going around making pull requests that forces dependency on my package sounds like the early warning signs of a personality disorder
2. (More importantly) that sounds really boring and I don’t want to.

Thankfully, the `ggdibbler` approach is so easy if you are the author/maintainer of a `ggplot2` extension and you want it to accept random variables, you can just do it yourself.

## How to extend your package to accept random variables (easiest to hardest)

### Geoms

As `ggdibbler` only doesn’t actually implement any new geoms, the geoms are just wrappers for the stats. If you use an existing ggplot2 stat, `ggdibbler` should already have a variation of it, so you can just make the wrapper function using code that looks like this:

    geom_YOURGEOM_sample <- make_constructor(YOURGEOM, stat = "GGPLOT2STAT_sample",
                                             times = 10, seed = NULL)

### Stats

Stats are slightly more complicated, but still shockingly simple. There are two approaches to this. The first options is to make a YOURSTATSample child version of your stat, similar to the relationship between the base stats in ggplot and the sample stats implemented in `ggdibbler`. When making these functions in `ggdibbler` I literally had a template that I would copy and paste into the .R file.

    #' @importFrom ggplot2 ggproto Stat***
    #' @format NULL
    #' @usage NULL
    #' @export
    Stat***Sample <- ggplot2::ggproto("Stat***Sample", ggplot2::Stat***,
                                      ### INCLUDE SETUP PARAMS IF IN PARENT STAT
                                      setup_params = function(self, data, params) {
                                        # take one sample just to train the parameters
                                        times <- params$times
                                        params$times <- 1
                                        data <- dibble_to_tibble(data, params)
                                        params <- ggplot2::ggproto_parent(ggplot2::Stat***, self)$setup_params(data, params)
                                        params$times <- times
                                        params
                                      }
                                      ###  SETUP_DATA MUST BE IMPLEMENTED...
                                      setup_data = function(data, params) {
                                        dibble_to_tibble(data, params)
                                        # BUT YOU ONLY NEED TO INCLUDE THIS LINE IF THE MAIN STAT USES SETUP DATA
                                        ggproto_parent(Stat***, self)$setup_data(data, scales)
                                        },

                                      extra_params = c("na.rm", "times", "seed")
    )

    #' @export
    #' @inheritParams ggplot2::stat_***
    #' @param times A parameter used to control the number of values sampled from
    #' each distribution.
    #' @param seed Set the seed for the layers random draw, allows you to plot the
    #' same draw across multiple layers.
    stat_***_sample <- make_constructor(Stat***Sample, geom = "***",
                                        times = 10, seed = NULL)

The alternative option is if your stat is the child of an existing ggplot2 stat, you can just make a new version of your function that is a child of the `ggdibbler` version instead of the ggplot2 version. I haven’t implemented this one, so I am not 100% sure how it would work, but the only thing that `ggdibbler` does (99% of the time) is do a setup_data step.

### Scales(TODO)

Honestly, if your package implements new scales, I would hold off on this one until the `ggdibbler` scales system is more built up. You can still try, if you want, but I am not making any promises on the usability of the function you spit out. So long as distributional can make a random variable of your scale’s object type, you can make a nested scale of it.

(NOTE: actually fill out this section)

### Nested Positions (TODO)

The nested position system can’t really be extended upon yet, but it is a future plan, sorry!