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")) +``` + +