diff --git a/DESCRIPTION b/DESCRIPTION index 65c6390..cef995c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -48,7 +48,8 @@ Suggests: ape, deeptime, palmerpenguins, - maps + maps, + sf Config/testthat/edition: 3 URL: https://rphylopic.palaeoverse.org, https://github.com/palaeoverse-community/rphylopic, diff --git a/NEWS.md b/NEWS.md index cecbad5..d4a8598 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # rphylopic (development version) * updated citation +* added warning when specified size is more than 1000 times smaller than the y-axis range (mostly useful for when making maps with coord_sf) (#86) # rphylopic 1.2.2 diff --git a/R/geom_phylopic.R b/R/geom_phylopic.R index 6857027..5615548 100644 --- a/R/geom_phylopic.R +++ b/R/geom_phylopic.R @@ -232,14 +232,21 @@ GeomPhylopic <- ggproto("GeomPhylopic", Geom, # Calculate height as percentage of y limits # (or r limits for polar coordinates) if ("y.range" %in% names(panel_params)) { - heights <- data$size / diff(panel_params$y.range) + y_diff <- diff(panel_params$y.range) } else if ("y_range" %in% names(panel_params)) { # exclusive to coord_sf - heights <- data$size / diff(panel_params$y_range) + y_diff <- diff(panel_params$y_range) } else if ("r.range" %in% names(panel_params)) { # exclusive to coord_polar - heights <- data$size / diff(panel_params$r.range) + y_diff <- diff(panel_params$r.range) } else { - heights <- data$size + y_diff <- 1 } + if (any(data$size < (y_diff / 1000))) { + warning(paste("Your specified silhouette `size`(s) are more than 1000", + "times smaller than your y-axis range. You probably want", + "to use a larger `size`."), call. = FALSE) + } + heights <- data$size / y_diff + # Hack to make silhouettes the full height of the plot heights[is.infinite(heights)] <- 1 diff --git a/tests/testthat/test-geom_phylopic.R b/tests/testthat/test-geom_phylopic.R index dc1904a..6b12966 100644 --- a/tests/testthat/test-geom_phylopic.R +++ b/tests/testthat/test-geom_phylopic.R @@ -54,6 +54,9 @@ test_that("geom_phylopic works", { gg <- ggplot(df) + geom_phylopic(aes(x = x, y = y), uuid = "asdfghjkl") expect_warning(plot(gg)) + gg <- ggplot(df) + + geom_phylopic(aes(x = x, y = y, uuid = uuid), size = 1E-6) + expect_warning(plot(gg)) }) test_that("phylopic_key_glyph works", { diff --git a/vignettes/b-advanced-ggplot.Rmd b/vignettes/b-advanced-ggplot.Rmd index b64c330..ff4bc3f 100644 --- a/vignettes/b-advanced-ggplot.Rmd +++ b/vignettes/b-advanced-ggplot.Rmd @@ -174,7 +174,7 @@ ggplot(penguins_subset) + Now that's a nice figure! # Geographic distribution -In much the same way as generic x-y plotting, the **rphylopic** package can be used in combination with `{ggplot2}` to plot organism silhouettes on a map. That is, to plot data points (e.g., species occurrences) as silhouettes. We provide an example here of how this might be achieved. For this application, we use the example occurrence dataset of early (Carboniferous to Early Triassic) tetrapods from the `{palaeoverse}` R package to visualize the geographic distribution of *Mesosaurus* fossils. +In much the same way as generic x-y plotting, the **rphylopic** package can be used in combination with `{ggplot2}` to plot organism silhouettes on a map. That is, to plot data points (e.g., species occurrences) as silhouettes. We provide an example here of how this might be achieved. For this application, we use the example occurrence dataset of early (Carboniferous to Early Triassic) tetrapods from the `{palaeoverse}` R package to visualize the geographic distribution of *Diplocaulus* fossils. First, let's load our libraries and the tetrapod data: @@ -184,16 +184,18 @@ First, let's load our libraries and the tetrapod data: library(rphylopic) library(ggplot2) library(palaeoverse) +library(sf) +library(maps) # Get occurrence data data(tetrapods) ``` -Then we'll subset our occurrences to only those for *Mesosaurus*: +Then we'll subset our occurrences to only those for *Diplocaulus*: ```r # Subset to desired group -tetrapods <- subset(tetrapods, genus == "Mesosaurus") +tetrapods <- subset(tetrapods, genus == "Diplocaulus") ``` Now, let's plot those occurrences on a world map. `{ggplot2}` and it's built-in function `map_data()` make this a breeze. Note that we use `alpha = 0.75` in case there are multiple occurrences in the same place. That way, the darker the color, the more occurrences in that geographic location. @@ -201,11 +203,11 @@ Now, let's plot those occurrences on a world map. `{ggplot2}` and it's built-in ```r # Get map data -world <- map_data(map = "world") +world <- st_as_sf(map("world", fill = TRUE, plot = FALSE)) +world <- st_wrap_dateline(world) # Make map -ggplot() + - geom_polygon(data = world, aes(x = long, y = lat, group = group), - fill = "lightgray", color = "darkgrey", linewidth = 0.1) + +ggplot(world) + + geom_sf(fill = "lightgray", color = "darkgrey", linewidth = 0.1) + geom_point(data = tetrapods, aes(x = lng, y = lat), size = 4, alpha = 0.75, color = "blue") + theme_void() + @@ -221,9 +223,8 @@ Now, as with the penguin figure above, we can easily replace those points with s ```r -ggplot() + - geom_polygon(data = world, aes(x = long, y = lat, group = group), - fill = "lightgray", color = "darkgrey", linewidth = 0.1) + +ggplot(world) + + geom_sf(fill = "lightgray", color = "darkgrey", linewidth = 0.1) + geom_phylopic(data = tetrapods, aes(x = lng, y = lat, name = genus), size = 4, alpha = 0.75, color = "blue") + theme_void() + @@ -237,10 +238,29 @@ ggplot() + Snazzy! -Note that while we used the genus name as the `name` aesthetic here, we easily could have done `name = "Mesosaurus"` outside of the `aes()` call instead. However, if we were plotting occurrences of multiple genera, we'd definitely want to plot them as different silhouettes using `name = genus` within the `aes()` call. +Note that while we used the genus name as the `name` aesthetic here, we easily could have done `name = "Diplocaulus"` outside of the `aes()` call instead. However, if we were plotting occurrences of multiple genera, we'd definitely want to plot them as different silhouettes using `name = genus` within the `aes()` call. Also, note that we could change the projection of the map and data using the `crs` and `default_crs` arguments in `coord_sf()`. When projecting data, note that the y-axis limits will change to projected limits. For example, in the Robinson projection, the y-axis limits are roughly -8,600,000 and 8,600,000 in projected coordinates. Therefore, you may need to adjust the `size` argument/aesthetic accordingly when projecting maps and data. + +```r +# Set up a bounding box +bbox <- st_graticule(crs = st_crs("ESRI:54030"), + lat = c(-89.9, 89.9), lon = c(-179.9, 179.9)) +ggplot(world) + + geom_sf(fill = "lightgray", color = "darkgrey", linewidth = 0.1) + + geom_phylopic(data = tetrapods, aes(x = lng, y = lat, name = genus), + size = 4E5, alpha = 0.75, color = "blue") + + geom_sf(data = bbox) + + theme_void() + + coord_sf(default_crs = st_crs(4326), crs = st_crs("ESRI:54030")) +``` + +
+plot of chunk ggplot-geog-plot-3 +

plot of chunk ggplot-geog-plot-3

+
+ # Phylogenetics Another common use case of PhyloPic silhouettes is to represent taxonomic information. In this example, we demonstrate how to use silhouettes within a phylogenetic framework. In this case, the phylogeny, taken from the `{phytools}` package, includes taxa across all vertebrates. Even many taxonomic experts are unlikely to know the scientific names of these 11 disparate taxa, so we'll replace the names with PhyloPic silhouettes. First, let's load our libraries and data: diff --git a/vignettes/b-advanced-ggplot.Rmd.orig b/vignettes/b-advanced-ggplot.Rmd.orig index bd522da..aee3b95 100644 --- a/vignettes/b-advanced-ggplot.Rmd.orig +++ b/vignettes/b-advanced-ggplot.Rmd.orig @@ -141,7 +141,7 @@ ggplot(penguins_subset) + Now that's a nice figure! # Geographic distribution -In much the same way as generic x-y plotting, the **rphylopic** package can be used in combination with `{ggplot2}` to plot organism silhouettes on a map. That is, to plot data points (e.g., species occurrences) as silhouettes. We provide an example here of how this might be achieved. For this application, we use the example occurrence dataset of early (Carboniferous to Early Triassic) tetrapods from the `{palaeoverse}` R package to visualize the geographic distribution of *Mesosaurus* fossils. +In much the same way as generic x-y plotting, the **rphylopic** package can be used in combination with `{ggplot2}` to plot organism silhouettes on a map. That is, to plot data points (e.g., species occurrences) as silhouettes. We provide an example here of how this might be achieved. For this application, we use the example occurrence dataset of early (Carboniferous to Early Triassic) tetrapods from the `{palaeoverse}` R package to visualize the geographic distribution of *Diplocaulus* fossils. First, let's load our libraries and the tetrapod data: @@ -150,26 +150,28 @@ First, let's load our libraries and the tetrapod data: library(rphylopic) library(ggplot2) library(palaeoverse) +library(sf) +library(maps) # Get occurrence data data(tetrapods) ``` -Then we'll subset our occurrences to only those for *Mesosaurus*: +Then we'll subset our occurrences to only those for *Diplocaulus*: ```{r} # Subset to desired group -tetrapods <- subset(tetrapods, genus == "Mesosaurus") +tetrapods <- subset(tetrapods, genus == "Diplocaulus") ``` Now, let's plot those occurrences on a world map. `{ggplot2}` and it's built-in function `map_data()` make this a breeze. Note that we use `alpha = 0.75` in case there are multiple occurrences in the same place. That way, the darker the color, the more occurrences in that geographic location. ```{r ggplot-geog-plot-1, fig.height = 3.5} # Get map data -world <- map_data(map = "world") +world <- st_as_sf(map("world", fill = TRUE, plot = FALSE)) +world <- st_wrap_dateline(world) # Make map -ggplot() + - geom_polygon(data = world, aes(x = long, y = lat, group = group), - fill = "lightgray", color = "darkgrey", linewidth = 0.1) + +ggplot(world) + + geom_sf(fill = "lightgray", color = "darkgrey", linewidth = 0.1) + geom_point(data = tetrapods, aes(x = lng, y = lat), size = 4, alpha = 0.75, color = "blue") + theme_void() + @@ -179,9 +181,8 @@ ggplot() + Now, as with the penguin figure above, we can easily replace those points with silhouettes. ```{r ggplot-geog-plot-2, fig.height = 3.5, warning = FALSE} -ggplot() + - geom_polygon(data = world, aes(x = long, y = lat, group = group), - fill = "lightgray", color = "darkgrey", linewidth = 0.1) + +ggplot(world) + + geom_sf(fill = "lightgray", color = "darkgrey", linewidth = 0.1) + geom_phylopic(data = tetrapods, aes(x = lng, y = lat, name = genus), size = 4, alpha = 0.75, color = "blue") + theme_void() + @@ -190,10 +191,23 @@ ggplot() + Snazzy! -Note that while we used the genus name as the `name` aesthetic here, we easily could have done `name = "Mesosaurus"` outside of the `aes()` call instead. However, if we were plotting occurrences of multiple genera, we'd definitely want to plot them as different silhouettes using `name = genus` within the `aes()` call. +Note that while we used the genus name as the `name` aesthetic here, we easily could have done `name = "Diplocaulus"` outside of the `aes()` call instead. However, if we were plotting occurrences of multiple genera, we'd definitely want to plot them as different silhouettes using `name = genus` within the `aes()` call. Also, note that we could change the projection of the map and data using the `crs` and `default_crs` arguments in `coord_sf()`. When projecting data, note that the y-axis limits will change to projected limits. For example, in the Robinson projection, the y-axis limits are roughly -8,600,000 and 8,600,000 in projected coordinates. Therefore, you may need to adjust the `size` argument/aesthetic accordingly when projecting maps and data. +```{r ggplot-geog-plot-3, fig.height = 3.5, warning = FALSE} +# Set up a bounding box +bbox <- st_graticule(crs = st_crs("ESRI:54030"), + lat = c(-89.9, 89.9), lon = c(-179.9, 179.9)) +ggplot(world) + + geom_sf(fill = "lightgray", color = "darkgrey", linewidth = 0.1) + + geom_phylopic(data = tetrapods, aes(x = lng, y = lat, name = genus), + size = 4E5, alpha = 0.75, color = "blue") + + geom_sf(data = bbox) + + theme_void() + + coord_sf(default_crs = st_crs(4326), crs = st_crs("ESRI:54030")) +``` + # Phylogenetics Another common use case of PhyloPic silhouettes is to represent taxonomic information. In this example, we demonstrate how to use silhouettes within a phylogenetic framework. In this case, the phylogeny, taken from the `{phytools}` package, includes taxa across all vertebrates. Even many taxonomic experts are unlikely to know the scientific names of these 11 disparate taxa, so we'll replace the names with PhyloPic silhouettes. First, let's load our libraries and data: diff --git a/vignettes/ggplot-geog-plot-1-1.png b/vignettes/ggplot-geog-plot-1-1.png index e505091..93f3dd6 100644 Binary files a/vignettes/ggplot-geog-plot-1-1.png and b/vignettes/ggplot-geog-plot-1-1.png differ diff --git a/vignettes/ggplot-geog-plot-2-1.png b/vignettes/ggplot-geog-plot-2-1.png index cfe9ceb..236ec78 100644 Binary files a/vignettes/ggplot-geog-plot-2-1.png and b/vignettes/ggplot-geog-plot-2-1.png differ diff --git a/vignettes/ggplot-geog-plot-3-1.png b/vignettes/ggplot-geog-plot-3-1.png new file mode 100644 index 0000000..605d54f Binary files /dev/null and b/vignettes/ggplot-geog-plot-3-1.png differ