---
title: "Overview"
output:
  rmarkdown::html_vignette:
    toc: true
vignette: >
  %\VignetteIndexEntry{ospsuite.plots}
  %\VignetteEncoding{UTF-8}
  %\VignetteEngine{knitr::rmarkdown}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  dpi = 300,
  fig.show = "hold",
  fig.align = "center",
  fig.width = 7,
  out.width = "80%",
  comment = "#>"
)
```

```{r setup, echo=FALSE}
options(rmarkdown.html_vignette.check_title = FALSE)

library(ospsuite.plots)
library(tidyr)
```

# 1. Introduction

## 1.1 Objectives of ospsuite.plots

The main purpose of the `ospsuite.plots` library is to provide standardized plots typically used in the context of PBPK modeling. The library supports plot generation for the packages `OSPSuiteR` and `OSPSuite.ReportingEngine`.

The library is based on `ggplot2` functionality and also utilizes the `ggh4x` package.

# 2. Default Settings for Layout

`ospsuite.plots` provides default settings for the layout, including theme, geometric aesthetics, colors, and shapes for distinct scales.

Examples within this vignette are plotted using the following test data:

```{r get-test-data, results='asis'}
testData <- exampleDataCovariates |>
  dplyr::filter(SetID == "DataSet1") |>
  dplyr::select(c("ID", "Age", "Obs", "Pred", "Sex"))

knitr::kable(head(testData), digits = 3)
```

## 2.1 Plots with and without Default Layout

### 2.1.1 Default ggplot Layout

- A plot created using the `ospsuite.plots` function
- B customized plot

```{r default-layout-comparison, warning=FALSE, fig.alt="Two plots comparing default ggplot styling (A) versus ospsuite.plots styling (B). Plot A shows a histogram with default ggplot formatting. Plot B shows a scatter plot with customized colors, shapes, and legend positioning demonstrating enhanced styling capabilities."}
# ospsuite.plots function
ospsuite.plots::plotHistogram(data = testData, mapping = aes(x = Age)) + labs(tag = "A")

# Customized plot
ggplot(data = testData, mapping = aes(x = Obs, y = Pred, color = Sex, shape = Sex)) +
  geom_point() +
  theme(legend.position = "top") +
  labs(tag = "B")
```

### 2.1.2 Set ospsuite.plots Layout

To set the default layout, we use the same logic as in `ggplot2::theme_set()`. The previous settings are returned invisibly, so you can easily save them and restore them later.

`setDefaults()` sets the theme, discrete color palette, and various options. All objects can also be set separately as described below. Shape ordering for OSP-aware geoms is controlled per plot via `scale_shape_osp()` or `scale_shape_osp_manual()`.

```{r set-ospsuite-defaults, warning=FALSE, fig.show='hold', fig.alt="Two plots showing the effect of setting ospsuite.plots defaults. Plot A shows a histogram with ospsuite.plots styling applied. Plot B shows a scatter plot that now automatically adopts the ospsuite.plots theme, colors, shapes, and formatting after setDefaults() is called."}
# Set default layout and save previous layout in variable oldDefaults
oldDefaults <- ospsuite.plots::setDefaults(defaultOptions = list(), colorMapList = NULL)

# ospsuite.plots function
ospsuite.plots::plotHistogram(data = testData, mapping = aes(x = Age)) + labs(tag = "A")

# Customized plot
ggplot(data = testData, mapping = aes(x = Obs, y = Pred, color = Sex, fill = Sex, shape = Sex)) +
  geom_point() +
  theme(legend.position = "top") +
  labs(tag = "B")
```

### 2.1.3 Reset to Previously Saved Layout

```{r reset-to-previous-defaults, warning=FALSE, fig.show='hold', fig.alt="Two plots demonstrating resetting to previously saved layout defaults. Plot A shows the histogram reverting to original default styling after resetDefaults() is called. Plot B shows the scatter plot also returning to the original ggplot defaults, confirming that the layout reset worked correctly."}
# Reset to previously saved layout options
ospsuite.plots::resetDefaults(oldDefaults = oldDefaults)

# ospsuite.plots function
ospsuite.plots::plotHistogram(data = testData, mapping = aes(x = Age)) + labs(tag = "A")

# Customized plot
ggplot(data = testData, mapping = aes(x = Obs, y = Pred, color = Sex, shape = Sex)) +
  geom_point() +
  theme(legend.position = "top") +
  labs(tag = "B")
```

## 2.2 Default Theme

Functions to set the `ospsuite.plots` default theme only are `setDefaultTheme()` and `resetDefaultTheme()`. These functions are called by `setDefaults()` and `resetDefaults()`.

```{r defaultTheme}
# Set ospsuite.plots Default Theme
oldTheme <- ospsuite.plots::setDefaultTheme()

# Customize theme using ggplot functionalities
theme_update(legend.position = "top")
theme_update(legend.title = element_blank())

# Reset to the previously saved theme
ospsuite.plots::resetDefaultTheme(oldTheme)
```

## 2.3 Default Color

Functions to set the `ospsuite.plots` default color only are `setDefaultColorMapDistinct()` and `resetDefaultColorMapDistinct()`. These functions are called by `setDefaults()` and `resetDefaults()`.

Colors are set to discrete and ordinal scales for `fill` and `colour`.

The package provides some color palettes in the object `colorMaps` (see `?colorMaps`).

The example below shows plots with:

- A plot with default settings for up to 6 different colors
- B plot with default settings for more than 6 different colors
- C customized settings for all following plots using the `colorMaps[["grays"]]`
- D customized plot: set gray scale for this plot only using function `scale_fill_grey()`
- E customized settings for all following plots using `ggsci::pal_lancet()(9)`
- F customized plots: set gray scale for this plot only using function `ggsci::scale_color_lancet()`

```{r default-color-settings-6colors, fig.alt="Tile plot demonstrating default color settings for up to 6 different colors. The plot shows a 3x2 grid of colored tiles, each representing a different discrete color from the default ospsuite.plots color palette for small categorical datasets."}
# Set ospsuite.plots Default Color
oldColors <- ospsuite.plots::setDefaultColorMapDistinct()

ggplot() +
  geom_tile(aes(x = rep(seq(1, 3), 2), y = rep(seq(1, 2), each = 3), fill = as.factor(seq(1, 6)))) +
  labs(title = "Default settings for up to 6 different colors", tag = "A") +
  theme(legend.position = "none", axis.title = element_blank())
```

```{r default-color-settings-many-colors, fig.alt="Tile plot demonstrating default color settings for more than 6 different colors. The plot shows a 7x7 grid plus 2 additional tiles (51 total), illustrating how ospsuite.plots handles large categorical datasets by cycling through and extending the color palette."}
ggplot() +
  geom_tile(aes(x = c(rep(seq(1, 7), 7), 1, 2), y = c(rep(seq(1, 7), each = 7), 8, 8), fill = as.factor(seq(1, 51)))) +
  labs(title = "Default settings for more than 6 different colors") +
  theme(legend.position = "none", axis.title = element_blank())
```

```{r customize-colors-gray, fig.alt="Tile plot demonstrating customized gray color palette. The plot shows a 3x3 grid of tiles using grayscale colors from the ospsuite.plots colorMaps gray palette, illustrating how to apply monochromatic color schemes for accessibility or publication requirements."}
# Customize colors: set to gray colors
ospsuite.plots::setDefaultColorMapDistinct(colorMaps[["grays"]])

ggplot() +
  geom_tile(aes(x = rep(seq(1, 3), 3), y = rep(seq(1, 3), each = 3), fill = as.factor(seq(1, 9)))) +
  theme(legend.position = "none", axis.title = element_blank()) +
  labs(title = "colorMaps gray", tag = "C")
```

```{r ggplot-scale-fill-grey, fig.alt="Tile plot using ggplot2's built-in scale_fill_grey() function. The plot shows a 3x3 grid of tiles demonstrating how to override ospsuite.plots defaults with standard ggplot2 gray scale functions for individual plots."}
ggplot() +
  geom_tile(aes(x = rep(seq(1, 3), 3), y = rep(seq(1, 3), each = 3), fill = as.factor(seq(1, 9)))) +
  theme(legend.position = "none", axis.title = element_blank()) +
  scale_fill_grey() +
  labs(title = "scale_fill_grey", tag = "D")
```

```{r ggsci-lancet-colors, fig.alt="Tile plot using ggsci Lancet journal color palette. The plot shows a 3x3 grid of tiles demonstrating how to set ospsuite.plots defaults to use professional journal color schemes inspired by The Lancet publication style."}
# Set to color palettes inspired by plots in Lancet journals
ospsuite.plots::setDefaultColorMapDistinct(ggsci::pal_lancet()(9))

ggplot() +
  geom_tile(aes(x = rep(seq(1, 3), 3), y = rep(seq(1, 3), each = 3), fill = as.factor(seq(1, 9)))) +
  theme(legend.position = "none", axis.title = element_blank()) +
  labs(title = "ggsci::pal_lancet", tag = "E")
```

```{r ggsci-color-lancet-override, fig.alt="Tile plot using ggsci Lancet color palette with scale override. The plot shows a 3x3 grid of tiles demonstrating how to use ggsci::scale_color_lancet() to override the default color mapping for individual plots while maintaining the Lancet color scheme."}
# Set to color palettes inspired by plots in Lancet journals
ospsuite.plots::setDefaultColorMapDistinct(ggsci::pal_lancet()(9))

ggplot() +
  geom_tile(aes(x = rep(seq(1, 3), 3), y = rep(seq(1, 3), each = 3), fill = as.factor(seq(1, 9)))) +
  theme(legend.position = "none", axis.title = element_blank()) +
  ggsci::scale_color_lancet() +
  labs(title = "ggsci::scale_color_lancet", tag = "F")
```

### Reset to Previously Saved Color Map

```{r resetColorMap}
# Reset to the previously saved color map
ospsuite.plots::resetDefaultColorMapDistinct(oldColorMaps = oldColors)
```

## 2.4 Default Shapes

All point layers produced by `ospsuite.plots` use `geom_point_osp()`, which draws from the OSP shape palette defined in `ospShapeNames`. When you build your own plots and want them to combine consistently with `ospsuite.plots` outputs, prefer `geom_point_osp()` over the raw `ggplot2::geom_point()`.

Shape ordering is controlled per plot, not via a global option:

- `geom_point_osp()` paired with `scale_shape_osp()` assigns shapes automatically from `ospShapeNames`.
- `scale_shape_osp_manual(values = c(level1 = "circle", level2 = "diamond", ...))` sets an explicit mapping.
- `scale_shape_osp_identity()` is the right choice when the data already contains shape names.

Raw `ggplot2::geom_point()` keeps using ggplot2's native pch shapes and is unaffected.

## 2.5 Default Options

`getDefaultOptions()` returns a list of options used in this package. These options are set by the function `setDefaults()` via the variable `defaultOptions`.

```{r, eval=FALSE}
ospsuite.plots::setDefaults(defaultOptions = ospsuite.plots::getDefaultOptions())
```

The names of all options defined by this package start with the package name `ospsuite.plots` as a prefix and a suffix. The suffixes are listed in the enumeration `OptionKeys`. There are two helper functions (`setOspsuite.plots.option` and `getOspsuite.plots.option`) to set and get these options.

## 2.5.1 Options to Customize Watermark

All plots in this packages are created with the function `ggplotWithWatermark()` instead of `ggplot()`. This function creates a `ggplot` with a customized print function which adds a watermark. 

The watermark is **enabled by default** — plots produced without any configuration will already carry the watermark.
Setting the option to `NULL` is treated the same as using the default, so the watermark will still appear.

No opt-in is required; you only need to interact with these options if you want to customize or remove the watermark.
To override this default in your `.Rprofile` (e.g., to disable watermarks globally):

```r
# Disable watermarks globally
options(ospsuite.plots.watermarkEnabled = FALSE)
```

You can edit your `.Rprofile` with `usethis::edit_r_profile()`.

**Attention!** If you combine plots e.g. with `cowplot:plot_grid` the default print function without watermark is called. In this case you have to add the watermark with the function `addWatermark(plotObject)` before the print.

The watermark can be customized by these options:

- Switch the watermark on and off (option key = `watermarkEnabled`, default = `TRUE`)
- Define the label (option key = `watermarkLabel`, default = "preliminary analysis")
- Customize format (option key = `watermarkFormat`, default = `list(x = 0.5, y = 0.5, color = "lightgrey", angle = 30, fontsize = 12, alpha = 0.7)`)

### Examples to Customize Watermark

- A: Change format of watermark
- B: Disable watermark
- C: Reset to default

```{r customize-watermark, fig.alt="Plot demonstrating customized watermark formatting. The plot shows a blank coordinate system with a red watermark rotated 90 degrees, positioned at specific coordinates with increased font size and reduced transparency, labeled 'NEW' instead of the default text."}
# Change format and label of watermark
setOspsuite.plots.option(optionKey = OptionKeys$watermarkFormat, value = list(x = 0.2, y = 0.6, color = "red", angle = 90, fontsize = 24, alpha = 0.2))
setOspsuite.plots.option(optionKey = OptionKeys$watermarkLabel, value = "NEW")

# Initialize plot
ggplotWithWatermark() + labs(title = "Changed Watermark", tag = "A")
```

```{r disable-watermark, fig.alt="Plot demonstrating disabled watermark functionality. The plot shows a clean blank coordinate system with no watermark text overlay, illustrating how the watermarkEnabled option can be set to FALSE for clean publication-ready plots."}
# Disable watermark
setOspsuite.plots.option(optionKey = OptionKeys$watermarkEnabled, value = FALSE)

# Initialize plot
ggplotWithWatermark() + labs(title = "No Watermark", tag = "B")
```

```{r reset-watermark-default, fig.alt="Plot demonstrating reset watermark to default settings. The plot shows a blank coordinate system with the default watermark restored - gray text reading 'preliminary analysis' at 30-degree angle in the center with standard transparency and font size."}
# Reset to default
setOspsuite.plots.option(optionKey = OptionKeys$watermarkFormat, value = NULL)
setOspsuite.plots.option(optionKey = OptionKeys$watermarkLabel, value = NULL)
setOspsuite.plots.option(optionKey = OptionKeys$watermarkEnabled, value = TRUE)

# Initialize plot
ggplotWithWatermark() + labs(title = "Default Watermark", tag = "C")
```

## 2.5.2 Options to Set the Defaults for Geom Layer Attributes

All plot functions have input variables `geom*Attributes` which are passed as variables to the corresponding ggplot layer. The defaults of the input variables can be set by options.

```{r options_defaultgeoms, echo=FALSE}
df <- rbind(
  data.frame(defaultOption = "Line", inputVariable = c("geomLineAttributes"), functions = c("plotTimeProfile()")),
  data.frame(defaultOption = "Ribbon", inputVariable = "geomRibbonAttributes", functions = c("plotTimeProfile()")),
  data.frame(defaultOption = "Point", inputVariable = "geomPointAttributes", functions = c("plotTimeProfile()", "plotResVsCov()", "plotRatioVsCov()", "plotPredVsObs()")),
  data.frame(defaultOption = "Errorbar", inputVariable = "geomErrorbarAttributes", functions = c("plotTimeProfile()", "plotResVsCov()", "plotRatioVsCov()", "plotPredVsObs()")),
  data.frame(defaultOption = "LLOQ", inputVariable = "geomLLOQAttributes", functions = c("plotTimeProfile()", "plotResVsCov()", "plotRatioVsCov()", "plotPredVsObs()")),
  data.frame(defaultOption = "Hist", inputVariable = "geomHistAttributes", functions = c("plotHistogram()")),
  data.frame(defaultOption = "Boxplot", inputVariable = c("geomBoxplotAttributes", "geomPointAttributes"), functions = c("plotBoxWhisker()", "plotBoxWhisker()")),
  data.frame(defaultOption = "ComparisonLine", inputVariable = c("geomComparisonLineAttributes"), functions = c("plotResVsCov()", "plotRatioVsCov()", "plotPredVsObs()")),
  data.frame(defaultOption = "GuestLine", inputVariable = c("geomGuestLineAttributes"), functions = c("plotResVsCov()", "plotRatioVsCov()", "plotPredVsObs()"))
) |>
  data.table::setDT() |>
  (\(x) x[, .(inputVariable = paste(inputVariable, collapse = ", ")), by = c("defaultOption", "functions")])() |>
  tidyr::pivot_wider(names_from = defaultOption, values_from = inputVariable, values_fill = " ")

knitr::kable(df, align = "c", caption = "Usage of options for geom attributes")
```

With default options:

- `LineAttributes = list()`
- `Ribbon = list(color = NA)`
- `PointAttributes = list()`
- `ErrorbarAttributes = list(width = 0)`
- `LLOQAttributes = list()`
- `ComparisonLineAttributes = list(linetype = "dashed")`
- `GuestLineAttributes = list(linetype = "dashed")`
- `BoxplotAttributes = list(position = position_dodge(width = 1), color = "black")`
- `HistAttributes = list(bins = 10, position = ggplot2::position_nudge())`

## 2.5.3 Options to Set Defaults for Aesthetics

Options to set the face alpha of ribbons, filled points and options to set the filled points for values below and above LLOQ.

```{r default-aesthetics, eval=FALSE}
# Default alpha = 0.5
getOspsuite.plots.option(optionKey = "alpha")

# Alpha of LLOQ values
c("TRUE" = 0.3, "FALSE" = 1)
getOspsuite.plots.option(optionKey = "lloqAlphaVector")

# Linetype LLOQ comparison lines
"dashed"
getOspsuite.plots.option(optionKey = "lloqLineType")
```

## 2.5.4 Options for Percentiles

There are two percentile-related options controlling default behavior:

- `percentiles`: A numeric vector of five quantiles defining the lower whisker, lower box, median, upper box, and upper whisker used by `plotBoxWhisker()` (default = `c(0.05, 0.25, 0.5, 0.75, 0.95)`).
- `defaultPercentiles`: A numeric vector of three quantiles used as the default for `plotRangeDistribution()` (default = `c(0.05, 0.5, 0.95)`).

```{r default-percentiles, eval=FALSE}
# Get current box-whisker percentiles (5 values)
getOspsuite.plots.option(optionKey = OptionKeys$percentiles)

# Change box-whisker percentiles globally
setOspsuite.plots.option(optionKey = OptionKeys$percentiles, value = c(0.1, 0.25, 0.5, 0.75, 0.9))

# Get current range-plot percentiles (3 values)
getOspsuite.plots.option(optionKey = OptionKeys$defaultPercentiles)

# Change range-plot default percentiles globally
setOspsuite.plots.option(optionKey = OptionKeys$defaultPercentiles, value = c(0.1, 0.5, 0.9))
```

## 2.5.5 Options to Define Export Format

There are options to define the export format using the function `exportPlot` (see details below):

- `exportWidth`: Width of the exported file
- `exportUnits`: Units for width and height
- `exportDevice`: Device for plot export
- `exportDpi`: Plot resolution

The latter options are used directly as input for `ggplot2::ggsave`, so check the help for available values.

# 3. Plot Functions

All plot functions listed below call internally the function `initializePlot()`. This function constructs labels from the metadata and adds a watermark layer. It can also be used to create a customized ggplot.

## 3.1 `plotTimeProfile()`

[Time Profile Plots](plot-time-profile.html)

## 3.2 `plotBoxWhisker()`

[Box Whisker Plots](box-whisker-vignette.html)

## 3.3 `plotHistogram()`

[Histogram Plots](histogram.html)

## 3.4 `plotPredVsObs()`

[Goodness of Fit](Goodness_of_fit.html)

## 3.5 `plotResVsCov()`

[Goodness of Fit](Goodness_of_fit.html)

## 3.6 `plotRatioVsCov()`

[Goodness of Fit](Goodness_of_fit.html)

## 3.7 `plotQQ()`

[Goodness of Fit](Goodness_of_fit.html)

# 4. Additional Aesthetics

This package provides some additional aesthetics.

For more details, see the examples within the vignettes for the respective functions.

- `groupby`: Shortcut to use different aesthetics to group. All functions where this aesthetic is used have also a variable `groupAesthetics`. The mapping `groupby` is copied to all aesthetics listed within this variable and to the aesthetic `group`.
- `lloq`: Mapped to a column with values indicating the lower limit of quantification, adds horizontal (or vertical) lines to the plot. All observed values below the "lloq" are plotted with a lighter alpha. As values are compared row by row, it is possible to have more than one LLOQ.
- `error`: Mapped to a column with additive error (e.g., standard deviation); error bars are plotted. This is a shortcut to map `ymin` and `ymax` directly (`ymin = y - error` and `ymax = y + error`). Additionally, if `yScale` is set, `ymin` values below 0 are set to `y`.
- `error_relative`: Mapped to a column with relative error (e.g., geometric standard deviation); error bars are plotted. This is a shortcut to map `ymin` and `ymax` directly (`ymin = y / error_relative` and `ymax = y * error_relative`).
- `y2axis`: Creates a plot with 2 y axes. It is used to map to a column with a logical value. Values where this column has a TRUE entry will be displayed with a secondary axis.
- `mdv`: Mapped to a logical column. Rows where this column has entries set to TRUE are not plotted (MDV = missing data value, taken from NONMEM notation).
- `observed` / `predicted`: For the function `plotPredVsObs()`, `observed` is mapped to `x` and `predicted` is mapped to `y`.

Residuals and ratios must be pre-calculated before passing them to the plotting functions. If you are using the `{ospsuite}` package, use `ospsuite::addResidualColumn()` to add a residual column to your data.

See `vignette("Goodness of Fit", package = "ospsuite.plots")` for examples.

```{r additional-aesthetic-table, echo=FALSE}
df <- rbind(
  data.frame(aesthetic = "`groupby`", functions = c("plotTimeProfile()", "plotHistogram()", "plotPredVsObs()", "plotResVsCov()", "plotRatioVsCov()", "plotQQ()")),
  data.frame(aesthetic = "`lloq`", functions = c("plotTimeProfile()", "plotPredVsObs()")),
  data.frame(aesthetic = "`error`", functions = c("plotTimeProfile()", "plotRatioVsCov()", "plotPredVsObs()", "plotResVsCov()")),
  data.frame(aesthetic = "`error_relative`", functions = c("plotTimeProfile()", "plotRatioVsCov()", "plotPredVsObs()", "plotResVsCov()")),
  data.frame(aesthetic = "`y2axis`", functions = "plotTimeProfile()"),
  data.frame(aesthetic = "`mdv`", functions = c("plotTimeProfile()", "plotBoxWhisker()", "plotHistogram()", "plotPredVsObs()", "plotResVsCov()", "plotRatioVsCov()", "plotQQ()")),
  data.frame(aesthetic = "`observed` / `predicted`", functions = c("plotPredVsObs()"))
) |>
  dplyr::mutate(used = "X") |>
  tidyr::pivot_wider(names_from = aesthetic, values_from = used, values_fill = " ")

knitr::kable(df, align = "c", caption = "Applicability of additional aesthetics in functions")
```

# 5. Plot Export

This section demonstrates how to use the `exportPlot` function to save `ggplot` objects to files, adjusting the width and height of the exported plots as necessary. This function is part of the `ospsuite.plots` package and simplifies the process of exporting plots for various purposes, such as publication or presentation.

## 5.1 Basic Usage

To export a plot, you need a ggplot object. Here's a basic example:

Create a simple ggplot object:

```{r export-object, eval=FALSE}
plotObject <- ospsuite.plots::plotHistogram(data = testData, mapping = aes(x = Age))
```

Exporting the Plot: Using the `exportPlot` function, you can easily save this plot to a file:

Replace "path/to/save" with the actual directory path where you want to save the plot, and adjust the width and height parameters as needed.

```{r export-basic, eval=FALSE}
exportPlot(plotObject = plotObject, filepath = "path/to/save", filename = "myplot", width = 10, height = 8)
```

## 5.2 Advanced Usage

### Adjusting Plot Dimensions Based on Content

The `exportPlot` function can automatically adjust the plot dimensions based on its content, such as the presence of a legend or the aspect ratio.

Assuming `plotObject` is your ggplot object:

```{r export-advanced, eval=FALSE}
exportPlot(plotObject = plotObject, filepath = "path/to/save", filename = "adjusted_plot.png")
```

In this case, you don't need to specify the width and height explicitly; the function calculates them for you. The default width value saved in the `ospsuite.plots` option `exportWidth` is used. If an aspect ratio is defined in the theme of the plot, height will be adjusted accordingly; otherwise, the function exports square figures.

# 6. Shapes

## 6.1 Default Shapes

```{r default-shapes, out.width = "90%", fig.asp = 0.7, fig.width = 8, fig.alt="Chart displaying all default OSP shape types available in ospsuite.plots. Shows various point shapes arranged in a grid with labels, demonstrating the visual appearance of each shape option."}
shapes <- data.frame(
  shapeNames = ospShapeNames,
  x = rep(1:6, length.out = length(ospShapeNames)),
  y = rep(1:4, each = 6, length.out = length(ospShapeNames))
)

ggplot(shapes, aes(x, y, shape = shapeNames)) +
  geom_point_osp(size = 5, color = "blue", fill = "red") +
  scale_shape_osp_identity() +
  geom_text(aes(label = shapeNames), nudge_y = -0.3, size = 3) +
  theme_void()
```

## 6.2 Using OSP Shapes in Plot Functions

OSP shapes are available in all `ospsuite.plots` functions via the default shape scale set by `setDefaults()`. You can also apply them directly with `scale_shape_osp()`.

```{r osp-shapes-demo, fig.alt="Scatter plot demonstrating OSP shapes in ospsuite.plots. Shows four data points representing different species using distinct OSP shapes with each species having a distinct symbol and color."}
oldDefaults <- ospsuite.plots::setDefaults()

dt <- data.frame(x = c(1, 2, 1, 2), y = c(1, 1, 2, 2), species = c("dog", "cat", "mouse", "rat"))

plotObject <- plotYVsX(data = dt, mapping = aes(x = x, y = y, groupby = species), xScale = "linear", xScaleArgs = list(limits = c(0.5, 2.5)), yScale = "linear", yScaleArgs = list(limits = c(0.5, 2.5)))

plot(plotObject)
```

```{r cleanup, echo=FALSE}
resetDefaults(oldDefaults)
```

```


