├── .github ├── .gitignore ├── workflows │ ├── lint.yaml │ ├── pkgdown.yaml │ ├── test-coverage.yaml │ ├── R-CMD-check.yaml │ ├── revdepcheck.yml │ └── rhub.yaml └── CONTRIBUTING.md ├── vignettes ├── .gitignore ├── coord_geo-1.png ├── coord_geo-2.png ├── phylogenies-1.png ├── phylogenies-2.png ├── phylogenies-3.png ├── phylogenies-4.png ├── phylogenies-5.png ├── phylogenies-6.png ├── phylogenies-7.png ├── phylogenies-8.png ├── coord.Rmd ├── ggarrange2.Rmd └── traits.Rmd ├── data ├── eons.rda ├── eras.rda ├── epochs.rda ├── periods.rda ├── stages.rda └── FGDC_names.rda ├── pkgdown ├── extra.css └── favicon │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── apple-touch-icon.png │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── web-app-manifest-192x192.png │ ├── web-app-manifest-512x512.png │ └── site.webmanifest ├── man ├── roxygen │ └── meta.R ├── figures │ ├── logo.png │ ├── ggarrange2.png │ ├── example_facet.png │ ├── example_left.png │ ├── example_phylo.png │ ├── example_stack.png │ ├── example_bottom.png │ ├── example_fittext.png │ ├── separate_scales.png │ ├── disparity_ggplot.png │ ├── disparity_lattice.png │ ├── example_discrete.png │ ├── example_left_right.png │ ├── example_patterns.png │ ├── example_phylogeny.png │ ├── example_fossil_phylo.png │ ├── example_points_range.png │ ├── example_discrete_multiple.png │ ├── lifecycle-stable.svg │ ├── lifecycle-defunct.svg │ ├── lifecycle-archived.svg │ ├── lifecycle-maturing.svg │ ├── lifecycle-deprecated.svg │ ├── lifecycle-superseded.svg │ ├── lifecycle-experimental.svg │ └── lifecycle-questioning.svg ├── panel.disparity.Rd ├── deeptime-package.Rd ├── eons.Rd ├── eras.Rd ├── epochs.Rd ├── stages.Rd ├── periods.Rd ├── fgdc_names.Rd ├── gtable_frame2.Rd ├── gggeo_scale.Rd ├── coord_trans_flip.Rd ├── fgdc_dict.Rd ├── ggarrange2.Rd ├── geo_pattern.Rd ├── gggeo_scale_old.Rd ├── disparity_through_time.Rd ├── get_scale_data.Rd ├── coord_trans_xy.Rd ├── grid.pattern_geo.Rd ├── scale_geo.Rd ├── geom_phylomorpho.Rd ├── scale_fill_geopattern.Rd ├── facet_wrap_color.Rd └── facet_grid_color.Rd ├── tests ├── testthat.R └── testthat │ ├── test-gggeo_scale.R │ ├── test-gggeo_scale_old.R │ ├── test-disparity_through_time.R │ ├── helper-vdiffr.R │ ├── test-phylomorpho.R │ ├── test-coord_trans_flip.R │ ├── test-get_scale_data.R │ ├── test-scales.R │ ├── test-coord_trans_xy.R │ ├── test-points_range.R │ ├── test-coord_geo_radial.R │ ├── test-geom_text_phylo.R │ ├── test-coord_geo_polar.R │ ├── test-ggarrange2.R │ ├── setup-data.R │ └── test-patterns.R ├── codecov.yml ├── R ├── deeptime-package.R ├── zzz.R ├── gggeo_scale.R ├── scales.R ├── gggeo_scale_old.R ├── coord_trans_flip.R ├── phylomorpho.R ├── get_scale_data.R ├── disparity_through_time.R └── data.R ├── .Rbuildignore ├── data-raw ├── fgdc_names.R ├── ICS_data.R └── names.txt ├── deeptime.Rproj ├── inst └── CITATION ├── .zenodo.json ├── .gitignore ├── cran-comments.md ├── DESCRIPTION ├── _pkgdown.yml └── NAMESPACE /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | NAPC_poster.Rmd 4 | -------------------------------------------------------------------------------- /data/eons.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/data/eons.rda -------------------------------------------------------------------------------- /data/eras.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/data/eras.rda -------------------------------------------------------------------------------- /pkgdown/extra.css: -------------------------------------------------------------------------------- 1 | .headroom--unpinned { 2 | transform: translateY(0%); 3 | } -------------------------------------------------------------------------------- /data/epochs.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/data/epochs.rda -------------------------------------------------------------------------------- /data/periods.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/data/periods.rda -------------------------------------------------------------------------------- /data/stages.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/data/stages.rda -------------------------------------------------------------------------------- /data/FGDC_names.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/data/FGDC_names.rda -------------------------------------------------------------------------------- /man/roxygen/meta.R: -------------------------------------------------------------------------------- 1 | list( 2 | rd_family_title = list(patterns = "FGDC patterns:") 3 | ) 4 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(deeptime) 3 | 4 | test_check("deeptime") 5 | -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/logo.png -------------------------------------------------------------------------------- /man/figures/ggarrange2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/ggarrange2.png -------------------------------------------------------------------------------- /vignettes/coord_geo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/vignettes/coord_geo-1.png -------------------------------------------------------------------------------- /vignettes/coord_geo-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/vignettes/coord_geo-2.png -------------------------------------------------------------------------------- /man/figures/example_facet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_facet.png -------------------------------------------------------------------------------- /man/figures/example_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_left.png -------------------------------------------------------------------------------- /man/figures/example_phylo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_phylo.png -------------------------------------------------------------------------------- /man/figures/example_stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_stack.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/favicon.ico -------------------------------------------------------------------------------- /vignettes/phylogenies-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/vignettes/phylogenies-1.png -------------------------------------------------------------------------------- /vignettes/phylogenies-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/vignettes/phylogenies-2.png -------------------------------------------------------------------------------- /vignettes/phylogenies-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/vignettes/phylogenies-3.png -------------------------------------------------------------------------------- /vignettes/phylogenies-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/vignettes/phylogenies-4.png -------------------------------------------------------------------------------- /vignettes/phylogenies-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/vignettes/phylogenies-5.png -------------------------------------------------------------------------------- /vignettes/phylogenies-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/vignettes/phylogenies-6.png -------------------------------------------------------------------------------- /vignettes/phylogenies-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/vignettes/phylogenies-7.png -------------------------------------------------------------------------------- /vignettes/phylogenies-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/vignettes/phylogenies-8.png -------------------------------------------------------------------------------- /man/figures/example_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_bottom.png -------------------------------------------------------------------------------- /man/figures/example_fittext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_fittext.png -------------------------------------------------------------------------------- /man/figures/separate_scales.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/separate_scales.png -------------------------------------------------------------------------------- /man/figures/disparity_ggplot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/disparity_ggplot.png -------------------------------------------------------------------------------- /man/figures/disparity_lattice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/disparity_lattice.png -------------------------------------------------------------------------------- /man/figures/example_discrete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_discrete.png -------------------------------------------------------------------------------- /man/figures/example_left_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_left_right.png -------------------------------------------------------------------------------- /man/figures/example_patterns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_patterns.png -------------------------------------------------------------------------------- /man/figures/example_phylogeny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_phylogeny.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/favicon-96x96.png -------------------------------------------------------------------------------- /man/figures/example_fossil_phylo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_fossil_phylo.png -------------------------------------------------------------------------------- /man/figures/example_points_range.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_points_range.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /man/figures/example_discrete_multiple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/man/figures/example_discrete_multiple.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /pkgdown/favicon/web-app-manifest-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/web-app-manifest-192x192.png -------------------------------------------------------------------------------- /pkgdown/favicon/web-app-manifest-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willgearty/deeptime/HEAD/pkgdown/favicon/web-app-manifest-512x512.png -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | threshold: 0.1% 6 | patch: no 7 | 8 | comment: false 9 | -------------------------------------------------------------------------------- /R/deeptime-package.R: -------------------------------------------------------------------------------- 1 | #' @keywords internal 2 | "_PACKAGE" 3 | 4 | ## usethis namespace: start 5 | #' @import rlang scales grImport2 deeptimedata 6 | #' @importFrom lifecycle deprecated 7 | ## usethis namespace: end 8 | NULL 9 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^\.travis\.yml$ 4 | ^data-raw$ 5 | ^\.github$ 6 | cran-comments.md 7 | ^CRAN-RELEASE$ 8 | ^CRAN-SUBMISSION$ 9 | ^revdep$ 10 | codecov.yml 11 | ^LICENSE\.md$ 12 | ^_pkgdown\.yml$ 13 | ^docs$ 14 | ^doc$ 15 | ^pkgdown$ 16 | .zenodo.json 17 | -------------------------------------------------------------------------------- /data-raw/fgdc_names.R: -------------------------------------------------------------------------------- 1 | # names.txt is modified from the file in Daven Quinn's GitHub repository: 2 | # https://github.com/davenquinn/geologic-patterns/blob/master/docs/names.txt 3 | fgdc_names <- read.table("data-raw/names.txt", sep = "\t", header = FALSE) 4 | colnames(fgdc_names) <- c("code", "name") 5 | 6 | usethis::use_data(fgdc_names, overwrite = TRUE) 7 | -------------------------------------------------------------------------------- /tests/testthat/test-gggeo_scale.R: -------------------------------------------------------------------------------- 1 | test_that("gggeo_scale() is deprecated", { 2 | skip_if_not_installed("divDyn") 3 | p <- ggplot(coral_div) + 4 | geom_line(aes(x = stage_age, y = n)) + 5 | scale_x_reverse("Age (Ma)") + 6 | ylab("Coral Genera") + 7 | coord_cartesian(xlim = c(250, 0), ylim = c(0, 1700), expand = FALSE) + 8 | theme_classic() 9 | lifecycle::expect_defunct(gggeo_scale(p)) 10 | }) 11 | -------------------------------------------------------------------------------- /tests/testthat/test-gggeo_scale_old.R: -------------------------------------------------------------------------------- 1 | test_that("gggeo_scale_old() is deprecated", { 2 | skip_if_not_installed("divDyn") 3 | p <- ggplot(coral_div) + 4 | geom_line(aes(x = stage_age, y = n)) + 5 | scale_x_reverse("Age (Ma)") + 6 | ylab("Coral Genera") + 7 | coord_cartesian(xlim = c(250, 0), ylim = c(0, 1700), expand = FALSE) + 8 | theme_classic() 9 | lifecycle::expect_defunct(gggeo_scale_old(p)) 10 | }) 11 | -------------------------------------------------------------------------------- /pkgdown/favicon/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/web-app-manifest-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png", 9 | "purpose": "maskable" 10 | }, 11 | { 12 | "src": "/web-app-manifest-512x512.png", 13 | "sizes": "512x512", 14 | "type": "image/png", 15 | "purpose": "maskable" 16 | } 17 | ], 18 | "theme_color": "#ffffff", 19 | "background_color": "#ffffff", 20 | "display": "standalone" 21 | } -------------------------------------------------------------------------------- /deeptime.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | ProjectId: 719c35b5-e115-4afc-b2cd-2758bae0317a 3 | 4 | RestoreWorkspace: No 5 | SaveWorkspace: No 6 | AlwaysSaveHistory: Default 7 | 8 | EnableCodeIndexing: Yes 9 | UseSpacesForTab: Yes 10 | NumSpacesForTab: 2 11 | Encoding: UTF-8 12 | 13 | RnwWeave: Sweave 14 | LaTeX: pdfLaTeX 15 | 16 | AutoAppendNewline: Yes 17 | StripTrailingWhitespace: Yes 18 | 19 | BuildType: Package 20 | PackageUseDevtools: Yes 21 | PackageInstallArgs: --no-multiarch --with-keep.source 22 | PackageRoxygenize: rd,collate,namespace 23 | -------------------------------------------------------------------------------- /tests/testthat/test-disparity_through_time.R: -------------------------------------------------------------------------------- 1 | test_that("disparity_through_time() works", { 2 | skip_if_not_installed("dispRity") 3 | 4 | crinoids <- as.data.frame(demo_data$wright$matrix[[1]][, 1:2]) 5 | crinoids$time <- "before extinction" 6 | crinoids$time[demo_data$wright$subsets$after$elements] <- "after extinction" 7 | crinoids$time <- factor(crinoids$time) 8 | attach(crinoids) 9 | gg <- disparity_through_time(time ~ V1 * V2, 10 | groups = time, aspect = c(2, 1), xlim = c(-.6, .6), ylim = c(-.5, .5), 11 | col.regions = "lightgreen", col.point = c("red", "blue") 12 | ) 13 | expect_true(is(gg, "trellis")) 14 | expect_doppelganger_deeptime("disparity_through_time()", gg) 15 | }) 16 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | citHeader("To cite deeptime in publications, use the following citation:") 2 | 3 | bibentry( 4 | bibtype = "Article", 5 | title = "deeptime: an R package that facilitates highly customizable and reproducible visualizations of data over geological time intervals", 6 | author = as.person("William Gearty"), 7 | journal = "Big Earth Data", 8 | year = "2025", 9 | doi = "10.1080/20964471.2025.2537516", 10 | textVersion = paste("Gearty, W. 2025.", 11 | "deeptime: an R package that facilitates highly customizable and reproducible visualizations of data over geological time intervals.", 12 | "Big Earth Data.", 13 | "doi: 10.1080/20964471.2025.2537516") 14 | ) 15 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "creators": [ 3 | { 4 | "affiliation": "Syracuse University", 5 | "name": "Gearty, William", 6 | "orcid": "0000-0003-0076-3262" 7 | } 8 | ], 9 | "keywords": [ 10 | "R", 11 | "data visualization", 12 | "ggplot2", 13 | "geology", 14 | "paleontology", 15 | "reproducible", 16 | "earth science" 17 | ], 18 | "related_identifiers": [ 19 | { 20 | "identifier": "https://doi.org/10.1080/20964471.2025.2537516", 21 | "relation": "isDescribedBy", 22 | "resource_type": "publication-article" 23 | } 24 | ], 25 | "license": { 26 | "id": "GPL-3.0-only" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /man/panel.disparity.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/disparity_through_time.R 3 | \name{panel.disparity} 4 | \alias{panel.disparity} 5 | \title{Combined wireframe and cloud panel} 6 | \usage{ 7 | panel.disparity(x, y, z, groups, subscripts, ...) 8 | } 9 | \arguments{ 10 | \item{x, y, z, groups, subscripts, ...}{Same as for \code{\link[lattice:panel.cloud]{lattice::panel.cloud()}}} 11 | } 12 | \value{ 13 | No return value, plots the results of both \code{\link[lattice:panel.cloud]{lattice::panel.cloud()}} 14 | and \code{\link[lattice:panel.cloud]{lattice::panel.wireframe()}}. 15 | } 16 | \description{ 17 | Plots the provided data on 2-D surfaces within a 3-D framework. See 18 | \code{\link[=disparity_through_time]{disparity_through_time()}}. 19 | } 20 | -------------------------------------------------------------------------------- /tests/testthat/helper-vdiffr.R: -------------------------------------------------------------------------------- 1 | # Copied from ggplot2 2 | 3 | # By default, if vdiffr is not installed, all visual tests are skipped unless 4 | # VDIFFR_RUN_TESTS is explicitly set to "true", which should be the case only on 5 | # a GitHub Actions CI runner with stable version of R. 6 | 7 | if (requireNamespace("vdiffr", quietly = TRUE) && 8 | utils::packageVersion("testthat") >= "3.0.3") { 9 | expect_doppelganger <- vdiffr::expect_doppelganger 10 | } else { 11 | # If vdiffr is not available and visual tests are explicitly required, 12 | # raise error. 13 | if (identical(Sys.getenv("VDIFFR_RUN_TESTS"), "true")) { 14 | abort("vdiffr is not installed") 15 | } 16 | 17 | # Otherwise, assign a dummy function 18 | expect_doppelganger <- function(...) skip("vdiffr is not installed.") 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # History files 2 | .Rhistory 3 | .Rapp.history 4 | 5 | # Session Data files 6 | .RData 7 | 8 | # Example code in package build process 9 | *-Ex.R 10 | 11 | # Output files from R CMD build 12 | /*.tar.gz 13 | 14 | # Output files from R CMD check 15 | /*.Rcheck/ 16 | 17 | # RStudio files 18 | .Rproj.user/ 19 | 20 | # produced vignettes 21 | vignettes/*.html 22 | vignettes/*.pdf 23 | 24 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 25 | .httr-oauth 26 | 27 | # knitr and R markdown default cache directories 28 | /*_cache/ 29 | /cache/ 30 | 31 | # Temporary files created by R markdown 32 | *.utf8.md 33 | *.knit.md 34 | 35 | # Shiny token, see https://shiny.rstudio.com/articles/shinyapps.html 36 | rsconnect/ 37 | /revdep 38 | 39 | /tests/testthat/Rplots.pdf 40 | 41 | inst/doc 42 | docs 43 | 44 | /doc/ 45 | -------------------------------------------------------------------------------- /tests/testthat/test-phylomorpho.R: -------------------------------------------------------------------------------- 1 | test_that("geom_phylomorpho works", { 2 | skip_if_not_installed("ape") 3 | skip_if_not_installed("phytools") 4 | library(ape) 5 | set.seed(1234) 6 | tr <- rtree(10) 7 | dat <- data.frame( 8 | x = runif(10), y = runif(10), label = tr$tip.label, 9 | row.names = tr$tip.label 10 | ) 11 | gg <- ggplot(dat) + 12 | geom_phylomorpho(tr, aes(x = x, y = y, label = label), 13 | seg_args = list(color = "blue") 14 | ) + 15 | geom_label(aes(x = x, y = y, label = label), size = 5) + 16 | theme_classic(base_size = 16) 17 | expect_true(is_ggplot(gg)) 18 | expect_true(is(gg$layers[[1]]$geom, "GeomSegment")) 19 | expect_true(is(gg$layers[[1]]$stat, "StatPhylomorpho")) 20 | expect_true(is(gg$layers[[2]]$geom, "GeomPoint")) 21 | expect_true(is(gg$layers[[2]]$stat, "StatIdentity")) 22 | expect_doppelganger_deeptime("geom_phylomorpho", gg) 23 | }) 24 | -------------------------------------------------------------------------------- /.github/workflows/lint.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: lint 10 | 11 | jobs: 12 | lint: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - uses: r-lib/actions/setup-r@v2 20 | with: 21 | use-public-rspm: true 22 | 23 | - uses: r-lib/actions/setup-r-dependencies@v2 24 | with: 25 | extra-packages: any::lintr, local::. 26 | needs: lint 27 | 28 | - name: Lint 29 | run: lintr::lint_package() 30 | shell: Rscript {0} 31 | env: 32 | LINTR_ERROR_ON_LINT: false 33 | -------------------------------------------------------------------------------- /man/figures/lifecycle-stable.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclestablestable -------------------------------------------------------------------------------- /man/figures/lifecycle-defunct.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecycledefunctdefunct -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | This patch (2.3.1) fixes a bug that was discovered right after publishing the latest minor release (2.3.0). Existing CRAN check result errors appear to be related to failures in the geojsonsf package, a dependency of multiple SUGGESTS. 2 | 3 | ## Test environments (with Github Actions) 4 | 5 | * Windows 10.0.26100 (x86_64-w64-mingw32): R 4.5.2 6 | * Mac OS X 15.7.1 (aarch64-apple-darwin20): R 4.5.2 7 | * Ubuntu 24.04.3 (x86_64-pc-linux-gnu): R 4.4.3, 4.5.2, and devel (r89059) 8 | 9 | * All checks were run separately with ggplot2 4.0.1 and 4.0.1.9000 10 | 11 | ## R CMD check results 12 | There were no ERRORs, WARNINGs, or NOTEs. 13 | 14 | ## Downstream dependencies 15 | Checked 4 reverse dependencies, comparing R CMD check results across CRAN and dev versions of this package: 16 | 17 | * EvoPhylo (0.3.5) 18 | * RevGadgets (1.2.1) 19 | * rmacrostrat (1.0.0) 20 | * rphylopic (1.6.0) 21 | 22 | ### Dependency check results: 23 | All packages passed. 24 | -------------------------------------------------------------------------------- /man/figures/lifecycle-archived.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclearchivedarchived -------------------------------------------------------------------------------- /man/figures/lifecycle-maturing.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclematuringmaturing -------------------------------------------------------------------------------- /man/figures/lifecycle-deprecated.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecycledeprecateddeprecated -------------------------------------------------------------------------------- /man/figures/lifecycle-superseded.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclesupersededsuperseded -------------------------------------------------------------------------------- /man/figures/lifecycle-experimental.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecycleexperimentalexperimental -------------------------------------------------------------------------------- /man/figures/lifecycle-questioning.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclequestioningquestioning -------------------------------------------------------------------------------- /tests/testthat/test-coord_trans_flip.R: -------------------------------------------------------------------------------- 1 | test_that("coord_trans_flip() works", { 2 | gg <- ggplot(mtcars, aes(disp, wt)) + 3 | geom_point() + 4 | coord_trans_flip(x = "log10", y = "log10", 5 | xlim = c(50, 500), ylim = c(1, 6), expand = FALSE) 6 | expect_true(is_ggplot(gg)) 7 | params <- ggplot_build(gg)$layout$panel_params[[1]] 8 | expect_equal(params$x.range, log10(c(1, 6))) 9 | expect_equal(params$y.range, log10(c(50, 500))) 10 | expect_doppelganger_deeptime("coord_trans_flip()", gg) 11 | 12 | gg <- ggplot(mtcars, aes(disp, wt)) + 13 | geom_point() + 14 | coord_trans_flip(x = "sqrt", y = "pseudo_log", 15 | xlim = c(50, 500), ylim = c(1, 6), expand = FALSE) 16 | expect_true(is_ggplot(gg)) 17 | params <- ggplot_build(gg)$layout$panel_params[[1]] 18 | expect_equal(params$x.range, scales::pseudo_log_trans()$transform(c(1, 6))) 19 | expect_equal(params$y.range, sqrt(c(50, 500))) 20 | expect_doppelganger_deeptime("coord_trans_flip() with diff trans", 21 | gg) 22 | }) 23 | -------------------------------------------------------------------------------- /man/deeptime-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deeptime-package.R 3 | \docType{package} 4 | \name{deeptime-package} 5 | \alias{deeptime} 6 | \alias{deeptime-package} 7 | \title{deeptime: Plotting Tools for Anyone Working in Deep Time} 8 | \description{ 9 | \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} 10 | 11 | Extends the functionality of other plotting packages (notably 'ggplot2') to help facilitate the plotting of data over long time intervals, including, but not limited to, geological, evolutionary, and ecological data. The primary goal of 'deeptime' is to enable users to add highly customizable timescales to their visualizations. Other functions are also included to assist with other areas of deep time visualization. 12 | } 13 | \seealso{ 14 | Useful links: 15 | \itemize{ 16 | \item \url{https://williamgearty.com/deeptime/} 17 | \item \url{https://github.com/willgearty/deeptime} 18 | \item Report bugs at \url{https://github.com/willgearty/deeptime/issues} 19 | } 20 | 21 | } 22 | \author{ 23 | \strong{Maintainer}: William Gearty \email{willgearty@gmail.com} (\href{https://orcid.org/0000-0003-0076-3262}{ORCID}) 24 | 25 | } 26 | \keyword{internal} 27 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onLoad <- function(...) { 2 | # coord_geo_polar theme elements 3 | ggplot2::register_theme_elements( 4 | deeptime.scale.background = ggplot2::element_rect(fill = NA, color = NA), 5 | deeptime.axis.line.r = ggplot2::element_line(), 6 | deeptime.axis.text.r = ggplot2::element_text(size = 3.5, vjust = -2, 7 | hjust = -0.5), 8 | deeptime.axis.ticks.r = ggplot2::element_line(), 9 | deeptime.axis.ticks.length.r = grid::unit(1.5, "points"), 10 | element_tree = list( 11 | deeptime.scale.background = ggplot2::el_def("element_rect", "rect"), 12 | deeptime.axis.line.r = ggplot2::el_def("element_line", "line", 13 | "axis.line"), 14 | deeptime.axis.text.r = ggplot2::el_def("element_text", "text", 15 | "axis.text"), 16 | deeptime.axis.ticks.r = ggplot2::el_def("element_line", "line", 17 | "axis.ticks"), 18 | deeptime.axis.ticks.length.r = ggplot2::el_def("unit", 19 | "axis.ticks.length") 20 | ) 21 | ) 22 | 23 | options(ggpattern_geometry_funcs = list(geo = grid.pattern_geo)) 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | jobs: 15 | pkgdown: 16 | runs-on: ubuntu-latest 17 | # Only restrict concurrency for non-PR jobs 18 | concurrency: 19 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 20 | env: 21 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - uses: r-lib/actions/setup-pandoc@v2 26 | 27 | - uses: r-lib/actions/setup-r@v2 28 | with: 29 | use-public-rspm: true 30 | 31 | - uses: r-lib/actions/setup-r-dependencies@v2 32 | with: 33 | extra-packages: any::pkgdown, local::. 34 | needs: website 35 | 36 | - name: Build site 37 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 38 | shell: Rscript {0} 39 | 40 | - name: Deploy to GitHub pages 🚀 41 | if: github.event_name != 'pull_request' 42 | uses: JamesIves/github-pages-deploy-action@v4.5.0 43 | with: 44 | clean: false 45 | branch: gh-pages 46 | folder: docs 47 | -------------------------------------------------------------------------------- /man/eons.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{eons} 5 | \alias{eons} 6 | \title{Eon data from the International Commission on Stratigraphy (v2024/12)} 7 | \format{ 8 | A data frame with 3 rows and 5 variables: 9 | \describe{ 10 | \item{name}{eon name} 11 | \item{max_age}{maximum age, in millions of years} 12 | \item{min_age}{minimum age, in millions of years} 13 | \item{abbr}{eon name abbreviations} 14 | \item{color}{the colors for each eon, according to the Commission for the 15 | Geological Map of the World} 16 | \item{lab_color}{the label colors for each eon, either white or black, 17 | whichever has better contrast with the background color, based on 18 | \href{https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en}{recommendations by the International Telecommunication Union}} 19 | } 20 | } 21 | \source{ 22 | \url{https://stratigraphy.org} via \url{https://macrostrat.org/api/v2/defs/intervals?timescale=international\%20eons} 23 | } 24 | \usage{ 25 | eons 26 | } 27 | \description{ 28 | A dataset containing the boundary ages, abbreviations, and colors for the 29 | eons of the Geologic Time Scale. Based on The ICS International 30 | Chronostratigraphic Chart (v2024/12), by Cohen, Finney, Gibbard, and Fan. 31 | } 32 | \seealso{ 33 | Other built-in timescales: 34 | \code{\link{epochs}}, 35 | \code{\link{eras}}, 36 | \code{\link{periods}}, 37 | \code{\link{stages}} 38 | } 39 | \concept{built-in timescales} 40 | \keyword{datasets} 41 | -------------------------------------------------------------------------------- /man/eras.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{eras} 5 | \alias{eras} 6 | \title{Era data from the International Commission on Stratigraphy (v2024/12)} 7 | \format{ 8 | A data frame with 10 rows and 5 variables: 9 | \describe{ 10 | \item{name}{era name} 11 | \item{max_age}{maximum age, in millions of years} 12 | \item{min_age}{minimum age, in millions of years} 13 | \item{abbr}{era name abbreviations} 14 | \item{color}{the colors for each era, according to the Commission for the 15 | Geological Map of the World} 16 | \item{lab_color}{the label colors for each era, either white or black, 17 | whichever has better contrast with the background color, based on 18 | \href{https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en}{recommendations by the International Telecommunication Union}} 19 | } 20 | } 21 | \source{ 22 | \url{https://stratigraphy.org} via \url{https://macrostrat.org/api/v2/defs/intervals?timescale=international\%20eras} 23 | } 24 | \usage{ 25 | eras 26 | } 27 | \description{ 28 | A dataset containing the boundary ages, abbreviations, and colors for the 29 | eras of the Geologic Time Scale. Based on The ICS International 30 | Chronostratigraphic Chart (v2024/12), by Cohen, Finney, Gibbard, and Fan. 31 | } 32 | \seealso{ 33 | Other built-in timescales: 34 | \code{\link{eons}}, 35 | \code{\link{epochs}}, 36 | \code{\link{periods}}, 37 | \code{\link{stages}} 38 | } 39 | \concept{built-in timescales} 40 | \keyword{datasets} 41 | -------------------------------------------------------------------------------- /man/epochs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{epochs} 5 | \alias{epochs} 6 | \title{Epoch data from the International Commission on Stratigraphy (v2024/12)} 7 | \format{ 8 | A data frame with 34 rows and 5 variables: 9 | \describe{ 10 | \item{name}{epoch name} 11 | \item{max_age}{maximum age, in millions of years} 12 | \item{min_age}{minimum age, in millions of years} 13 | \item{abbr}{epoch name abbreviations} 14 | \item{color}{the colors for each epoch, according to the Commission for the 15 | Geological Map of the World} 16 | \item{lab_color}{the label colors for each epoch, either white or black, 17 | whichever has better contrast with the background color, based on 18 | \href{https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en}{recommendations by the International Telecommunication Union}} 19 | } 20 | } 21 | \source{ 22 | \url{https://stratigraphy.org} via \url{https://macrostrat.org/api/v2/defs/intervals?timescale=international\%20epochs} 23 | } 24 | \usage{ 25 | epochs 26 | } 27 | \description{ 28 | A dataset containing the boundary ages, abbreviations, and colors for the 29 | epochs of the Geologic Time Scale. Based on The ICS International 30 | Chronostratigraphic Chart (v2024/12), by Cohen, Finney, Gibbard, and Fan. 31 | } 32 | \seealso{ 33 | Other built-in timescales: 34 | \code{\link{eons}}, 35 | \code{\link{eras}}, 36 | \code{\link{periods}}, 37 | \code{\link{stages}} 38 | } 39 | \concept{built-in timescales} 40 | \keyword{datasets} 41 | -------------------------------------------------------------------------------- /man/stages.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{stages} 5 | \alias{stages} 6 | \title{Stage data from the International Commission on Stratigraphy (v2024/12)} 7 | \format{ 8 | A data frame with 102 rows and 5 variables: 9 | \describe{ 10 | \item{name}{stage name} 11 | \item{max_age}{maximum age, in millions of years} 12 | \item{min_age}{minimum age, in millions of years} 13 | \item{abbr}{stage name abbreviations} 14 | \item{color}{the colors for each stage, according to the Commission for the 15 | Geological Map of the World} 16 | \item{lab_color}{the label colors for each stage, either white or black, 17 | whichever has better contrast with the background color, based on 18 | \href{https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en}{recommendations by the International Telecommunication Union}} 19 | } 20 | } 21 | \source{ 22 | \url{https://stratigraphy.org} via \url{https://macrostrat.org/api/v2/defs/intervals?timescale=international\%20ages} 23 | } 24 | \usage{ 25 | stages 26 | } 27 | \description{ 28 | A dataset containing the boundary ages, abbreviations, and colors for the 29 | stages of the Geologic Time Scale. Based on The ICS International 30 | Chronostratigraphic Chart (v2024/12), by Cohen, Finney, Gibbard, and Fan. 31 | } 32 | \seealso{ 33 | Other built-in timescales: 34 | \code{\link{eons}}, 35 | \code{\link{epochs}}, 36 | \code{\link{eras}}, 37 | \code{\link{periods}} 38 | } 39 | \concept{built-in timescales} 40 | \keyword{datasets} 41 | -------------------------------------------------------------------------------- /man/periods.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{periods} 5 | \alias{periods} 6 | \title{Period data from the International Commission on Stratigraphy (v2024/12)} 7 | \format{ 8 | A data frame with 22 rows and 5 variables: 9 | \describe{ 10 | \item{name}{period name} 11 | \item{max_age}{maximum age, in millions of years} 12 | \item{min_age}{minimum age, in millions of years} 13 | \item{abbr}{period name abbreviations} 14 | \item{color}{the colors for each period, according to the Commission for 15 | the Geological Map of the World} 16 | \item{lab_color}{the label colors for each period, either white or black, 17 | whichever has better contrast with the background color, based on 18 | \href{https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en}{recommendations by the International Telecommunication Union}} 19 | } 20 | } 21 | \source{ 22 | \url{https://stratigraphy.org} via \url{https://macrostrat.org/api/v2/defs/intervals?timescale=international\%20periods} 23 | } 24 | \usage{ 25 | periods 26 | } 27 | \description{ 28 | A dataset containing the boundary ages, abbreviations, and colors for the 29 | periods of the Geologic Time Scale. Based on The ICS International 30 | Chronostratigraphic Chart (v2024/12), by Cohen, Finney, Gibbard, and Fan. 31 | } 32 | \seealso{ 33 | Other built-in timescales: 34 | \code{\link{eons}}, 35 | \code{\link{epochs}}, 36 | \code{\link{eras}}, 37 | \code{\link{stages}} 38 | } 39 | \concept{built-in timescales} 40 | \keyword{datasets} 41 | -------------------------------------------------------------------------------- /R/gggeo_scale.R: -------------------------------------------------------------------------------- 1 | #' Add a geologic scale below ggplots using *grid* 2 | #' 3 | #' @description 4 | #' `r lifecycle::badge('deprecated')` 5 | #' 6 | #' This function takes a ggplot object and adds a geologic time scale at the 7 | #' specified side using the grid and gtable packages. 8 | #' 9 | #' If custom data is provided (with `dat`), it should consist of at least 3 10 | #' columns of data. See `data(periods)` for an example. 11 | #' \itemize{ 12 | #' \item The `name` column lists the names of each time interval. These will 13 | #' be used as labels if no abbreviations are provided. 14 | #' \item The `max_age` column lists the oldest boundary of each time interval. 15 | #' \item The `min_age` column lists the youngest boundary of each time 16 | #' interval. 17 | #' \item The `abbr` column is optional and lists abbreviations that may be 18 | #' used as labels. 19 | #' \item The `color` column is also optional and lists a hex color code 20 | #' (which can be obtained with `rgb()`) for each time interval. 21 | #' } 22 | #' @section Life cycle: 23 | #' This function is fully deprecated in favor of [coord_geo()] as of 24 | #' **deeptime** version 2.3.0. It will be removed in a future version. 25 | #' @param obj An object of class `ggplot`, `gtable`, or `geo_scale` (as produced 26 | #' by this function). 27 | #' @return A geo_scale object. Basically a gtable object but with the axis 28 | #' limits included. 29 | #' @keywords internal 30 | #' @export 31 | gggeo_scale <- function(obj, ...) { 32 | lifecycle::deprecate_stop("2.3.0", "gggeo_scale()", "coord_geo()") 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /data-raw/ICS_data.R: -------------------------------------------------------------------------------- 1 | int_types <- c( 2 | "eons" = "eons", "eras" = "eras", "periods" = "periods", 3 | "epochs" = "epochs", "stages" = "ages" 4 | ) 5 | 6 | for (int_type in names(int_types)) { 7 | # Get the old data from within the package 8 | old_dat <- eval(parse(text = paste0("deeptime::", int_type))) 9 | 10 | # Get ICS data from Macrostrat 11 | raw_dat <- read.csv(url(paste0("https://macrostrat.org/api/v2/defs/intervals", 12 | "?format=csv×cale=international%20", 13 | int_types[int_type], "&true_colors=true")), 14 | stringsAsFactors = FALSE) 15 | clean_dat <- raw_dat[, c("name", "b_age", "t_age", "abbrev", "color")] 16 | colnames(clean_dat) <- c("name", "max_age", "min_age", "abbr", "color") 17 | 18 | # Set abbreviations where they don't already exist 19 | no_abbr <- (is.na(clean_dat$abbr) | clean_dat$abbr == "") 20 | clean_dat$abbr[no_abbr] <- 21 | abbreviate(clean_dat$name, minlength = 1, 22 | use.classes = TRUE, named = FALSE)[no_abbr] 23 | clean_dat$abbr[clean_dat$name == "Stage 10"] <- "S10" # fix abbreviation 24 | 25 | # Add label colors based on luminance as per 26 | # https://stackoverflow.com/a/1855903/4660582 27 | # values are from https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en 28 | clean_dat$lab_color <- deeptime:::white_or_black(clean_dat$color) 29 | 30 | assign(int_type, clean_dat) 31 | 32 | if (!identical(old_dat, clean_dat)) { 33 | do.call(eval(parse(text = "usethis::use_data")), 34 | list(as.name(int_type), overwrite = TRUE)) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /man/fgdc_names.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{fgdc_names} 5 | \alias{fgdc_names} 6 | \title{Pattern numbers and names for patterns from the FGDC Digital Cartographic 7 | Standard for Geologic Map Symbolization} 8 | \format{ 9 | A data frame with 117 rows and 2 variables: 10 | \describe{ 11 | \item{code}{the pattern number according to the FGDC standard} 12 | \item{name}{the verbatim name for the pattern according to the FGDC standard} 13 | } 14 | } 15 | \source{ 16 | \url{https://ngmdb.usgs.gov/fgdc_gds/geolsymstd/fgdc-geolsym-patternchart.pdf} 17 | via \url{https://github.com/davenquinn/geologic-patterns/} 18 | } 19 | \usage{ 20 | fgdc_names 21 | } 22 | \description{ 23 | A dataset containing the FGDC pattern numbers and verbatim names from the 24 | \href{https://ngmdb.usgs.gov/fgdc_gds/geolsymstd.php}{FGDC Digital Cartographic Standard for Geologic Map Symbolization} by the \href{https://www.usgs.gov/}{U.S. Geological Survey} and the \href{https://ngmdb.usgs.gov/fgdc_gds/index.php}{Geologic Data Subcommittee (GDS)} of the \href{https://www.fgdc.gov/}{Federal Geographic Data Committee (FGDC)}. Only patterns with names are 25 | included (i.e., patterns 601-733). 26 | } 27 | \details{ 28 | These pattern numbers and names were originally extracted by Daven Quinn and 29 | are hosted on \href{https://github.com/davenquinn/geologic-patterns/}{GitHub}. 30 | } 31 | \seealso{ 32 | FGDC patterns: 33 | \code{\link{fgdc_dict}()}, 34 | \code{\link{geo_pattern}()}, 35 | \code{\link{grid.pattern_geo}()}, 36 | \code{\link{scale_fill_geopattern}()} 37 | } 38 | \concept{patterns} 39 | \keyword{datasets} 40 | -------------------------------------------------------------------------------- /tests/testthat/test-get_scale_data.R: -------------------------------------------------------------------------------- 1 | test_that("get_scale_data works", { 2 | # check that package data is being loaded correctly 3 | expect_named(get_scale_data("stages"), 4 | c("name", "max_age", "min_age", "abbr", "color", "lab_color")) 5 | expect_identical(get_scale_data("stages"), deeptime::stages) 6 | expect_identical(get_scale_data("periods"), deeptime::periods) 7 | expect_identical(get_scale_data("epochs"), deeptime::epochs) 8 | expect_identical(get_scale_data("eras"), deeptime::eras) 9 | expect_identical(get_scale_data("eons"), deeptime::eons) 10 | 11 | # check errors 12 | expect_error(get_scale_data("e"), "multiple") 13 | 14 | skip_if_offline(host = "macrostrat.org") 15 | # check that package data matches data from Macrostrat 16 | expect_identical(get_scale_data("stages"), 17 | get_scale_data("international ages")) 18 | expect_identical(get_scale_data("epochs"), 19 | get_scale_data("international epochs")) 20 | expect_identical(get_scale_data("periods"), 21 | get_scale_data("international periods")) 22 | expect_identical(get_scale_data("eras"), 23 | get_scale_data("international eras")) 24 | expect_identical(get_scale_data("eons"), 25 | get_scale_data("international eons")) 26 | 27 | # check other Macrostrat timescales 28 | expect_no_error(get_scale_data("mammal")) 29 | expect_no_error(get_scale_data("australia")) 30 | 31 | # check Macrostrat errors 32 | expect_error(get_scale_data("international house of pancakes"), 33 | "does not match") 34 | expect_error(get_scale_data("international"), "multiple") 35 | }) 36 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: test-coverage 10 | 11 | jobs: 12 | test-coverage: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | 21 | - uses: r-lib/actions/setup-r@v2 22 | with: 23 | use-public-rspm: true 24 | 25 | - uses: r-lib/actions/setup-r-dependencies@v2 26 | with: 27 | extra-packages: any::covr 28 | needs: coverage 29 | 30 | - name: Test coverage 31 | run: | 32 | excl <- list("R/zzz.R"=1:1e6) 33 | covr::codecov( 34 | quiet = FALSE, 35 | clean = FALSE, 36 | install_path = file.path(Sys.getenv("RUNNER_TEMP"), "package"), 37 | line_exclusions = excl 38 | ) 39 | shell: Rscript {0} 40 | 41 | - name: Show testthat output 42 | if: always() 43 | run: | 44 | ## -------------------------------------------------------------------- 45 | find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true 46 | shell: bash 47 | 48 | - name: Upload test results 49 | if: failure() 50 | uses: actions/upload-artifact@v4 51 | with: 52 | name: coverage-test-failures 53 | path: ${{ runner.temp }}/package 54 | -------------------------------------------------------------------------------- /man/gtable_frame2.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggarrange2.R 3 | \name{gtable_frame2} 4 | \alias{gtable_frame2} 5 | \title{Decompose a ggplot gtable} 6 | \usage{ 7 | gtable_frame2( 8 | g, 9 | width = unit(1, "null"), 10 | height = unit(1, "null"), 11 | debug = FALSE 12 | ) 13 | } 14 | \arguments{ 15 | \item{g}{gtable} 16 | 17 | \item{width}{requested width} 18 | 19 | \item{height}{requested height} 20 | 21 | \item{debug}{logical draw gtable cells} 22 | } 23 | \value{ 24 | 7x7 gtable wrapping the plot 25 | } 26 | \description{ 27 | Reformat the gtable associated with a ggplot object into a 7x7 gtable where 28 | the central cell corresponds to the plot panel(s), the rectangle of cells 29 | around that corresponds to the axes, and the rectangle of cells around that 30 | corresponds to the axis titles. 31 | } 32 | \examples{ 33 | library(grid) 34 | library(gridExtra) 35 | library(ggplot2) 36 | p1 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) + 37 | geom_point() 38 | 39 | p2 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) + 40 | geom_point() + 41 | facet_wrap(~cyl, ncol = 2, scales = "free") + 42 | guides(colour = "none") + 43 | theme() 44 | 45 | p3 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) + 46 | geom_point() + 47 | facet_grid(. ~ cyl, scales = "free") 48 | 49 | g1 <- ggplotGrob(p1) 50 | g2 <- ggplotGrob(p2) 51 | g3 <- ggplotGrob(p3) 52 | fg1 <- gtable_frame2(g1) 53 | fg2 <- gtable_frame2(g2) 54 | fg12 <- gtable_frame2(gtable_rbind(fg1, fg2), width = unit(2, "null"), 55 | height = unit(1, "null")) 56 | fg3 <- gtable_frame2(g3, width = unit(1, "null"), height = unit(1, "null")) 57 | grid.newpage() 58 | combined <- gtable_cbind(fg12, fg3) 59 | grid.draw(combined) 60 | } 61 | -------------------------------------------------------------------------------- /man/gggeo_scale.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gggeo_scale.R 3 | \name{gggeo_scale} 4 | \alias{gggeo_scale} 5 | \title{Add a geologic scale below ggplots using \emph{grid}} 6 | \usage{ 7 | gggeo_scale(obj, ...) 8 | } 9 | \arguments{ 10 | \item{obj}{An object of class \code{ggplot}, \code{gtable}, or \code{geo_scale} (as produced 11 | by this function).} 12 | } 13 | \value{ 14 | A geo_scale object. Basically a gtable object but with the axis 15 | limits included. 16 | } 17 | \description{ 18 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} 19 | 20 | This function takes a ggplot object and adds a geologic time scale at the 21 | specified side using the grid and gtable packages. 22 | 23 | If custom data is provided (with \code{dat}), it should consist of at least 3 24 | columns of data. See \code{data(periods)} for an example. 25 | \itemize{ 26 | \item The \code{name} column lists the names of each time interval. These will 27 | be used as labels if no abbreviations are provided. 28 | \item The \code{max_age} column lists the oldest boundary of each time interval. 29 | \item The \code{min_age} column lists the youngest boundary of each time 30 | interval. 31 | \item The \code{abbr} column is optional and lists abbreviations that may be 32 | used as labels. 33 | \item The \code{color} column is also optional and lists a hex color code 34 | (which can be obtained with \code{rgb()}) for each time interval. 35 | } 36 | } 37 | \section{Life cycle}{ 38 | 39 | This function is fully deprecated in favor of \code{\link[=coord_geo]{coord_geo()}} as of 40 | \strong{deeptime} version 2.3.0. It will be removed in a future version. 41 | } 42 | 43 | \keyword{internal} 44 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: deeptime 2 | Title: Plotting Tools for Anyone Working in Deep Time 3 | Version: 2.3.1.9000 4 | Authors@R: person("William", "Gearty", email = "willgearty@gmail.com", role = c("aut", "cre"), 5 | comment = c(ORCID = "0000-0003-0076-3262")) 6 | Maintainer: William Gearty 7 | Description: Extends the functionality of other plotting packages (notably 'ggplot2') 8 | to help facilitate the plotting of data over long time intervals, including, 9 | but not limited to, geological, evolutionary, and ecological data. The 10 | primary goal of 'deeptime' is to enable users to add highly customizable 11 | timescales to their visualizations. Other functions are also included to 12 | assist with other areas of deep time visualization. 13 | URL: https://williamgearty.com/deeptime/, 14 | https://github.com/willgearty/deeptime 15 | BugReports: https://github.com/willgearty/deeptime/issues 16 | Depends: R (>= 3.5) 17 | License: GPL (>= 3) 18 | Encoding: UTF-8 19 | RoxygenNote: 7.3.3 20 | LazyData: true 21 | biocViews: 22 | Imports: 23 | deeptimedata, 24 | ggplot2 (>= 3.5.0), 25 | utils, 26 | ggforce, 27 | grid, 28 | gridExtra, 29 | gtable, 30 | methods, 31 | stats, 32 | lattice, 33 | rlang (>= 1.1.0), 34 | scales, 35 | ggfittext, 36 | curl, 37 | cli, 38 | lifecycle, 39 | grImport2, 40 | ggh4x 41 | Suggests: 42 | geomtextpath, 43 | phytools, 44 | dplyr, 45 | divDyn, 46 | gsloid, 47 | ape, 48 | palaeoverse, 49 | paleotree, 50 | dispRity, 51 | ggtree (>= 3.6.1), 52 | tidytree, 53 | testthat (>= 3.0.0), 54 | vdiffr (>= 1.0.8), 55 | knitr, 56 | rmarkdown, 57 | withr, 58 | ggpattern, 59 | ggrepel, 60 | rmacrostrat, 61 | svglite 62 | VignetteBuilder: knitr 63 | Config/testthat/edition: 3 64 | Config/Needs/revdeps: revdepcheck 65 | Roxygen: list(markdown = TRUE) 66 | -------------------------------------------------------------------------------- /tests/testthat/test-scales.R: -------------------------------------------------------------------------------- 1 | test_that("scale_fill_geo works", { 2 | set.seed(1234) 3 | df <- data.frame( 4 | x = runif(1000, 0, 10), y = runif(1000, 0, 10), 5 | color = sample(periods$name, 1000, TRUE), shape = 21 6 | ) 7 | gg <- ggplot(df) + 8 | geom_point(aes(x = x, y = y, fill = color), shape = 21) + 9 | scale_fill_geo("periods", name = "Period") + 10 | theme_classic() 11 | expect_doppelganger_deeptime("scale_fill_geo", gg) 12 | }) 13 | 14 | test_that("scale_color_geo works", { 15 | set.seed(1234) 16 | df <- data.frame(x = runif(1000, 0, 1000), y = runif(1000, 0, 8)) 17 | df$color <- cut(df$x, c(periods$min_age, periods$max_age[22]), periods$name) 18 | gg <- ggplot(df) + 19 | geom_point(aes(x = x, y = y, color = color)) + 20 | scale_x_reverse() + 21 | scale_color_geo("periods", name = "Period") + 22 | coord_geo(xlim = c(1000, 0), ylim = c(0, 8)) + 23 | theme_classic() 24 | expect_doppelganger_deeptime("scale_color_geo", gg) 25 | }) 26 | 27 | test_that("scale_discrete_geo works", { 28 | set.seed(1234) 29 | df <- data.frame(x = runif(1000, 0, 1000), y = runif(1000, 0, 8)) 30 | df$color <- cut(df$x, c(periods$min_age, periods$max_age[22]), periods$name) 31 | gg <- ggplot(df) + 32 | geom_point(aes(x = x, y = y, color = color, fill = color), shape = 21) + 33 | scale_x_reverse() + 34 | scale_discrete_geo("periods", c("color", "fill"), name = "Period") + 35 | coord_geo(xlim = c(1000, 0), ylim = c(0, 8)) + 36 | theme_classic() 37 | expect_doppelganger_deeptime("scale_discrete_geo", gg) 38 | 39 | # test error catching 40 | expect_error( 41 | ggplot(df) + 42 | geom_point(aes(x = x, y = y, color = color, fill = color), shape = 21) + 43 | scale_x_reverse() + 44 | scale_discrete_geo(data.frame(x = 1, y = 2), c("color", "fill")) + 45 | coord_geo(xlim = c(1000, 0), ylim = c(0, 8)) + 46 | theme_classic() 47 | ) 48 | 49 | df$color <- factor(seq_len(nrow(df))) 50 | gg <- ggplot(df) + 51 | geom_point(aes(x = x, y = y, color = color, fill = color), shape = 21) + 52 | scale_x_reverse() + 53 | scale_discrete_geo("periods", c("color", "fill")) + 54 | coord_geo(xlim = c(1000, 0), ylim = c(0, 8)) + 55 | theme_classic() 56 | expect_error(print(gg)) 57 | }) 58 | -------------------------------------------------------------------------------- /man/coord_trans_flip.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/coord_trans_flip.R 3 | \docType{data} 4 | \name{coord_trans_flip} 5 | \alias{coord_trans_flip} 6 | \alias{CoordTransFlip} 7 | \title{Transformed and flipped Cartesian coordinate system} 8 | \usage{ 9 | coord_trans_flip( 10 | x = "identity", 11 | y = "identity", 12 | xlim = NULL, 13 | ylim = NULL, 14 | clip = "on", 15 | expand = TRUE 16 | ) 17 | } 18 | \arguments{ 19 | \item{x, y}{Transformers for x and y axes or their names.} 20 | 21 | \item{xlim, ylim}{Limits for the x and y axes.} 22 | 23 | \item{clip}{Should drawing be clipped to the extent of the plot panel? A 24 | setting of \code{"on"} (the default) means yes, and a setting of \code{"off"} 25 | means no. In most cases, the default of \code{"on"} should not be changed, 26 | as setting \code{clip = "off"} can cause unexpected results. It allows 27 | drawing of data points anywhere on the plot, including in the plot margins. If 28 | limits are set via \code{xlim} and \code{ylim} and some data points fall outside those 29 | limits, then those data points may show up in places such as the axes, the 30 | legend, the plot title, or the plot margins.} 31 | 32 | \item{expand}{If \code{TRUE}, the default, adds a small expansion factor to 33 | the limits to ensure that data and axes don't overlap. If \code{FALSE}, 34 | limits are taken exactly from the data or \code{xlim}/\code{ylim}. 35 | Giving a logical vector will separately control the expansion for the four 36 | directions (top, left, bottom and right). The \code{expand} argument will be 37 | recycled to length 4 if necessary. Alternatively, can be a named logical 38 | vector to control a single direction, e.g. \code{expand = c(bottom = FALSE)}.} 39 | } 40 | \description{ 41 | \code{coord_trans_flip} behaves similarly to \code{\link[ggplot2:coord_transform]{ggplot2::coord_trans()}} in that it 42 | occurs after statistical transformation and will affect the visual appearance 43 | of geoms. The main difference is that it also flips the x and y coordinates 44 | like \code{\link[ggplot2:coord_flip]{ggplot2::coord_flip()}}. 45 | } 46 | \examples{ 47 | library(ggplot2) 48 | ggplot(mtcars, aes(disp, wt)) + 49 | geom_point() + 50 | coord_trans_flip(x = "log10", y = "log10") 51 | } 52 | \keyword{datasets} 53 | -------------------------------------------------------------------------------- /tests/testthat/test-coord_trans_xy.R: -------------------------------------------------------------------------------- 1 | test_that("coord_trans_xy() works", { 2 | trans <- ggforce::linear_trans(shear(2, 0), rotate(-pi / 3)) 3 | square <- data.frame(x = c(-2, -2, 2, 2), y = c(-2, 2, 2, -2)) 4 | points <- data.frame( 5 | x = rep(seq(-2, 2, 0.25), each = 17), 6 | y = rep(seq(-2, 2, 0.25), 17), 7 | color = rep(seq(1, 17, 1), each = 17) 8 | ) 9 | gg <- ggplot(data = points, aes(x = x, y = y, color = color)) + 10 | geom_polygon(data = square, fill = NA, color = "black") + 11 | geom_point() + 12 | scale_x_continuous(sec.axis = sec_axis(~.)) + 13 | coord_trans_xy(trans = trans, expand = FALSE) + 14 | theme_classic() 15 | expect_true(is_ggplot(gg)) 16 | params <- ggplot_build(gg)$layout$panel_params[[1]] 17 | points_trans <- trans$transform(points$x, points$y) 18 | expect_equal(params$x.range, range(points_trans$x)) 19 | expect_equal(params$y.range, range(points_trans$y)) 20 | expect_true(is(ggplot_build(gg)$layout$panel_params[[1]]$x.sec, "ViewScale")) 21 | expect_equal(ggplot_build(gg)$layout$panel_params[[1]]$x$limits, c(-2, 2)) 22 | expect_doppelganger_deeptime("coord_trans_xy() without expansion", gg) 23 | 24 | gg <- ggplot(data = points, aes(x = x, y = y, color = color)) + 25 | geom_polygon(data = square, fill = NA, color = "black") + 26 | geom_point() + 27 | scale_x_continuous(sec.axis = sec_axis(~.)) + 28 | scale_y_continuous(sec.axis = sec_axis(~.)) + 29 | coord_trans_xy(trans = trans, expand = TRUE) + 30 | theme_classic() 31 | expect_true(is_ggplot(gg)) 32 | expect_equal(ggplot_build(gg)$layout$panel_params[[1]]$x$limits, c(-2, 2)) 33 | expect_doppelganger_deeptime("coord_trans_xy() with expansion", gg) 34 | 35 | gg <- ggplot(data = points, aes(x = x, y = y, color = color)) + 36 | geom_polygon(data = square, fill = NA, color = "black") + 37 | geom_point() + 38 | scale_x_continuous(sec.axis = sec_axis(~.)) + 39 | coord_trans_xy(expand = FALSE) + 40 | theme_classic() 41 | expect_true(is_ggplot(gg)) 42 | params <- ggplot_build(gg)$layout$panel_params[[1]] 43 | expect_equal(params$x.range, range(points$x)) 44 | expect_equal(params$y.range, range(points$y)) 45 | expect_doppelganger_deeptime("coord_trans_xy() with no trans", gg) 46 | expect_error({ 47 | ggplot(data = points, aes(x = x, y = y, color = color)) + 48 | geom_polygon(data = square, fill = NA, color = "black") + 49 | geom_point() + 50 | coord_trans_xy(trans = 5, expand = TRUE) 51 | }) 52 | }) 53 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | schedule: 9 | - cron: '30 5 1 * *' 10 | 11 | name: R-CMD-check 12 | 13 | permissions: read-all 14 | 15 | env: 16 | R_BIOC_VERSION: 3.22 17 | 18 | jobs: 19 | R-CMD-check: 20 | runs-on: ${{ matrix.config.os }} 21 | 22 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}, ggplot2 ${{ matrix.ggplot2 }}) 23 | 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | ggplot2: [">= 3.5.2", "devel"] 28 | config: 29 | - {os: macos-latest, r: 'release'} 30 | - {os: windows-latest, r: 'release'} 31 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 32 | - {os: ubuntu-latest, r: 'release'} 33 | - {os: ubuntu-latest, r: 'oldrel-1'} 34 | 35 | env: 36 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 37 | R_KEEP_PKG_SOURCE: yes 38 | 39 | steps: 40 | - uses: actions/checkout@v4 41 | 42 | - name: Install X11 dependencies on MacOS 43 | if: runner.os == 'macOS' 44 | run: | 45 | brew install xquartz 46 | 47 | - uses: r-lib/actions/setup-pandoc@v2 48 | 49 | - uses: r-lib/actions/setup-r@v2 50 | with: 51 | r-version: ${{ matrix.config.r }} 52 | http-user-agent: ${{ matrix.config.http-user-agent }} 53 | use-public-rspm: true 54 | 55 | - uses: r-lib/actions/setup-r-dependencies@v2 56 | with: 57 | extra-packages: any::rcmdcheck 58 | needs: check 59 | 60 | - name: Install ggplot2 ${{ matrix.ggplot2 }} 61 | run: | 62 | install.packages("remotes") 63 | remotes::install_version("ggplot2", version = "${{ matrix.ggplot2 }}") 64 | shell: Rscript {0} 65 | if: matrix.ggplot2 != 'devel' 66 | 67 | - name: Install development ggplot2 68 | run: | 69 | install.packages("pak") 70 | pak::pak("tidyverse/ggplot2") 71 | shell: Rscript {0} 72 | if: matrix.ggplot2 == 'devel' 73 | 74 | - name: run default R CMD Check 75 | uses: r-lib/actions/check-r-package@v2 76 | env: 77 | _R_CHECK_FORCE_SUGGESTS_: 0 78 | with: 79 | upload-snapshots: true 80 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 81 | -------------------------------------------------------------------------------- /man/fgdc_dict.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.R 3 | \name{fgdc_dict} 4 | \alias{fgdc_dict} 5 | \title{FGDC pattern labeling function/dictionary} 6 | \usage{ 7 | fgdc_dict(clean = TRUE, nomatch = NULL, wrap = NULL) 8 | } 9 | \arguments{ 10 | \item{clean}{\code{logical}. Should the pattern names be cleaned? If \code{TRUE} 11 | (default), the names will be cleaned to remove strings such as "(2nd 12 | option)". If \code{FALSE}, the names will be verbatim from the FGDC standard. 13 | Note that pattern names may not be unique when this is set to \code{TRUE}.} 14 | 15 | \item{nomatch}{\code{character}. A string to label values that do not match any 16 | name in the dictionary. When \code{NULL} (default), the values are kept as-is.} 17 | 18 | \item{wrap}{\code{integer}. If not \code{NULL}, the pattern names will be wrapped to 19 | the specified width (in characters) by insertting line breaks between words 20 | using \code{\link[=strwrap]{strwrap()}} (words will not be broken). This can be useful for making 21 | long names fit better in legends. If \code{NULL} (default), no wrapping is done.} 22 | } 23 | \value{ 24 | A \link[scales:label_dictionary]{labeling function} that takes 25 | a vector \code{x} of pattern numbers and returns a character vector of 26 | \code{length(x)} giving the corresponding pattern names. The function is 27 | designed to be used with the \code{labels} argument of ggplot2 scales, such as 28 | \code{\link[=scale_fill_geopattern]{scale_fill_geopattern()}} and \code{\link[ggpattern:scale_pattern_identity]{ggpattern::scale_pattern_type_identity()}}. 29 | } 30 | \description{ 31 | Generates a \link[scales:label_dictionary]{labeling function}/dictionary based 32 | on the built-in \link{fgdc_names} dataset that can be used to retrieve the names 33 | of patterns based on their pattern numbers/codes as defined in the \href{https://ngmdb.usgs.gov/fgdc_gds/geolsymstd.php}{FGDC Digital Cartographic Standard for Geologic Map Symbolization} by the \href{https://www.usgs.gov/}{U.S. Geological Survey} and the \href{https://ngmdb.usgs.gov/fgdc_gds/index.php}{Geologic Data Subcommittee (GDS)} of the \href{https://www.fgdc.gov/}{Federal Geographic Data Committee (FGDC)}. Like \link{fgdc_names}, only 34 | patterns with names are included (i.e., patterns 601-733). 35 | } 36 | \examples{ 37 | library(ggplot2) 38 | vals <- c("603", "626", "720", "733") 39 | ggplot(mpg, aes(factor(cyl), fill = vals[factor(cyl)])) + 40 | geom_bar() + 41 | scale_fill_geopattern(name = NULL, labels = fgdc_dict()) 42 | } 43 | \seealso{ 44 | FGDC patterns: 45 | \code{\link{fgdc_names}}, 46 | \code{\link{geo_pattern}()}, 47 | \code{\link{grid.pattern_geo}()}, 48 | \code{\link{scale_fill_geopattern}()} 49 | } 50 | \concept{patterns} 51 | -------------------------------------------------------------------------------- /R/scales.R: -------------------------------------------------------------------------------- 1 | #' Geological Time Scale color scales 2 | #' 3 | #' Color scales using the colors in the Geological Time Scale graphics. 4 | #' 5 | #' @inheritParams ggplot2::scale_discrete_manual 6 | #' @inheritDotParams ggplot2::discrete_scale -expand -position -palette -breaks -fallback.palette 7 | #' @importFrom ggplot2 discrete_scale 8 | #' @rdname scale_geo 9 | #' @param dat Either A) a string indicating a built-in dataframe with interval 10 | #' data from the ICS ("periods", "epochs", "stages", "eons", or "eras"), 11 | #' B) a string indicating a timescale from macrostrat (see list here: 12 | #' ), 13 | #' or C) a custom data.frame of time interval boundaries 14 | #' (see [coord_geo()]). 15 | #' @export 16 | #' @examples 17 | #' library(ggplot2) 18 | #' df <- data.frame( 19 | #' x = runif(1000, 0, 10), y = runif(1000, 0, 10), 20 | #' color = sample(periods$name, 1000, TRUE), shape = 21 21 | #' ) 22 | #' ggplot(df) + 23 | #' geom_point(aes(x = x, y = y, fill = color), shape = 21) + 24 | #' scale_fill_geo("periods", name = "Period") + 25 | #' theme_classic() 26 | #' 27 | #' # cut continuous variable into discrete 28 | #' df <- data.frame(x = runif(1000, 0, 1000), y = runif(1000, 0, 8)) 29 | #' df$color <- cut(df$x, c(periods$min_age, periods$max_age[22]), periods$name) 30 | #' ggplot(df) + 31 | #' geom_point(aes(x = x, y = y, color = color)) + 32 | #' scale_x_reverse() + 33 | #' scale_color_geo("periods", name = "Period") + 34 | #' coord_geo(xlim = c(1000, 0), ylim = c(0, 8)) + 35 | #' theme_classic() 36 | scale_color_geo <- function(dat, ...) { 37 | scale_discrete_geo(dat, "color", ...) 38 | } 39 | 40 | #' @export 41 | #' @rdname scale_geo 42 | #' @usage NULL 43 | scale_colour_geo <- scale_color_geo 44 | 45 | #' @rdname scale_geo 46 | #' @export 47 | scale_fill_geo <- function(dat, ...) { 48 | scale_discrete_geo(dat, "fill", ...) 49 | } 50 | 51 | #' @export 52 | #' @rdname scale_geo 53 | #' @importFrom stats setNames 54 | scale_discrete_geo <- function(dat, aesthetics, ...) { 55 | if (is(dat, "data.frame")) { 56 | # just use the supplied data 57 | } else if (is.character(dat)) { 58 | dat <- get_scale_data(dat) 59 | } else { 60 | cli::cli_abort("`dat` must be either a dataframe or a string.") 61 | } 62 | if (!all(c("name", "color") %in% colnames(dat))) { 63 | cli::cli_abort("Either `name` or `color` is not a named column in `dat`") 64 | } 65 | values <- setNames(dat$color, dat$name) 66 | 67 | pal <- function(n) { 68 | if (n > length(values)) { 69 | cli::cli_abort("Insufficient values in manual scale. {n} needed but only 70 | {length(values)} provided.") 71 | } 72 | values 73 | } 74 | 75 | discrete_scale(aesthetics, palette = pal, breaks = names(values), ...) 76 | } 77 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to deeptime 2 | 3 | This outlines how to propose a change to deeptime. These guidelines are based on the tidyverse [contribution guidelines](https://rstd.io/tidy-contrib). 4 | 5 | ## Fixing typos 6 | 7 | You can fix typos, spelling mistakes, or grammatical errors in the documentation directly using the GitHub web interface, as long as the changes are made in the _source_ file. 8 | This generally means you'll need to edit [roxygen2 comments](https://roxygen2.r-lib.org/articles/roxygen2.html) in an `.R`, not a `.Rd` file. 9 | You can find the `.R` file that generates the `.Rd` by reading the comment in the first line. 10 | 11 | ## Bigger changes 12 | 13 | If you want to make a bigger change, it's a good idea to first file an issue and make sure someone from the team agrees that it’s needed. 14 | If you’ve found a bug, please file an issue that illustrates the bug with a minimal 15 | [reprex](https://www.tidyverse.org/help/#reprex) (this will also help you write a unit test, if needed). 16 | 17 | ### Pull request process 18 | 19 | * Fork the package and clone onto your computer. If you haven't done this before, we recommend using `usethis::create_from_github("batpigandme/deeptime", fork = TRUE)`. 20 | 21 | * Install all development dependencies with `devtools::install_dev_deps()`, and then make sure the package passes R CMD check by running `devtools::check()`. 22 | If R CMD check doesn't pass cleanly, it's a good idea to ask for help before continuing. 23 | * Create a Git branch for your pull request (PR). We recommend using `usethis::pr_init("brief-description-of-change")`. 24 | 25 | * Make your changes, commit to git, and then create a PR by running `usethis::pr_push()`, and following the prompts in your browser. 26 | The title of your PR should briefly describe the change. 27 | The body of your PR should contain `Fixes #issue-number`. 28 | 29 | * For user-facing changes, add a bullet to the top of `NEWS.md` (i.e. just below the first header). Follow the style described in . 30 | 31 | ### Code style 32 | 33 | * New code should follow the tidyverse [style guide](https://style.tidyverse.org). 34 | You can use the [styler](https://CRAN.R-project.org/package=styler) package to apply these styles, but please don't restyle code that has nothing to do with your PR. 35 | 36 | * We use [roxygen2](https://cran.r-project.org/package=roxygen2), with [Markdown syntax](https://roxygen2.r-lib.org/articles/rd-formatting.html), for documentation. 37 | 38 | * We use [testthat](https://cran.r-project.org/package=testthat) for unit tests. 39 | Contributions with test cases included are easier to accept. 40 | 41 | ## Code of Conduct 42 | 43 | Please note that the deeptime project is released with a 44 | [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By contributing to this 45 | project you agree to abide by its terms. 46 | -------------------------------------------------------------------------------- /tests/testthat/test-points_range.R: -------------------------------------------------------------------------------- 1 | test_that("geom_points_range works", { 2 | skip_if_not_installed("palaeoverse") 3 | tetrapod_names <- tetrapods$accepted_name[1:50] 4 | beds_sampled <- sample.int(n = 10, size = 50, replace = TRUE) 5 | occdf <- data.frame(taxon = tetrapod_names, bed = beds_sampled) 6 | 7 | # check that vertical orientation works 8 | gg <- ggplot(occdf, aes(x = reorder(taxon, bed, min), y = bed)) + 9 | geom_points_range(size = 1) + 10 | theme_classic(base_size = 16) 11 | expect_true(is_ggplot(gg)) 12 | expect_true(is(gg$layers[[1]]$geom, "GeomPointsRange")) 13 | expect_true(is(gg$layers[[1]]$stat, "StatPointsRange")) 14 | expect_doppelganger_deeptime("geom_points_range_v", gg) 15 | 16 | # check that horizontal orientation works 17 | gg <- ggplot(occdf, aes(y = reorder(taxon, bed, min), x = bed)) + 18 | geom_points_range(size = .5) + 19 | theme_classic(base_size = 16) 20 | expect_true(is_ggplot(gg)) 21 | expect_true(is(gg$layers[[1]]$geom, "GeomPointsRange")) 22 | expect_true(is(gg$layers[[1]]$stat, "StatPointsRange")) 23 | expect_doppelganger_deeptime("geom_points_range_h", gg) 24 | 25 | # check that aesthetics and groupings work 26 | occdf$certainty <- factor(rep(1, 50), levels = c(0, 1)) 27 | occdf <- rbind(occdf, 28 | data.frame(taxon = "Eryops", bed = c(12, 15), certainty = 0)) 29 | gg <- ggplot(occdf, aes(y = reorder(taxon, bed, min), x = bed, 30 | fill = certainty, linetype = certainty)) + 31 | geom_points_range(size = .5, shape = 21) + 32 | scale_fill_manual(values = c("white", "black")) + 33 | scale_linetype_manual(values = c("dashed", "solid")) + 34 | theme_classic(base_size = 16) 35 | expect_true(is_ggplot(gg)) 36 | expect_true(is(gg$layers[[1]]$geom, "GeomPointsRange")) 37 | expect_true(is(gg$layers[[1]]$stat, "StatPointsRange")) 38 | expect_doppelganger_deeptime("geom_points_range_aes", gg) 39 | 40 | # check that background lines work 41 | gg <- ggplot(occdf, aes(y = reorder(taxon, bed, min), x = bed, 42 | fill = certainty, linetype = certainty)) + 43 | geom_points_range(size = .5, shape = 21, 44 | background_line = list(linetype = "dashed")) + 45 | scale_fill_manual(values = c("white", "black")) + 46 | scale_linetype_manual(values = c("dashed", "solid")) + 47 | theme_classic(base_size = 16) 48 | expect_true(is_ggplot(gg)) 49 | expect_true(is(gg$layers[[1]]$geom, "GeomPointsRange")) 50 | expect_true(is(gg$layers[[1]]$stat, "StatPointsRange")) 51 | expect_doppelganger_deeptime("geom_points_range_bg", gg) 52 | 53 | stat_obj <- stat_points_range(data = occdf, 54 | aes(y = reorder(taxon, bed, min), x = bed, 55 | fill = certainty, linetype = certainty)) 56 | expect_true(is(stat_obj, "gg")) 57 | expect_true(is(stat_obj$geom, "GeomPointsRange")) 58 | expect_true(is(stat_obj$stat, "StatPointsRange")) 59 | }) 60 | -------------------------------------------------------------------------------- /tests/testthat/test-coord_geo_radial.R: -------------------------------------------------------------------------------- 1 | skip_if_not_installed("ggtree") 2 | 3 | test_that("coord_geo_radial works", { 4 | skip_if_not_installed("ape") 5 | gg <- revts(ggtree(tree)) + 6 | coord_geo_radial(dat = "stages", expand = FALSE) + 7 | scale_y_continuous(guide = "none", breaks = NULL) + 8 | theme_gray() 9 | expect_true(is_ggplot(gg)) 10 | expect_true(is(ggplot_build(gg)$layout$coord, "CoordGeoRadial")) 11 | expect_doppelganger_deeptime("coord_geo_radial", gg) 12 | skip_if_not_installed("phytools") 13 | expect_equal(ggplot_build(gg)$layout$panel_params[[1]]$r.range, 14 | c(-max(nodeHeights(tree)), 0)) 15 | 16 | gg <- revts(ggtree(tree)) 17 | lifecycle::expect_deprecated({ 18 | gg + coord_geo_radial(direction = -1) 19 | }) 20 | expect_error({ 21 | gg + coord_geo_radial(direction = 5) 22 | }) 23 | lifecycle::expect_deprecated({ 24 | gg + coord_geo_radial(r_axis_inside = TRUE) 25 | }) 26 | lifecycle::expect_deprecated({ 27 | gg + coord_geo_radial(rotate_angle = TRUE) 28 | }) 29 | }) 30 | 31 | test_that("stacking scales works", { 32 | skip_if_not_installed("phytools") 33 | gg <- revts(ggtree(mammal.tree)) + 34 | coord_geo_radial( 35 | dat = list("stages", "periods"), alpha = .5, 36 | prop = list(0.75, .25), start = pi / 4, end = 2 * pi, lty = "dashed" 37 | ) + 38 | scale_y_continuous(expand = expansion(mult = c(0.02, 0.02)), 39 | guide = "none", breaks = NULL) + 40 | theme_gray() 41 | expect_doppelganger_deeptime("stacked scales", gg) 42 | 43 | gg <- ggarrange2( 44 | revts(ggtree(mammal.tree)) + 45 | coord_geo_radial(list("stages", "periods")), 46 | revts(ggtree(mammal.tree)) + 47 | coord_geo_radial(list("stages", "periods"), reverse = "theta"), 48 | nrow = 1 49 | ) 50 | expect_doppelganger_deeptime("stacked scales_reverse", gg) 51 | }) 52 | 53 | test_that("ggtree scale works with only fossil taxa", { 54 | skip_if_not_installed("paleotree") 55 | skip_if_not_installed("geomtextpath") 56 | gg <- ggtree(ceratopsianTreeRaia, 57 | position = position_nudge(x = -ceratopsianTreeRaia$root.time)) + 58 | coord_geo_radial(dat = "stages") + 59 | scale_y_continuous(guide = "none", breaks = NULL) + 60 | theme_gray() + 61 | theme(panel.grid.major = element_blank()) 62 | expect_doppelganger_deeptime("scale on fossil ggtree", gg) 63 | skip_if(R.Version()$os != "mingw32") # only test this on Windows 64 | gg <- ggtree(ceratopsianTreeRaia, 65 | position = position_nudge(x = -ceratopsianTreeRaia$root.time)) + 66 | coord_geo_radial(dat = list("stages", "periods"), lab = list(FALSE, TRUE), 67 | abbrv = TRUE) + 68 | scale_x_continuous(expand = expansion(add = c(20, 30))) + 69 | scale_y_continuous(guide = "none", breaks = NULL) + 70 | theme_gray() + 71 | theme(panel.grid.major = element_blank()) 72 | expect_doppelganger_deeptime("scale on fossil ggtree with labels", gg) 73 | }) 74 | -------------------------------------------------------------------------------- /.github/workflows/revdepcheck.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | - master 6 | paths-ignore: 7 | - "Meta**" 8 | - "data-raw**" 9 | - "docs**" 10 | - "inst**" 11 | - "man**" 12 | - "memcheck**" 13 | - "tests**" 14 | - "vignettes**" 15 | - "**.git" 16 | - "**.json" 17 | - "**.md" 18 | - "**.yml" 19 | - "!**revdepcheck.yml" 20 | - "**.R[dD]ata" 21 | - "**.Rpro*" 22 | pull_request: 23 | branches: 24 | - main 25 | - master 26 | paths-ignore: 27 | - "Meta**" 28 | - "memcheck**" 29 | - "data-raw**" 30 | - "docs**" 31 | - "inst**" 32 | - "man**" 33 | - "tests**" 34 | - "vignettes**" 35 | - "**.git" 36 | - "**.json" 37 | - "**.md" 38 | - "**.yml" 39 | - "!**revdepcheck.yml" 40 | - "**.R[dD]ata" 41 | - "**.Rpro*" 42 | schedule: 43 | - cron: '30 5 1 * *' 44 | 45 | name: revdep-check 46 | 47 | jobs: 48 | mem-check: 49 | runs-on: windows-latest 50 | 51 | name: revdepcheck, macOS, R release 52 | 53 | env: 54 | _R_CHECK_CRAN_INCOMING_: true # Seemingly not set by --as-cran 55 | _R_CHECK_FORCE_SUGGESTS_: false # CRAN settings 56 | R_COMPILE_AND_INSTALL_PACKAGES: 'never' 57 | _R_CHECK_THINGS_IN_CHECK_DIR_: false 58 | R_REMOTES_STANDALONE: true 59 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true 60 | RSPM: ${{ matrix.config.rspm }} 61 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 62 | R_BIOC_VERSION: 3.22 63 | 64 | steps: 65 | - uses: actions/checkout@v4 66 | 67 | - uses: r-lib/actions/setup-r@v2 68 | with: 69 | r-version: release 70 | use-public-rspm: true 71 | 72 | - uses: r-lib/actions/setup-pandoc@v2 73 | 74 | - name: Cache R packages 75 | uses: actions/cache@v4 76 | with: 77 | path: ${{ env.R_LIBS_USER }} 78 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} 79 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- 80 | 81 | - name: Install dependencies 82 | run: | 83 | install.packages('pak', repos = 'https://r-lib.github.io/p/pak/dev/') 84 | pak::local_install_deps() 85 | pak::pkg_install('r-lib/revdepcheck') 86 | shell: Rscript {0} 87 | 88 | - name: Check reverse dependencies 89 | env: 90 | _R_CHECK_CRAN_INCOMING_REMOTE_: false 91 | run: | 92 | revdepcheck::revdep_reset() 93 | revdepcheck::revdep_check(num_workers=4) 94 | problems <- readLines('revdep/problems.md', warn = FALSE) 95 | if (length(problems) > 1) stop(paste0(problems, collapse= "\n")) 96 | shell: Rscript {0} 97 | 98 | - name: Upload check results 99 | if: failure() 100 | uses: actions/upload-artifact@v4 101 | with: 102 | name: revdep-results 103 | path: revdep/*.md 104 | -------------------------------------------------------------------------------- /tests/testthat/test-geom_text_phylo.R: -------------------------------------------------------------------------------- 1 | test_that("geom_text_phylo works", { 2 | skip_if_not_installed("ape") 3 | skip_if_not_installed("ggtree") 4 | library(ape) 5 | library(ggtree) 6 | set.seed(1234) 7 | tr <- rtree(10) 8 | gg <- revts(ggtree(tr)) + 9 | geom_text_phylo() + 10 | coord_geo_radial("epochs") 11 | expect_true(is_ggplot(gg)) 12 | expect_true(is(gg$layers[[3]]$geom, "GeomTextPhylo")) 13 | expect_true(is(gg$layers[[3]]$stat, "StatIdentity")) 14 | expect_doppelganger_deeptime("geom_text_phylo", gg) 15 | 16 | expect_error({ 17 | ggtree(tr) + 18 | geom_text_phylo(node_type = "wrong") + 19 | coord_geo_radial("epochs") 20 | }) 21 | expect_error({ 22 | ggtree(tr) + 23 | geom_text_phylo(auto_adjust = "wrong") + 24 | coord_geo_radial("epochs") 25 | }) 26 | }) 27 | 28 | test_that("geom_text_clade works", { 29 | skip_if_not_installed("ape") 30 | skip_if_not_installed("ggtree") 31 | skip_if_not_installed("phytools") 32 | library(ape) 33 | library(ggtree) 34 | library(phytools) 35 | data(primate.tree) 36 | clades.df <- data.frame( 37 | clade = c("Lorisoidea", "Lemuroidea", "Tarsioidea", "Ceboidea", 38 | "Cercopithecoidea", "Hominoidea"), 39 | node = c(166, 146, 144, 120, 95, 114) 40 | ) 41 | gg <- revts(ggtree(primate.tree)) %<+% clades.df + 42 | geom_text_clade(aes(label = clade), extend = c(0.1, 0.1)) + 43 | coord_geo_radial() 44 | expect_true(is_ggplot(gg)) 45 | expect_true(is(gg$layers[[3]]$geom, "GeomTextClade")) 46 | expect_true(is(gg$layers[[3]]$stat, "StatIdentity")) 47 | expect_doppelganger_deeptime("geom_text_clade", gg) 48 | 49 | # geom_label 50 | gg <- revts(ggtree(primate.tree)) %<+% clades.df + 51 | geom_text_clade(aes(label = clade), extend = c(0.1, 0.1), 52 | text_geom = "label") + 53 | coord_geo_radial() 54 | expect_doppelganger_deeptime("geom_text_clade-labels", gg) 55 | 56 | expect_error({ 57 | revts(ggtree(primate.tree)) %<+% clades.df + 58 | geom_text_clade(aes(label = clade), text_geom = "rect") + 59 | coord_geo_radial() 60 | }) 61 | expect_error({ 62 | revts(ggtree(primate.tree)) %<+% clades.df + 63 | geom_text_clade(aes(label = clade), extend = 0.5) + 64 | coord_geo_radial() 65 | }) 66 | 67 | # annotation 68 | gg <- revts(ggtree(primate.tree)) + 69 | geom_text_clade(label = "Hominoidea", node = 114, extend = c(0.1, 0.1)) + 70 | coord_geo_radial() 71 | expect_doppelganger_deeptime("geom_text_clade-annotation", gg) 72 | expect_error({ 73 | revts(ggtree(primate.tree)) + 74 | geom_text_clade(label = "Hominoidea", extend = c(0.1, 0.1)) + 75 | coord_geo_radial() 76 | }) 77 | expect_error({ 78 | revts(ggtree(primate.tree)) + 79 | geom_text_clade(label = c("Hominoidea", "Lorisoidea"), node = 114, 80 | extend = c(0.1, 0.1)) + 81 | coord_geo_radial() 82 | }) 83 | expect_error({ 84 | revts(ggtree(primate.tree)) + 85 | geom_text_clade(aes(label = label), label = "Hominoidea", node = 114, 86 | extend = c(0.1, 0.1)) + 87 | coord_geo_radial() 88 | }) 89 | }) 90 | -------------------------------------------------------------------------------- /man/ggarrange2.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggarrange2.R 3 | \name{ggarrange2} 4 | \alias{ggarrange2} 5 | \title{Combine and arrange multiple ggplot-like objects} 6 | \usage{ 7 | ggarrange2( 8 | ..., 9 | plots = list(...), 10 | layout = NULL, 11 | nrow = NULL, 12 | ncol = NULL, 13 | widths = NULL, 14 | heights = NULL, 15 | byrow = TRUE, 16 | top = NULL, 17 | bottom = NULL, 18 | left = NULL, 19 | right = NULL, 20 | padding = unit(0.5, "line"), 21 | margin = unit(0.5, "line"), 22 | clip = "on", 23 | draw = TRUE, 24 | newpage = TRUE, 25 | debug = FALSE, 26 | labels = NULL, 27 | label.args = list(gp = gpar(font = 4, cex = 1.2)) 28 | ) 29 | } 30 | \arguments{ 31 | \item{...}{ggplot, grobified ggplot (gtable), or geo_scale objects} 32 | 33 | \item{plots}{list of ggplot, gtable, or geo_scale objects} 34 | 35 | \item{layout}{a matrix of integers specifying where each plot should go, like 36 | \code{mat} in \code{\link[graphics:layout]{graphics::layout()}}; \code{NA} or a value less than 0 or greater than 37 | the number of plots indicates a blank plot; overrides nrow/ncol/byrow} 38 | 39 | \item{nrow}{number of rows} 40 | 41 | \item{ncol}{number of columns} 42 | 43 | \item{widths}{list of requested widths} 44 | 45 | \item{heights}{list of requested heights} 46 | 47 | \item{byrow}{logical, fill by rows} 48 | 49 | \item{top}{optional string, or grob} 50 | 51 | \item{bottom}{optional string, or grob} 52 | 53 | \item{left}{optional string, or grob} 54 | 55 | \item{right}{optional string, or grob} 56 | 57 | \item{padding}{unit of length one, margin around annotations} 58 | 59 | \item{margin}{vector of units of length 4: top, right, bottom, left (as in 60 | \code{\link[gtable:gtable_add_padding]{gtable::gtable_add_padding()}})} 61 | 62 | \item{clip}{argument of gtable} 63 | 64 | \item{draw}{logical: draw or return a grob} 65 | 66 | \item{newpage}{logical: draw on a new page} 67 | 68 | \item{debug}{logical, show layout with thin lines} 69 | 70 | \item{labels}{character labels used for annotation of subfigures (should be 71 | in the same order as \code{plots})} 72 | 73 | \item{label.args}{label list of parameters for the formatting of labels} 74 | } 75 | \value{ 76 | gtable of aligned plots 77 | } 78 | \description{ 79 | Arrange multiple ggplot, grobified ggplot, or geo_scale objects on a page, 80 | aligning the plot panels, axes, and axis titles. 81 | } 82 | \examples{ 83 | library(ggplot2) 84 | p1 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) + 85 | geom_point() 86 | p2 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) + 87 | geom_point() + 88 | facet_wrap(~cyl, ncol = 2, scales = "free") + 89 | guides(colour = "none") + 90 | theme() 91 | ggarrange2(p1, p2, widths = c(2, 1), labels = c("a", "b")) 92 | 93 | p3 <- ggplot() + 94 | geom_point(aes(y = runif(1000, 0, 8), x = runif(1000, 0, 1000))) + 95 | scale_x_reverse() + 96 | coord_geo(xlim = c(1000, 0), ylim = c(0, 8)) + 97 | theme_classic() 98 | ggarrange2(ggarrange2(p1, p2, widths = c(2, 1), draw = FALSE), p3, nrow = 2) 99 | } 100 | -------------------------------------------------------------------------------- /tests/testthat/test-coord_geo_polar.R: -------------------------------------------------------------------------------- 1 | skip_if_not_installed("ggtree") 2 | test_that("coord_geo_polar works", { 3 | skip_if_not_installed("ape") 4 | lifecycle::expect_deprecated({ 5 | gg <- revts(ggtree(tree)) + 6 | coord_geo_polar(dat = "stages") + 7 | scale_x_continuous(limits = c(NA, 0)) 8 | }) 9 | expect_true(is_ggplot(gg)) 10 | expect_true(is(ggplot_build(gg)$layout$coord, "CoordGeoPolar")) 11 | expect_doppelganger_deeptime("coord_geo_polar", gg) 12 | expect_equal(ggplot_build(gg)$layout$panel_params[[1]]$r.range, 13 | c(-max(node.depth.edgelength(tree)), 0)) 14 | 15 | withr::local_options(lifecycle_verbosity = "quiet") 16 | gg2 <- revts(ggtree(tree)) + 17 | coord_geo_polar(dat = "stages", fill = c("grey60", "grey80")) + 18 | scale_x_continuous(limits = c(NA, 0)) 19 | expect_true(is_ggplot(gg2)) 20 | expect_true(is(ggplot_build(gg2)$layout$coord, "CoordGeoPolar")) 21 | expect_doppelganger_deeptime("coord_geo_polar_grey", gg2) 22 | 23 | # this doesn't make sense, but let's test it anyways 24 | gg3 <- ggtree(tree) + 25 | coord_geo_polar(dat = "stages", neg = FALSE) + 26 | scale_x_continuous(limits = c(0, NA)) 27 | expect_true(is_ggplot(gg3)) 28 | expect_true(is(ggplot_build(gg3)$layout$coord, "CoordGeoPolar")) 29 | expect_doppelganger_deeptime("coord_geo_polar_pos", gg3) 30 | expect_equal(ggplot_build(gg3)$layout$panel_params[[1]]$r.range, 31 | c(0, max(node.depth.edgelength(tree)))) 32 | 33 | expect_error({ 34 | ggtree(tree) + 35 | coord_geo_polar(direction = "up") 36 | }) 37 | gg4 <- ggtree(tree) + 38 | coord_geo_polar(dat = 5) 39 | expect_error(plot(gg4)) 40 | }) 41 | 42 | test_that("stacking scales works", { 43 | withr::local_options(lifecycle_verbosity = "quiet") 44 | skip_if_not_installed("phytools") 45 | gg <- revts(ggtree(mammal.tree)) + 46 | coord_geo_polar( 47 | dat = list("stages", "periods"), alpha = .5, 48 | prop = list(0.75, .25), start = pi / 4, lty = "dashed" 49 | ) + 50 | scale_y_continuous(expand = expansion(mult = c(0.02, 0.02))) + 51 | theme(deeptime.axis.text.r = element_text(size = 3.5, hjust = .25, 52 | vjust = .75)) 53 | expect_doppelganger_deeptime("stacked scales", gg) 54 | }) 55 | 56 | test_that("ggtree scale works with only fossil taxa", { 57 | withr::local_options(lifecycle_verbosity = "quiet") 58 | skip_if_not_installed("paleotree") 59 | skip_if_not_installed("geomtextpath") 60 | gg <- ggtree(ceratopsianTreeRaia, 61 | position = position_nudge( 62 | x = -ceratopsianTreeRaia$root.time 63 | )) + 64 | coord_geo_polar(dat = "stages") 65 | expect_doppelganger_deeptime("scale on fossil ggtree", gg) 66 | skip_if(R.Version()$os != "mingw32") # only test this on Windows 67 | gg <- ggtree(ceratopsianTreeRaia, 68 | position = position_nudge(x = -ceratopsianTreeRaia$root.time)) + 69 | coord_geo_polar(dat = list("stages", "periods"), 70 | lab = list(FALSE, TRUE), abbrv = TRUE) + 71 | scale_x_continuous(expand = expansion(add = c(20, 30))) 72 | expect_doppelganger_deeptime("scale on fossil ggtree with labels", gg) 73 | }) 74 | -------------------------------------------------------------------------------- /tests/testthat/test-ggarrange2.R: -------------------------------------------------------------------------------- 1 | test_that("ggarrange2() works", { 2 | skip_if_not_installed("paleotree") 3 | p1 <- ggplot(ammoniteTraitsRaia) + 4 | geom_point(aes(x = Log_D, y = FD)) + 5 | labs(x = "Body size", y = "Suture complexity") + 6 | theme_classic() 7 | p2 <- ggplot(ammoniteTraitsRaia) + 8 | geom_point(aes(x = Log_D, y = log_dur)) + 9 | labs(x = "Body size", y = "Stratigraphic duration (myr)") + 10 | theme_classic() 11 | gg1 <- ggarrange2(p1, p2, widths = c(2, 1), draw = FALSE, 12 | labels = c("A", "B")) 13 | expect_true(gtable::is.gtable(gg1)) 14 | expect_doppelganger_deeptime("ggarrange2()", gg1) 15 | expect_doppelganger_deeptime("ggarrange2() layout", 16 | gtable::gtable_show_layout(gg1)) 17 | 18 | gg2 <- ggarrange2(p1, p2, layout = matrix(c(2, 0, 0, 1), nrow = 2), 19 | widths = c(2, 1), draw = FALSE, labels = c("A", "B"), 20 | debug = TRUE) 21 | expect_doppelganger_deeptime("ggarrange2() with layout", gg2) 22 | expect_doppelganger_deeptime("ggarrange2() with layout (layout)", 23 | gtable::gtable_show_layout(gg2)) 24 | 25 | skip_if_not_installed("ggtree") 26 | p3 <- ggtree(ammoniteTreeRaia, 27 | position = position_nudge(x = -ammoniteTreeRaia$root.time)) + 28 | coord_geo(xlim = c(-415, -66), ylim = c(-2, Ntip(ammoniteTreeRaia)), 29 | pos = "bottom", size = 4, abbrv = FALSE, neg = TRUE) + 30 | scale_x_continuous(breaks = seq(-425, -50, 25), 31 | labels = -seq(-425, -50, 25)) + 32 | theme_tree2() + 33 | theme(plot.margin = margin(7, 11, 7, 11)) 34 | 35 | gg3 <- ggarrange2(gg1, p3, 36 | nrow = 2, widths = unit(60, "lines"), 37 | heights = c(unit(20, "lines"), unit(40, "lines")), 38 | top = "Test1", bottom = "Test2", left = "Test3", right = "Test4", 39 | newpage = TRUE, draw = FALSE 40 | ) 41 | expect_true(gtable::is.gtable(gg3)) 42 | expect_doppelganger_deeptime("double ggarrange2()", print(gg3)) 43 | expect_doppelganger_deeptime("double ggarrange2() layout", 44 | gtable::gtable_show_layout(gg3)) 45 | 46 | gg4 <- ggarrange2(p1, .dummy_gtable, 47 | ncol = 2, heights = unit(20, "lines"), 48 | top = "Test1", bottom = "Test2", 49 | left = "Test3", right = "Test4", 50 | newpage = TRUE, draw = FALSE) 51 | expect_true(gtable::is.gtable(gg4)) 52 | expect_doppelganger_deeptime("ggarrange2() no heights", print(gg4)) 53 | expect_doppelganger_deeptime("ggarrange2() no heights layout", 54 | gtable::gtable_show_layout(gg4)) 55 | 56 | p1_grob <- ggplotGrob(p1) 57 | p1_grob$respect <- TRUE 58 | gg5 <- ggarrange2(p1_grob, .dummy_gtable, 59 | top = "Test1", bottom = "Test2", 60 | left = "Test3", right = "Test4", 61 | newpage = TRUE, draw = TRUE) 62 | expect_true(gtable::is.gtable(gg5)) 63 | expect_doppelganger_deeptime("ggarrange2() no dims", print(gg5)) 64 | expect_doppelganger_deeptime("ggarrange2() no dims layout", 65 | gtable::gtable_show_layout(gg5)) 66 | }) 67 | -------------------------------------------------------------------------------- /R/gggeo_scale_old.R: -------------------------------------------------------------------------------- 1 | #' Add a geologic scale on top of ggplots 2 | #' 3 | #' @description 4 | #' `r lifecycle::badge('deprecated')` 5 | #' 6 | #' This function takes a ggplot object and adds a geologic time scale at the 7 | #' specified side. 8 | #' 9 | #' @details 10 | #' If custom data is provided (with `dat`), it should consist of at least 3 11 | #' columns of data. See `data(periods)` for an example. 12 | #' \itemize{ 13 | #' \item The `name` column lists the names of each time interval. These will 14 | #' be used as labels if no abbreviations are provided. 15 | #' \item The `max_age` column lists the oldest boundary of each time interval. 16 | #' \item The `min_age` column lists the youngest boundary of each time 17 | #' interval. 18 | #' \item The `abbr` column is optional and lists abbreviations that may be 19 | #' used as labels. 20 | #' \item The `color` column is also optional and lists a hex color code (which 21 | #' can be obtained with `rgb()`) for each time interval. 22 | #' } 23 | #' @section Life cycle: 24 | #' This function is fully deprecated in favor of [coord_geo()] as of 25 | #' **deeptime** version 2.0.0. It will be removed in a future version. 26 | #' @param gg The ggplot object. 27 | #' @param dat Either A) a string indicating a built-in dataframe with interval 28 | #' data from the ICS ("periods", "epochs", "stages", "eons", or "eras"), 29 | #' B) a string indicating a timescale from macrostrat (see list here: 30 | #' ), 31 | #' or C) a custom dataframe of time interval boundaries (see Details). 32 | #' @param fill The fill color of the boxes. The default is to use the colors 33 | #' included in `dat`. If a custom dataset is provided with `dat` without color 34 | #' and without fill, a greyscale will be used. Custom fill colors can be 35 | #' provided with this option and will be recycled if/as necessary. 36 | #' @param color The outline color of the interval boxes. 37 | #' @param alpha The transparency of the fill colors. 38 | #' @param height The proportional height (or width if `pos` is `left` or 39 | #' `right`) of the entire plot to use for the scale. 40 | #' @param gap The proportional height (or width) of the entire plot to use as a 41 | #' gap between the axis and the scale. 42 | #' @param pos Which side to add the scale to (left, right, top, or bottom). 43 | #' First letter may also be used. 44 | #' @param lab Whether to include labels. 45 | #' @param rot The amount of counter-clockwise rotation to add to the labels (in 46 | #' degrees). 47 | #' @param abbrv If including labels, whether to use abbreviations instead of 48 | #' full interval names. 49 | #' @param skip A vector of interval names indicating which intervals should not 50 | #' be labeled. 51 | #' @param size Label size. 52 | #' @param neg Set this to true if your x-axis is using negative values. 53 | #' @return A ggplot object. 54 | #' @keywords internal 55 | #' @export 56 | gggeo_scale_old <- 57 | function(gg, dat = "periods", fill = NULL, color = "black", alpha = 1, 58 | height = .05, gap = 0, pos = "bottom", lab = TRUE, rot = 0, 59 | abbrv = TRUE, skip = c("Quaternary", "Holocene", "Late Pleistocene"), 60 | size = 5, neg = FALSE) { 61 | lifecycle::deprecate_stop("2.0.0", "gggeo_scale_old()", "coord_geo()") 62 | } 63 | -------------------------------------------------------------------------------- /.github/workflows/rhub.yaml: -------------------------------------------------------------------------------- 1 | # R-hub's generic GitHub Actions workflow file. It's canonical location is at 2 | # https://github.com/r-hub/actions/blob/v1/workflows/rhub.yaml 3 | # You can update this file to a newer version using the rhub2 package: 4 | # 5 | # rhub::rhub_setup() 6 | # 7 | # It is unlikely that you need to modify this file manually. 8 | 9 | name: R-hub 10 | run-name: "${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}" 11 | 12 | on: 13 | workflow_dispatch: 14 | inputs: 15 | config: 16 | description: 'A comma separated list of R-hub platforms to use.' 17 | type: string 18 | default: 'linux,windows,macos' 19 | name: 20 | description: 'Run name. You can leave this empty now.' 21 | type: string 22 | id: 23 | description: 'Unique ID. You can leave this empty now.' 24 | type: string 25 | 26 | jobs: 27 | 28 | setup: 29 | runs-on: ubuntu-latest 30 | outputs: 31 | containers: ${{ steps.rhub-setup.outputs.containers }} 32 | platforms: ${{ steps.rhub-setup.outputs.platforms }} 33 | 34 | steps: 35 | # NO NEED TO CHECKOUT HERE 36 | - uses: r-hub/actions/setup@v1 37 | with: 38 | config: ${{ github.event.inputs.config }} 39 | id: rhub-setup 40 | 41 | linux-containers: 42 | needs: setup 43 | if: ${{ needs.setup.outputs.containers != '[]' }} 44 | runs-on: ubuntu-latest 45 | name: ${{ matrix.config.label }} 46 | strategy: 47 | fail-fast: false 48 | matrix: 49 | config: ${{ fromJson(needs.setup.outputs.containers) }} 50 | container: 51 | image: ${{ matrix.config.container }} 52 | 53 | steps: 54 | - uses: r-hub/actions/checkout@v1 55 | - uses: r-hub/actions/platform-info@v1 56 | with: 57 | token: ${{ secrets.RHUB_TOKEN }} 58 | job-config: ${{ matrix.config.job-config }} 59 | - uses: r-hub/actions/setup-deps@v1 60 | with: 61 | token: ${{ secrets.RHUB_TOKEN }} 62 | job-config: ${{ matrix.config.job-config }} 63 | - uses: r-hub/actions/run-check@v1 64 | with: 65 | token: ${{ secrets.RHUB_TOKEN }} 66 | job-config: ${{ matrix.config.job-config }} 67 | 68 | other-platforms: 69 | needs: setup 70 | if: ${{ needs.setup.outputs.platforms != '[]' }} 71 | runs-on: ${{ matrix.config.os }} 72 | name: ${{ matrix.config.label }} 73 | strategy: 74 | fail-fast: false 75 | matrix: 76 | config: ${{ fromJson(needs.setup.outputs.platforms) }} 77 | 78 | steps: 79 | - uses: r-hub/actions/checkout@v1 80 | - uses: r-hub/actions/setup-r@v1 81 | with: 82 | job-config: ${{ matrix.config.job-config }} 83 | token: ${{ secrets.RHUB_TOKEN }} 84 | - uses: r-hub/actions/platform-info@v1 85 | with: 86 | token: ${{ secrets.RHUB_TOKEN }} 87 | job-config: ${{ matrix.config.job-config }} 88 | - uses: r-hub/actions/setup-deps@v1 89 | with: 90 | job-config: ${{ matrix.config.job-config }} 91 | token: ${{ secrets.RHUB_TOKEN }} 92 | - uses: r-hub/actions/run-check@v1 93 | with: 94 | job-config: ${{ matrix.config.job-config }} 95 | token: ${{ secrets.RHUB_TOKEN }} 96 | -------------------------------------------------------------------------------- /R/coord_trans_flip.R: -------------------------------------------------------------------------------- 1 | #' Transformed and flipped Cartesian coordinate system 2 | #' 3 | #' `coord_trans_flip` behaves similarly to [ggplot2::coord_trans()] in that it 4 | #' occurs after statistical transformation and will affect the visual appearance 5 | #' of geoms. The main difference is that it also flips the x and y coordinates 6 | #' like [ggplot2::coord_flip()]. 7 | #' 8 | #' @importFrom ggplot2 ggproto 9 | #' @inheritParams ggplot2::coord_trans 10 | #' @export 11 | #' @examples 12 | #' library(ggplot2) 13 | #' ggplot(mtcars, aes(disp, wt)) + 14 | #' geom_point() + 15 | #' coord_trans_flip(x = "log10", y = "log10") 16 | coord_trans_flip <- function(x = "identity", y = "identity", 17 | xlim = NULL, ylim = NULL, 18 | clip = "on", expand = TRUE) { 19 | # resolve transformers 20 | if (is.character(x)) x <- as.trans(x) 21 | if (!is.trans(x)) { 22 | cli::cli_abort("`x` must be a transformer function or a string.") 23 | } 24 | if (is.character(y)) y <- as.trans(y) 25 | if (!is.trans(y)) { 26 | cli::cli_abort("`y` must be a transformer function or a string.") 27 | } 28 | 29 | # check arguments 30 | clip <- arg_match0(clip, c("off", "on")) 31 | check_bool(expand) 32 | 33 | ggproto(NULL, CoordTransFlip, 34 | trans = list(x = x, y = y), 35 | limits = list(x = xlim, y = ylim), 36 | expand = expand, 37 | clip = clip 38 | ) 39 | } 40 | 41 | # copied from ggplot2 42 | flip_axis_labels <- function(x) { 43 | old_names <- names(x) 44 | 45 | new_names <- old_names 46 | new_names <- gsub("^x", "z", new_names) 47 | new_names <- gsub("^y", "x", new_names) 48 | new_names <- gsub("^z", "y", new_names) 49 | 50 | setNames(x, new_names) 51 | } 52 | 53 | #' @rdname coord_trans_flip 54 | #' @format NULL 55 | #' @usage NULL 56 | #' @importFrom ggplot2 ggproto CoordTrans CoordFlip ggproto_parent 57 | #' @export 58 | CoordTransFlip <- ggproto("CoordTransFlip", CoordFlip, 59 | transform = function(self, data, panel_params) { 60 | # Need the panel params to be unflipped to correctly transform the data 61 | panel_params <- flip_axis_labels(panel_params) 62 | data <- ggproto_parent(CoordTrans, self)$transform(data, panel_params) 63 | flip_axis_labels(data) 64 | }, 65 | backtransform_range = function(self, panel_params) { 66 | un_flipped_range <- 67 | ggproto_parent(CoordTrans, self)$backtransform_range(panel_params) 68 | list(x = un_flipped_range$y, y = un_flipped_range$x) 69 | }, 70 | range = function(self, panel_params) { 71 | # summarise_layout() expects the original x and y ranges here, 72 | # not the ones we would get after flipping the axes 73 | un_flipped_range <- ggproto_parent(CoordTrans, self)$range(panel_params) 74 | list(x = un_flipped_range$y, y = un_flipped_range$x) 75 | }, 76 | setup_panel_params = function(self, scale_x, scale_y, params = list()) { 77 | parent <- ggproto_parent(CoordTrans, self) 78 | panel_params <- parent$setup_panel_params(scale_x, scale_y, params) 79 | flip_axis_labels(panel_params) 80 | }, 81 | labels = function(labels, panel_params) { 82 | CoordTrans$labels(flip_axis_labels(labels), panel_params) 83 | }, 84 | setup_layout = function(layout, params) { 85 | CoordFlip$setup_layout(layout, params) 86 | }, 87 | modify_scales = function(scales_x, scales_y) { 88 | CoordFlip$modify_scales(scales_x, scales_y) 89 | } 90 | ) 91 | -------------------------------------------------------------------------------- /man/geo_pattern.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.R 3 | \name{geo_pattern} 4 | \alias{geo_pattern} 5 | \alias{geo_grob} 6 | \title{Get a FGDC geologic plotting pattern} 7 | \usage{ 8 | geo_pattern( 9 | code, 10 | scale = 2, 11 | col = NULL, 12 | fill = NULL, 13 | alpha = NULL, 14 | bg = "white" 15 | ) 16 | 17 | geo_grob(code, col = NULL, fill = NULL, alpha = NULL, bg = "white") 18 | } 19 | \arguments{ 20 | \item{code}{The number corresponding to the pattern to return. Strings and 21 | numbers are permitted.} 22 | 23 | \item{scale}{The visual scale of the pattern (higher values mean the pattern 24 | is more zoomed in).} 25 | 26 | \item{col}{The color to use for the lines of the pattern.} 27 | 28 | \item{fill}{The color used to fill various closed shapes (e.g., circles) in 29 | the pattern.} 30 | 31 | \item{alpha}{The transparency to use for the fill of the pattern.} 32 | 33 | \item{bg}{The background color to use for the pattern.} 34 | } 35 | \value{ 36 | \code{geo_grob()} returns a \link[grid:gTree]{grob} object with a single 37 | instance of the desired pattern. \code{geo_pattern()} returns a 38 | \link[grid:patterns]{GridPattern} object with a repeated instance of the 39 | desired pattern. 40 | } 41 | \description{ 42 | Retrieve a single geologic pattern as defined in the \href{https://ngmdb.usgs.gov/fgdc_gds/geolsymstd.php}{FGDC Digital Cartographic Standard for Geologic Map Symbolization} by the \href{https://www.usgs.gov/}{U.S. Geological Survey} and the \href{https://ngmdb.usgs.gov/fgdc_gds/index.php}{Geologic Data Subcommittee (GDS)} of the \href{https://www.fgdc.gov/}{Federal Geographic Data Committee (FGDC)}. 43 | } 44 | \details{ 45 | For specific codes, see the "pattern numbers" in the \href{https://ngmdb.usgs.gov/fgdc_gds/geolsymstd/fgdc-geolsym-patternchart.pdf}{full pattern chart} 46 | for valid \code{code} values. Daven Quinn has also assembled more accessible 47 | documentation of the \href{https://davenquinn.com/projects/geologic-patterns/#pattern-reference}{map patterns/codes} 48 | and \href{https://davenquinn.com/projects/geologic-patterns/#series-600}{lithology patterns/codes}. 49 | The set of patterns with names is also included in the built-in dataset 50 | \link{fgdc_names} (and a label dictionary is available using \code{\link[=fgdc_dict]{fgdc_dict()}}. 51 | \code{\link[rmacrostrat:def_lithologies]{rmacrostrat::def_lithologies()}} can also be used to look up pattern codes 52 | for various lithologies (see the "fill" column). Note that codes associated 53 | with color variants (e.g., "101-M") are supported but will result in the 54 | default color variant instead (usually black and white, e.g., "101-K"). 55 | 56 | These patterns were originally processed and optimized by Daven Quinn and 57 | are hosted on \href{https://github.com/davenquinn/geologic-patterns/}{GitHub}. 58 | } 59 | \examples{ 60 | library(grid) 61 | # Get a generic igneous pattern 62 | pattern1 <- geo_pattern(code = "313-K") 63 | # Get the pattern for a sandstone 64 | pattern2 <- geo_pattern(code = "607") 65 | 66 | # plot the two patterns 67 | grid.newpage() 68 | grid.draw(rectGrob(gp = gpar(fill = pattern1))) 69 | grid.newpage() 70 | grid.draw(rectGrob(gp = gpar(fill = pattern2))) 71 | } 72 | \seealso{ 73 | FGDC patterns: 74 | \code{\link{fgdc_dict}()}, 75 | \code{\link{fgdc_names}}, 76 | \code{\link{grid.pattern_geo}()}, 77 | \code{\link{scale_fill_geopattern}()} 78 | } 79 | \concept{patterns} 80 | -------------------------------------------------------------------------------- /tests/testthat/setup-data.R: -------------------------------------------------------------------------------- 1 | suppressPackageStartupMessages(library(ggplot2, quietly = TRUE)) 2 | 3 | if (suppressPackageStartupMessages(require(divDyn, quietly = TRUE))) { 4 | data(corals) 5 | corals_stages_clean <- subset(corals, stage != "") 6 | coral_div <- aggregate(cbind(n = genus) ~ stage, 7 | data = corals_stages_clean, 8 | FUN = function(x) length(x) 9 | ) 10 | coral_div$stage_age <- (stages$max_age[match(coral_div$stage, stages$name)] + 11 | stages$min_age[match(coral_div$stage, stages$name)]) / 2 12 | 13 | coral_div_diet <- aggregate(cbind(n = genus) ~ stage + diet, 14 | data = corals_stages_clean, 15 | FUN = function(x) length(x) 16 | ) 17 | coral_div_diet$stage_age <- 18 | (stages$max_age[match(coral_div_diet$stage, stages$name)] + 19 | stages$min_age[match(coral_div_diet$stage, stages$name)]) / 2 20 | 21 | corals_periods_clean <- subset(corals, period != "") 22 | coral_div_dis <- aggregate(cbind(n = genus) ~ period + diet, 23 | data = corals_periods_clean, 24 | FUN = function(x) length(x) 25 | ) 26 | coral_div_dis$period_age <- 27 | (periods$max_age[match(coral_div_dis$period, periods$name)] + 28 | periods$min_age[match(coral_div_dis$period, periods$name)]) / 2 29 | coral_div_dis <- 30 | coral_div_dis[rev(order(coral_div_dis$period_age)), , drop = FALSE] 31 | coral_div_dis$period <- factor(coral_div_dis$period, 32 | levels = unique(coral_div_dis$period)) 33 | } 34 | 35 | if (suppressPackageStartupMessages(require(ape, quietly = TRUE))) { 36 | set.seed(1) 37 | tree <- rtree(100) 38 | } 39 | 40 | if (suppressPackageStartupMessages(require(paleotree, quietly = TRUE))) { 41 | data(RaiaCopesRule) 42 | } 43 | 44 | if (suppressPackageStartupMessages(require(phytools, quietly = TRUE))) { 45 | data(mammal.tree) 46 | } 47 | 48 | if (suppressPackageStartupMessages(require(dispRity, quietly = TRUE))) { 49 | data(demo_data) 50 | } 51 | 52 | if (suppressPackageStartupMessages(require(palaeoverse, quietly = TRUE))) { 53 | data(tetrapods) 54 | } 55 | 56 | suppressPackageStartupMessages(require(gsloid, quietly = TRUE)) 57 | suppressPackageStartupMessages(require(ggtree, quietly = TRUE)) 58 | suppressPackageStartupMessages(require(dispRity, quietly = TRUE)) 59 | suppressPackageStartupMessages(require(grid, quietly = TRUE)) 60 | suppressPackageStartupMessages(require(ggpattern, quietly = TRUE)) 61 | 62 | # copied from vdiffr 63 | str_standardise <- function(s, sep = "-") { 64 | s <- gsub("[^a-z0-9]", sep, tolower(s)) 65 | s <- gsub(paste0(sep, sep, "+"), sep, s) 66 | s <- gsub(paste0("^", sep, "|", sep, "$"), "", s) 67 | s 68 | } 69 | 70 | # copied from https://github.com/r-lib/vdiffr/issues/132#issuecomment-1477006436 71 | write_svg_bleeding_edge <- function(plot, file, title = "") { 72 | svglite::svglite(file) 73 | on.exit(grDevices::dev.off()) 74 | # warning: `print_plot()` is not exported by {vdiffr} 75 | vdiffr:::print_plot(plot, title) 76 | } 77 | 78 | expect_doppelganger_deeptime <- function(title, fig, patterns = FALSE) { 79 | title_new <- paste(title, "new") 80 | fig_name <- str_standardise(title_new) 81 | file <- paste0(fig_name, ".svg") 82 | announce_snapshot_file(name = file) 83 | 84 | variant <- switch(packageVersion("ggplot2") > "3.5.2", "ggplot4", NULL) 85 | 86 | if (patterns) { 87 | expect_doppelganger(title_new, fig, writer = write_svg_bleeding_edge, 88 | variant = variant) 89 | } else { 90 | expect_doppelganger(title_new, fig, variant = variant) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /man/gggeo_scale_old.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gggeo_scale_old.R 3 | \name{gggeo_scale_old} 4 | \alias{gggeo_scale_old} 5 | \title{Add a geologic scale on top of ggplots} 6 | \usage{ 7 | gggeo_scale_old( 8 | gg, 9 | dat = "periods", 10 | fill = NULL, 11 | color = "black", 12 | alpha = 1, 13 | height = 0.05, 14 | gap = 0, 15 | pos = "bottom", 16 | lab = TRUE, 17 | rot = 0, 18 | abbrv = TRUE, 19 | skip = c("Quaternary", "Holocene", "Late Pleistocene"), 20 | size = 5, 21 | neg = FALSE 22 | ) 23 | } 24 | \arguments{ 25 | \item{gg}{The ggplot object.} 26 | 27 | \item{dat}{Either A) a string indicating a built-in dataframe with interval 28 | data from the ICS ("periods", "epochs", "stages", "eons", or "eras"), 29 | B) a string indicating a timescale from macrostrat (see list here: 30 | \url{https://macrostrat.org/api/defs/timescales?all}), 31 | or C) a custom dataframe of time interval boundaries (see Details).} 32 | 33 | \item{fill}{The fill color of the boxes. The default is to use the colors 34 | included in \code{dat}. If a custom dataset is provided with \code{dat} without color 35 | and without fill, a greyscale will be used. Custom fill colors can be 36 | provided with this option and will be recycled if/as necessary.} 37 | 38 | \item{color}{The outline color of the interval boxes.} 39 | 40 | \item{alpha}{The transparency of the fill colors.} 41 | 42 | \item{height}{The proportional height (or width if \code{pos} is \code{left} or 43 | \code{right}) of the entire plot to use for the scale.} 44 | 45 | \item{gap}{The proportional height (or width) of the entire plot to use as a 46 | gap between the axis and the scale.} 47 | 48 | \item{pos}{Which side to add the scale to (left, right, top, or bottom). 49 | First letter may also be used.} 50 | 51 | \item{lab}{Whether to include labels.} 52 | 53 | \item{rot}{The amount of counter-clockwise rotation to add to the labels (in 54 | degrees).} 55 | 56 | \item{abbrv}{If including labels, whether to use abbreviations instead of 57 | full interval names.} 58 | 59 | \item{skip}{A vector of interval names indicating which intervals should not 60 | be labeled.} 61 | 62 | \item{size}{Label size.} 63 | 64 | \item{neg}{Set this to true if your x-axis is using negative values.} 65 | } 66 | \value{ 67 | A ggplot object. 68 | } 69 | \description{ 70 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} 71 | 72 | This function takes a ggplot object and adds a geologic time scale at the 73 | specified side. 74 | } 75 | \details{ 76 | If custom data is provided (with \code{dat}), it should consist of at least 3 77 | columns of data. See \code{data(periods)} for an example. 78 | \itemize{ 79 | \item The \code{name} column lists the names of each time interval. These will 80 | be used as labels if no abbreviations are provided. 81 | \item The \code{max_age} column lists the oldest boundary of each time interval. 82 | \item The \code{min_age} column lists the youngest boundary of each time 83 | interval. 84 | \item The \code{abbr} column is optional and lists abbreviations that may be 85 | used as labels. 86 | \item The \code{color} column is also optional and lists a hex color code (which 87 | can be obtained with \code{rgb()}) for each time interval. 88 | } 89 | } 90 | \section{Life cycle}{ 91 | 92 | This function is fully deprecated in favor of \code{\link[=coord_geo]{coord_geo()}} as of 93 | \strong{deeptime} version 2.0.0. It will be removed in a future version. 94 | } 95 | 96 | \keyword{internal} 97 | -------------------------------------------------------------------------------- /man/disparity_through_time.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/disparity_through_time.R 3 | \name{disparity_through_time} 4 | \alias{disparity_through_time} 5 | \title{Disparity through time plot using lattice} 6 | \usage{ 7 | disparity_through_time( 8 | x, 9 | data, 10 | groups, 11 | pch = 16, 12 | col.point = c("blue"), 13 | scales = list(arrows = FALSE, distance = 1, col = "black", z = list(rot = 90)), 14 | colorkey = FALSE, 15 | screen = list(z = 90, x = 70, y = 180), 16 | aspect = c(1.5, 4), 17 | drape = TRUE, 18 | col.regions = c("white"), 19 | alpha.regions = c(1), 20 | perspective = FALSE, 21 | R.mat = matrix(c(1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1), 4, 4), 22 | par.settings = list(axis.line = list(col = "transparent"), layout.heights = 23 | list(top.padding = 0, main.key.padding = 0, key.axis.padding = 0, axis.xlab.padding = 24 | 0, xlab.key.padding = 0, key.sub.padding = 0, bottom.padding = 0), layout.widths = 25 | list(left.padding = 0, key.ylab.padding = 0, ylab.axis.padding = 0, axis.key.padding 26 | = 0, right.padding = 0)), 27 | lattice.options = list(axis.padding = list(factor = 0)), 28 | ... 29 | ) 30 | } 31 | \arguments{ 32 | \item{x}{a formula (most likely of the form \code{z ~ x * y})} 33 | 34 | \item{data}{a data frame in which variables in the formula are to be 35 | evaluated} 36 | 37 | \item{groups}{a variable in \code{data} to be used as a grouping variable (this is 38 | probably the z variable)} 39 | 40 | \item{pch}{the point type} 41 | 42 | \item{col.point}{color(s) for points on surfaces} 43 | 44 | \item{scales}{a list specifying how the axes are drawn (see 45 | \code{\link[lattice:xyplot]{lattice::xyplot()}} for details)} 46 | 47 | \item{colorkey}{logical, should a legend be drawn (or a list describing the 48 | legend; see \code{\link[lattice:levelplot]{lattice::levelplot()}} for details)} 49 | 50 | \item{screen}{a list of the rotations that should be applied to each axis} 51 | 52 | \item{aspect}{a numeric vector of length 2, giving the relative aspects of 53 | the y-size/x-size and z-size/x-size of the enclosing cube} 54 | 55 | \item{drape}{logical, whether the surfaces should be colored based on 56 | \code{col.regions} and \code{alpha.regions}} 57 | 58 | \item{col.regions}{color(s) for surfaces} 59 | 60 | \item{alpha.regions}{alpha value(s) for surfaces} 61 | 62 | \item{perspective}{logical, whether to plot a perspective view} 63 | 64 | \item{R.mat}{a transformational matrix that is applied to the orientation of 65 | the axes} 66 | 67 | \item{par.settings}{plotting settings (see \code{\link[lattice:trellis.par.get]{lattice::trellis.par.set()}})} 68 | 69 | \item{lattice.options}{lattice settings (see \code{\link[lattice:lattice.options]{lattice::lattice.options()}})} 70 | 71 | \item{...}{Other arguments passed to \code{\link[lattice:cloud]{lattice::wireframe()}}} 72 | } 73 | \value{ 74 | An object of class \code{"trellis"}, as output by \code{\link[lattice:cloud]{lattice::wireframe()}}. 75 | } 76 | \description{ 77 | Plots points on 2-D surfaces within a a 3-D framework. See 78 | \code{\link[lattice:cloud]{lattice::wireframe()}} and \code{\link[lattice:panel.cloud]{lattice::panel.cloud()}} for customization 79 | options. 80 | } 81 | \examples{ 82 | g <- data.frame( 83 | x = runif(100, 0, 60), y = runif(100, 0, 10), 84 | z = factor(rep(periods$name[1:5], each = 20), 85 | levels = periods$name[1:5] 86 | ) 87 | ) 88 | disparity_through_time(z ~ x * y, 89 | data = g, groups = z, aspect = c(1.5, 2), 90 | xlim = c(0, 60), ylim = c(0, 10), col.regions = "lightgreen", 91 | col.point = c("red", "blue") 92 | ) 93 | } 94 | -------------------------------------------------------------------------------- /vignettes/coord.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Transforming coordinate systems" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Transforming coordinate systems} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set(collapse = TRUE, fig.width = 7, fig.height = 5, fig.align = "center") 12 | ``` 13 | 14 |
15 | `{ggplot2}` has many built-in [coordinate systems](https://ggplot2-book.org/coord.html) which are used to both 1) produce the two-dimensional position of the plotted data and 2) draw custom axes and panel backgrounds. `coord_geo()` uses this second purpose to draw special axes that include timescales. However, __deeptime__ also includes a number of other coordinate systems whose primary function is to modify the way data is plotted. To demonstrate this, we'll first need to load some packages. 16 | 17 | ```{r message = FALSE} 18 | # Load deeptime 19 | library(deeptime) 20 | # Load ggplot for making plots 21 | # It has some example data too 22 | library(ggplot2) 23 | ``` 24 | 25 | ## coord_trans meets coord_flip 26 | One limitation of the traditional `coord_trans()` function in `{ggplot2}` is that you can not flip the axes while also transforming the axes. Historically, you would need to either 1) use `scale_x_continuous()` or `scale_y_continuous()` to transform one or both of your axes (which could result in the untransparent loss of data) in combination with `coord_flip()` or 2) transform your data before supplying it to `ggplot()`. `coord_trans_flip()` accomplishes this without the need for `scales` or transforming your data. It works just like `coord_trans()`, with the added functionality of the axis flip from `coord_flip()`. 27 | ```{r} 28 | ggplot(mtcars, aes(disp, wt)) + 29 | geom_point() + 30 | coord_trans_flip(x = "sqrt", y = "log10") + 31 | theme_classic() 32 | ``` 33 | 34 | 35 | Note: back in 2020, `{ggplot2}` [updated](https://tidyverse.org/blog/2020/03/ggplot2-3-3-0/#bi-directional-geoms-and-stats) all the directional stats and geoms (e.g., boxplots and histograms) to work in both directions based on the aesthetic mapping. This somewhat makes this function redundant, but I still find it useful. 36 | 37 | ## 2D linear transformations 38 | Another limitation of the traditional `coord_trans()` is that each axis is transformed independently. `coord_trans_xy()` expands this functionality to allow for a two-dimensional linear transformation as generated by `ggforce::linear_trans()`. This allows for rotations, stretches, shears, translations, and reflections. A dummy example using the `?mtcars` dataset from `{ggplot2}` is included below. While applications of this functionality may seem abstract for real data, see the [plotting traits](traits.html) article for a potential real-world application using species trait data. 39 | 40 | 41 | ```{r} 42 | # make transformer 43 | library(ggforce) 44 | trans <- linear_trans(shear(50, 0)) 45 | 46 | # set up data to be plotted 47 | square <- data.frame( 48 | disp = c( 49 | min(mtcars$disp), min(mtcars$disp), 50 | max(mtcars$disp), max(mtcars$disp) 51 | ), 52 | wt = c( 53 | min(mtcars$wt), max(mtcars$wt), 54 | max(mtcars$wt), min(mtcars$wt) 55 | ) 56 | ) 57 | 58 | # plot data normally 59 | library(ggplot2) 60 | ggplot(mtcars, aes(disp, wt)) + 61 | geom_polygon(data = square, fill = NA, color = "black") + 62 | geom_point(color = "black") + 63 | coord_cartesian() + 64 | theme_classic() 65 | # plot data with transformation 66 | ggplot(mtcars, aes(disp, wt)) + 67 | geom_polygon(data = square, fill = NA, color = "black") + 68 | geom_point(color = "black") + 69 | coord_trans_xy(trans = trans, expand = TRUE) + 70 | theme_classic() 71 | ``` 72 | 73 |
74 | -------------------------------------------------------------------------------- /man/get_scale_data.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_scale_data.R 3 | \name{get_scale_data} 4 | \alias{get_scale_data} 5 | \title{Get geological timescale data} 6 | \usage{ 7 | get_scale_data(name, true_colors = TRUE) 8 | } 9 | \arguments{ 10 | \item{name}{The name of the desired timescale.} 11 | 12 | \item{true_colors}{Return original international time scale colors? (as 13 | opposed to custom Macrostrat plotting colors)} 14 | } 15 | \value{ 16 | A \code{data.frame} with the following columns: 17 | \item{name}{the names of the time intervals} 18 | \item{max_age}{the oldest boundaries of the time intervals, in millions of 19 | years} 20 | \item{min_age}{the youngest boundaries of the time intervals, in millions 21 | of years} 22 | \item{abbr}{either traditional abbreviations of the names of the time 23 | intervals (if they exist) or custom abbreviations created with R} 24 | \item{color}{hex color codes associated with the time intervals (if 25 | applicable)} 26 | \item{lab_color}{default label colors for the time interals, either white 27 | or black, whichever has better contrast with the background color, based 28 | on \href{https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en}{recommendations by the International Telecommunication Union}} 29 | } 30 | \description{ 31 | This function takes a name of a geological timescale and returns data for the 32 | timescale. Valid names include those of built-in \code{data.frames} (\code{\link[=periods]{periods()}}, 33 | \code{\link[=epochs]{epochs()}}, \code{\link[=stages]{stages()}}, \code{\link[=eons]{eons()}}, or \code{\link[=eras]{eras()}}), partial matches of those 34 | names (e.g., "per" or "age"), and partial or exact matches to those hosted 35 | by Macrostrat (see Details below). Note that the colors in the built-in 36 | \code{data.frames} are according to the Commission for the Geological Map of the 37 | World. If you would like to obtain custom Macrostrat colors that are better 38 | for mapping, you should specify the full name of a timescale (e.g., 39 | "international periods") and set \code{true_colors} to \code{FALSE}. Note that these 40 | colors only vary for the Precambrian. 41 | } 42 | \details{ 43 | The following timescales are available from the Macrostrat API as of 44 | 2025-11-19: 45 | \itemize{ 46 | \item international ages 47 | \item international epochs 48 | \item international periods 49 | \item calcareous nannoplankton zones 50 | \item New Zealand ages 51 | \item custom COSUNA 52 | \item North American land mammal ages 53 | \item international intervals 54 | \item COSUNA 55 | \item international eras 56 | \item international eons 57 | \item Trilobite Zonation - Laurentia 58 | \item Conodont Zonation 59 | \item North American Regional 60 | \item Ammonite Zonation - Boreal 61 | \item Ammonite Zonation - Western Interior 62 | \item international intervals covering all time 63 | \item Scotese Reconstruction 64 | \item Geomagnetic Polarity Chron 65 | \item Geomagnetic Polarity Subchron 66 | \item Planktic foraminiferal Primary Biozones 67 | \item Planktic foraminiferal Secondary Biozones 68 | \item Planktic foraminiferal datums 69 | \item Martian Periods 70 | \item Martian Epochs 71 | \item Cretaceous Planktic foraminifer zonations 72 | \item Low latitude radiolarian zonation 73 | \item Neogene North Pacific Diatom Biochronology 74 | \item Neogene North Pacific Diatom Biochronology Subzones 75 | \item Siberian Regional 76 | \item Australian Regional 77 | \item Western Europe Regional 78 | \item Russian Platform Regional Stages 79 | \item Russian Precambrian Eras 80 | \item Russian Precambrian Eons 81 | \item Russian Epochs 82 | \item Russian Stages 83 | } 84 | 85 | The most up-to-date list can be found via the Macrostrat API \href{https://macrostrat.org/api/defs/timescales?all}{here}. 86 | } 87 | -------------------------------------------------------------------------------- /data-raw/names.txt: -------------------------------------------------------------------------------- 1 | 601 Gravel or conglomerate (1st option) 2 | 602 Gravel or conglomerate (2nd option) 3 | 603 Crossbedded gravel or conglomerate 4 | 605 Breccia (1st option) 5 | 606 Breccia (2nd option) 6 | 607 Massive sand or sandstone 7 | 608 Bedded sand or sandstone 8 | 609 Crossbedded sand or sandstone (1st option) 9 | 610 Crossbedded sand or sandstone (2nd option) 10 | 611 Ripple-bedded sand or sandstone 11 | 612 Argillaceous or shaly sandstone 12 | 613 Calcareous sandstone 13 | 614 Dolomitic sandstone 14 | 616 Silt, siltstone, or shaly silt 15 | 617 Calcareous siltstone 16 | 618 Dolomitic siltstone 17 | 619 Sandy or silty shale 18 | 620 Clay or clay shale 19 | 621 Cherty shale 20 | 622 Dolomitic shale 21 | 623 Calcareous shale or marl 22 | 624 Carbonaceous shale 23 | 625 Oil shale 24 | 626 Chalk 25 | 627 Limestone 26 | 628 Clastic limestone 27 | 629 Fossiliferous clastic limestone 28 | 630 Nodular or irregularly bedded limestone 29 | 631 Limestone, irregular (burrow?) fillings of saccharoidal dolomite 30 | 632 Crossbedded limestone 31 | 633 Cherty crossbedded limestone 32 | 634 Cherty and sandy crossbedded clastic limestone 33 | 635 Oolitic limestone 34 | 636 Sandy limestone 35 | 637 Silty limestone 36 | 638 Argillaceous or shaly limestone 37 | 639 Cherty limestone (1st option) 38 | 640 Cherty limestone (2nd option) 39 | 641 Dolomitic limestone, limy dolostone, or limy dolomite 40 | 642 Dolostone or dolomite 41 | 643 Cross-bedded dolostone or dolomite 42 | 644 Oolitic dolostone or dolomite 43 | 645 Sandy dolostone or dolomite 44 | 646 Silty dolostone or dolomite 45 | 647 Argillaceous or shaly dolostone or dolomite 46 | 648 Cherty dolostone or dolomite 47 | 649 Bedded chert (1st option) 48 | 650 Bedded chert (2nd option) 49 | 651 Fossiliferous bedded chert 50 | 652 Fossiliferous rock 51 | 653 Diatomaceous rock 52 | 654 Subgraywacke 53 | 655 Cross-bedded subgraywacke 54 | 656 Ripple-bedded subgraywacke 55 | 657 Peat 56 | 658 Coal 57 | 659 Bony coal or impure coal 58 | 660 Underclay 59 | 661 Flint clay 60 | 662 Bentonite 61 | 663 Glauconite 62 | 664 Limonite 63 | 665 Siderite 64 | 666 Phosphatic-nodular rock 65 | 667 Gypsum 66 | 668 Salt 67 | 669 Interbedded sandstone and siltstone 68 | 670 Interbedded sandstone and shale 69 | 671 Interbedded ripple-bedded sandstone and shale 70 | 672 Interbedded shale and silty limestone (shale dominant) 71 | 673 Interbedded shale and limestone (shale dominant) (1st option) 72 | 674 Interbedded shale and limestone (shale dominant) (2nd option) 73 | 675 Interbedded calcareous shale and limestone (shale dominant) 74 | 676 Interbedded silty limestone and shale 75 | 677 Interbedded limestone and shale (1st option) 76 | 678 Interbedded limestone and shale (2nd option) 77 | 679 Interbedded limestone and shale (limestone dominant) 78 | 680 Interbedded limestone and calcareous shale 79 | 681 Till or diamicton (1st option) 80 | 682 Till or diamicton (2nd option) 81 | 683 Till or diamicton (3rd option) 82 | 684 Loess (1st option) 83 | 685 Loess (2nd option) 84 | 686 Loess (3rd option) 85 | 701 Metamorphism 86 | 702 Quartzite 87 | 703 Slate 88 | 704 Schistose or gneissoid granite 89 | 705 Schist 90 | 706 Contorted schist 91 | 707 Schist and gneiss 92 | 708 Gneiss 93 | 709 Contorted gneiss 94 | 710 Soapstone, talc, or serpentinite 95 | 711 Tuffaceous rock 96 | 712 Crystal tuff 97 | 713 Devitrified tuff 98 | 714 Volcanic breccia and tuff 99 | 715 Volcanic breccia or agglomerate 100 | 716 Zeolitic rock 101 | 717 Basaltic flows 102 | 718 Granite (1st option) 103 | 719 Granite (2nd option) 104 | 720 Banded igneous rock 105 | 721 Igneous rock (1st option) 106 | 722 Igneous rock (2nd option) 107 | 723 Igneous rock (3rd option) 108 | 724 Igneous rock (4th option) 109 | 725 Igneous rock (5th option) 110 | 726 Igneous rock (6th option) 111 | 727 Igneous rock (7th option) 112 | 728 Igneous rock (8th option) 113 | 729 Porphyritic rock (1st option) 114 | 730 Porphyritic rock (2nd option) 115 | 731 Vitrophyre 116 | 732 Quartz 117 | 733 Ore 118 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://williamgearty.com/deeptime/ 2 | template: 3 | bootstrap: 5 4 | bootswatch: flatly 5 | bslib: 6 | navbar-padding-y: 8px 7 | includes: 8 | in_header: | 9 | 10 | 11 | 18 | 19 | figures: 20 | dev: grDevices::png 21 | 22 | development: 23 | mode: auto 24 | 25 | authors: 26 | William Gearty: 27 | href: https://williamgearty.com 28 | 29 | articles: 30 | - title: Articles 31 | navbar: ~ 32 | contents: 33 | - coord_geo 34 | - phylogenies 35 | - coord 36 | - traits 37 | - time 38 | - geo 39 | - ggarrange2 40 | 41 | reference: 42 | - title: Adding geological timescales to plots 43 | desc: > 44 | The original purpose of deeptime, `coord_geo()` adds a highly 45 | customizable timescale to any `{ggplot2}` plot. Other functions now supplement 46 | it to aid in the visualization of data over long time scales. 47 | contents: 48 | - coord_geo 49 | - scale_color_geo 50 | - get_scale_data 51 | - guide_geo 52 | 53 | - subtitle: Built-in interval data 54 | desc: > 55 | deeptime includes a selection of built-in interval data from the 56 | most up-to-date Geological Time Scale. These dataframes include name, 57 | max age, min age, abbreviation, and color columns. 58 | contents: 59 | - eons 60 | - eras 61 | - periods 62 | - epochs 63 | - stages 64 | 65 | - subtitle: Deprecated functions 66 | desc: > 67 | The following function(s) represent early iterations of what is 68 | now `coord_geo()`. These function(s) still work but are considered 69 | "deprecated". They will be removed in a future version of deeptime, and 70 | users are strongly encouraged to use `coord_geo()` instead, which has more 71 | features and is still under active development. 72 | contents: 73 | - gggeo_scale 74 | 75 | - title: Adding geological timescales to phylogenies 76 | desc: > 77 | These functions can be used to add timescales specifically to phylogenies 78 | that are plotted with [ggtree](https://www.bioconductor.org/packages/ggtree). 79 | contents: 80 | - coord_geo 81 | - coord_geo_radial 82 | - coord_geo_polar 83 | - scale_color_geo 84 | - get_scale_data 85 | - guide_geo 86 | 87 | - subtitle: Adding text labels to phylogenies 88 | desc: > 89 | When using deeptime coordinate systems, these geoms may work better than geoms 90 | from ggtree. 91 | contents: 92 | - geom_text_phylo 93 | - geom_text_clade 94 | 95 | - title: Transforming coordinate systems 96 | desc: > 97 | These functions can be used to modify the way that your data is plotted 98 | by `{ggplot2}`. 99 | contents: 100 | - coord_trans_flip 101 | - coord_trans_xy 102 | 103 | - title: Plotting trait data 104 | desc: > 105 | These functions can be used for visualizing species trait data. 106 | contents: 107 | - geom_phylomorpho 108 | - disparity_through_time 109 | - panel.disparity 110 | - coord_trans_xy 111 | 112 | - title: Plotting temporal data 113 | desc: > 114 | These functions can be used for visualizing categorical temporal data. 115 | contents: 116 | - geom_points_range 117 | - stat_points_range 118 | - facet_grid_color 119 | - facet_wrap_color 120 | - facet_nested_color 121 | - facet_nested_wrap_color 122 | 123 | - title: Plotting geologic data 124 | desc: > 125 | These functions can be used for visualizing geologic/stratigraphic data. 126 | contents: 127 | - grid.pattern_geo 128 | - geo_pattern 129 | - scale_fill_geopattern 130 | - fgdc_names 131 | - fgdc_dict 132 | 133 | - title: Combining and arranging plots 134 | desc: > 135 | These functions can be used to combine and arrange plots into 136 | publishable-quality figures. 137 | contents: 138 | - ggarrange2 139 | - gtable_frame2 140 | -------------------------------------------------------------------------------- /man/coord_trans_xy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/coord_trans_xy.R 3 | \docType{data} 4 | \name{coord_trans_xy} 5 | \alias{coord_trans_xy} 6 | \alias{CoordTransXY} 7 | \title{Transformed XY Cartesian coordinate system} 8 | \usage{ 9 | coord_trans_xy( 10 | trans = NULL, 11 | xlim = NULL, 12 | ylim = NULL, 13 | expand = FALSE, 14 | default = FALSE, 15 | clip = "on" 16 | ) 17 | } 18 | \arguments{ 19 | \item{trans}{Transformer for x and y axes.} 20 | 21 | \item{xlim, ylim}{Limits for the x and y axes.} 22 | 23 | \item{expand}{If \code{TRUE}, the default, adds a small expansion factor to 24 | the limits to ensure that data and axes don't overlap. If \code{FALSE}, 25 | limits are taken exactly from the data or \code{xlim}/\code{ylim}. 26 | Giving a logical vector will separately control the expansion for the four 27 | directions (top, left, bottom and right). The \code{expand} argument will be 28 | recycled to length 4 if necessary. Alternatively, can be a named logical 29 | vector to control a single direction, e.g. \code{expand = c(bottom = FALSE)}.} 30 | 31 | \item{default}{Is this the default coordinate system? If \code{FALSE} (the default), 32 | then replacing this coordinate system with another one creates a message alerting 33 | the user that the coordinate system is being replaced. If \code{TRUE}, that warning 34 | is suppressed.} 35 | 36 | \item{clip}{Should drawing be clipped to the extent of the plot panel? A 37 | setting of \code{"on"} (the default) means yes, and a setting of \code{"off"} 38 | means no. In most cases, the default of \code{"on"} should not be changed, 39 | as setting \code{clip = "off"} can cause unexpected results. It allows 40 | drawing of data points anywhere on the plot, including in the plot margins. If 41 | limits are set via \code{xlim} and \code{ylim} and some data points fall outside those 42 | limits, then those data points may show up in places such as the axes, the 43 | legend, the plot title, or the plot margins.} 44 | } 45 | \description{ 46 | \code{coord_trans_xy} behaves similarly to \code{\link[ggplot2:coord_transform]{ggplot2::coord_trans()}} in that it 47 | occurs after statistical transformation and will affect the visual appearance 48 | of geoms. The main difference is that it takes a single transformer that is 49 | applied to the x and y axes simultaneously. Any transformers produced by 50 | \code{\link[ggforce:linear_trans]{ggforce::linear_trans()}} that have x and y arguments should work, but any 51 | other transformers produced using \code{\link[scales:new_transform]{scales::trans_new()}} that take x and y 52 | arguments should also work. Axis limits will be adjusted to account for 53 | transformation unless limits are specified with \code{xlim} or \code{ylim}. 54 | } 55 | \details{ 56 | This coordinate system only works with geoms where all points are 57 | defined with x and y coordinates (e.g., \code{\link[ggplot2:geom_point]{ggplot2::geom_point()}}, 58 | \code{\link[ggplot2:geom_polygon]{ggplot2::geom_polygon()}}). This does not currently work with geoms where 59 | point coordinates are extrapolated (e.g., \code{\link[ggplot2:geom_tile]{ggplot2::geom_rect()}}). 60 | Furthermore, when used with ggplot2 3.5.0 and later, some transformation 61 | edge cases may cause problems with rendering axis lines. This includes not 62 | currently support "capping" axes. I hope to support all of these geoms, 63 | edge cases, and features in the future. 64 | } 65 | \examples{ 66 | # make transformer 67 | library(ggforce) 68 | trans <- linear_trans(shear(2, 0), rotate(-pi / 3)) 69 | 70 | # set up data to be plotted 71 | square <- data.frame(x = c(0, 0, 4, 4), y = c(0, 1, 1, 0)) 72 | points <- data.frame(x = runif(100, 0, 4), y = runif(100, 0, 1)) 73 | 74 | # plot data normally 75 | library(ggplot2) 76 | ggplot(data = points, aes(x = x, y = y)) + 77 | geom_polygon(data = square, fill = NA, color = "black") + 78 | geom_point(color = "black") + 79 | coord_cartesian(expand = FALSE) + 80 | theme_classic() 81 | 82 | # plot data with transformation 83 | ggplot(data = points, aes(x = x, y = y)) + 84 | geom_polygon(data = square, fill = NA, color = "black") + 85 | geom_point(color = "black") + 86 | coord_trans_xy(trans = trans, expand = FALSE) + 87 | theme_classic() 88 | } 89 | \keyword{datasets} 90 | -------------------------------------------------------------------------------- /vignettes/ggarrange2.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Combining and arranging plots" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Combining and arranging plots} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set(collapse = TRUE, fig.width = 7, fig.height = 5, fig.align = "center") 12 | ``` 13 | 14 | ```{r setup, message = FALSE} 15 | library(deeptime) 16 | # Load ggplot2 17 | library(ggplot2) 18 | # Load ggtree 19 | library(ggtree) 20 | # Load paleotree for some example data 21 | library(paleotree) 22 | data(RaiaCopesRule) 23 | ``` 24 | 25 |
26 | ## The history of arranging and combining plots 27 | Combining multiple plots together into figures is a key component of developing publishable data visualizations. Many other packages provide ways to combine and arrange plots. For example, the `gridExtra` package has the [`grid.arrange()` function](https://cran.r-project.org/package=gridExtra/vignettes/arrangeGrob.html) which allows the user to arrange plots in fairly complex layouts. However, the main drawback (for most cases) of this function is that the components of the plots (axes, labels, panels, etc.) are not aligned. The [`ggarrange()` function](https://cran.r-project.org/package=egg/vignettes/Overview.html#arranging-and-aligning-multiple-plots) in the `egg` package uses a 3x3 decomposition of the individual plots to align some of the plot components. The central cells correspond to the core panels, surrounded by axes, legends, etc. 28 | 29 | ## Arranging plots with deeptime 30 | __deeptime__ expands on this functionality with `ggarrange2()` to perform 7x7 decomposition of individual plots, as shown below. This ensures that more components of the individual plots are aligned with one another (e.g., the axis labels, the axis tick labels). The central cell corresponds to the plot panel(s), the rectangle of cells around that corresponds to the axes, the rectangle of cells around that corresponds to the axis titles, and the rectangle of cells around that corresponds to legends. 31 | ```{r} 32 | p1 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) + 33 | geom_point() + 34 | theme_classic(base_size = 20) 35 | ggarrange2(p1, debug = TRUE) 36 | ``` 37 | 38 | ## Combining plots 39 | With this 7x7 decomposition process, it becomes very simple to combine plots into single figures with properly aligned components. 40 | ```{r} 41 | p1 <- ggplot(ammoniteTraitsRaia) + 42 | geom_point(aes(x = Log_D, y = FD)) + 43 | labs(x = "Body size", y = "Suture complexity") + 44 | theme_classic() 45 | 46 | p2 <- ggplot(ammoniteTraitsRaia) + 47 | geom_point(aes(x = Log_D, y = log_dur)) + 48 | labs(x = "Body size", y = "Stratigraphic duration (myr)") + 49 | theme_classic() 50 | gg1 <- ggarrange2(p1, p2, widths = c(2, 1), draw = FALSE) 51 | ``` 52 | 53 | You can chain calls to `ggarrange2()` to accomplish highly complex combinations and arrangements: 54 | ```{r} 55 | p3 <- ggtree(ammoniteTreeRaia, position = position_nudge(x = -ammoniteTreeRaia$root.time)) + 56 | coord_geo( 57 | xlim = c(-415, -66), ylim = c(-2, Ntip(ammoniteTreeRaia)), pos = "bottom", 58 | size = 4, abbrv = FALSE, neg = TRUE 59 | ) + 60 | scale_x_continuous(breaks = seq(-425, -50, 25), labels = -seq(-425, -50, 25)) + 61 | theme_tree2() + 62 | theme(plot.margin = margin(7, 11, 7, 11)) 63 | ggarrange2(gg1, p3, nrow = 2, heights = c(1, 2)) 64 | ``` 65 | 66 | You can also accomplish complex plot layouts by supplying a matrix of integers to the `layout` argument, like with the base R `layout()` function. This can be used to insert empty plots or change the order of plots. Note that repeating a number will duplicate a plot, not expand it across multiple plot spots. 67 | ```{r} 68 | ggarrange2(p1, p2, p3, 69 | layout = matrix(c(1, 2, 0, 3), nrow = 2, byrow = TRUE), 70 | widths = c(1, 3) 71 | ) 72 | ``` 73 | 74 | ## Other resources for arranging plots 75 | Note that I provide no guarantee that `ggarrange2()` solves every problem when arranging plots. The following other options may also be very useful: 76 | 77 | - The `{cowplot}` package has the `cowplot::plot_grid()` function which accomplishes many of the same features as `ggarrange2()`. 78 | - The `{patchwork}` package has very intuitive tools for combining and arranging plots (e.g., using mathematical symbols). 79 |
80 | -------------------------------------------------------------------------------- /tests/testthat/test-patterns.R: -------------------------------------------------------------------------------- 1 | test_that("scale_fill_geopattern works", { 2 | # invalid code 3 | vals <- c("101", "313", "603", "999") 4 | gg <- ggplot(mpg, aes(factor(cyl), fill = vals[factor(cyl)])) + 5 | geom_bar() + 6 | scale_fill_geopattern() 7 | expect_error(print(gg)) 8 | 9 | skip_if(R.Version()$os != "mingw32") # only test the rest on Windows 10 | vals <- c("101", "313", "603", "733") 11 | gg <- ggplot(mpg, aes(factor(cyl), fill = vals[factor(cyl)])) + 12 | geom_bar() + 13 | scale_fill_geopattern() 14 | expect_doppelganger_deeptime("scale_fill_geopattern", gg, patterns = TRUE) 15 | 16 | # custom labels 17 | gg <- ggplot(mpg, aes(factor(cyl), fill = vals[factor(cyl)])) + 18 | geom_bar() + 19 | scale_fill_geopattern(labels = c("101" = "test")) 20 | expect_doppelganger_deeptime("scale_fill_geopattern_labels", gg, patterns = TRUE) 21 | 22 | # custom limits 23 | gg <- ggplot(mpg, aes(factor(cyl), fill = vals[factor(cyl)])) + 24 | geom_bar() + 25 | scale_fill_geopattern(limits = c("101", "313")) 26 | expect_doppelganger_deeptime("scale_fill_geopattern_limits", gg, patterns = TRUE) 27 | 28 | # test with NA values 29 | vals <- c("101", "313", "603", NA) 30 | gg <- ggplot(mpg, aes(factor(cyl), fill = vals[factor(cyl)])) + 31 | geom_bar() + 32 | scale_fill_geopattern() 33 | expect_doppelganger_deeptime("scale_fill_geopattern_NA", gg, patterns = TRUE) 34 | 35 | # test with custom NA value 36 | gg <- ggplot(mpg, aes(factor(cyl), fill = vals[factor(cyl)])) + 37 | geom_bar() + 38 | scale_fill_geopattern(na.value = geo_pattern("701")) 39 | expect_doppelganger_deeptime("scale_fill_geopattern_NA2", gg, patterns = TRUE) 40 | }) 41 | 42 | test_that("geo_grob works", { 43 | grob <- geo_grob("101") 44 | expect_true(grid::is.grob(grob)) 45 | 46 | expect_error(geo_grob(999)) 47 | expect_error(geo_grob("test")) 48 | 49 | expect_doppelganger_deeptime("geo_grob", { 50 | grid.newpage() 51 | grid.draw(grob) 52 | }) 53 | }) 54 | 55 | test_that("geo_pattern works", { 56 | patt <- geo_pattern("101") 57 | expect_true(is(patt, "GridPattern")) 58 | 59 | expect_error(geo_pattern(999)) 60 | expect_error(geo_pattern("test")) 61 | 62 | pattern1 <- geo_pattern(code = "313-K") 63 | pattern2 <- geo_pattern(code = "607") 64 | 65 | expect_doppelganger_deeptime("geo_pattern1", { 66 | grid.newpage() 67 | grid.draw(rectGrob(gp = gpar(fill = pattern1))) 68 | }, patterns = TRUE) 69 | 70 | expect_doppelganger_deeptime("geo_pattern2", { 71 | grid.newpage() 72 | grid.draw(rectGrob(gp = gpar(fill = pattern2))) 73 | }, patterns = TRUE) 74 | }) 75 | 76 | test_that("grid.pattern_geo works", { 77 | x <- 0.5 + 0.5 * cos(seq(2 * pi / 4, by = 2 * pi / 6, length.out = 6)) 78 | y <- 0.5 + 0.5 * sin(seq(2 * pi / 4, by = 2 * pi / 6, length.out = 6)) 79 | 80 | expect_doppelganger_deeptime("grid.pattern_geo", { 81 | grid.newpage() 82 | grid.pattern_geo(params = list(pattern_type = "633", pattern_scale = 4), 83 | boundary_df = data.frame(x, y, id = 1)) 84 | }, patterns = TRUE) 85 | }) 86 | 87 | test_that("ggpattern works", { 88 | skip_if_not_installed("ggpattern") 89 | df <- data.frame(trt = c("a", "b", "c"), outcome = c(2.3, 1.9, 3.2)) 90 | gg <- ggplot(df, aes(trt, outcome)) + 91 | geom_col_pattern(aes(color = trt, pattern_type = trt), pattern = 'geo', 92 | pattern_color = "black", fill = "white", 93 | pattern_fill = "white") + 94 | scale_pattern_type_manual(values = c("101", "313", "999")) + 95 | scale_color_viridis_d() + 96 | theme(legend.key.size = unit(1.5, 'cm')) 97 | expect_error(print(gg)) 98 | 99 | skip_if(R.Version()$os != "mingw32") # only test the rest on Windows 100 | gg <- ggplot(df, aes(trt, outcome)) + 101 | geom_col_pattern(aes(color = trt, pattern_type = trt), pattern = 'geo', 102 | pattern_color = "black", fill = "white", 103 | pattern_fill = "white") + 104 | scale_pattern_type_manual(values = c("101", "313", "634")) + 105 | scale_color_viridis_d() + 106 | theme(legend.key.size = unit(1.5, 'cm')) 107 | expect_doppelganger_deeptime("ggpattern", gg, patterns = TRUE) 108 | }) 109 | 110 | test_that("fgdc_dict works", { 111 | dict <- fgdc_dict() 112 | expect_true(is.function(dict)) 113 | vals <- c("603", "626", "720", "733") 114 | expect_equal(dict(vals), c("Crossbedded gravel or conglomerate", "Chalk", 115 | "Banded igneous rock", "Ore")) 116 | dict <- fgdc_dict(clean = FALSE, wrap = 10) 117 | expect_equal(dict("601"), "Gravel or\nconglomerate\n(1st\noption)") 118 | }) 119 | -------------------------------------------------------------------------------- /man/grid.pattern_geo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.R 3 | \name{grid.pattern_geo} 4 | \alias{grid.pattern_geo} 5 | \title{Plot an individual FGDC pattern using grid} 6 | \usage{ 7 | grid.pattern_geo(params, boundary_df, aspect_ratio, legend = FALSE) 8 | } 9 | \arguments{ 10 | \item{params}{A list of pattern parameters to customize the plotted pattern 11 | (see "Details").} 12 | 13 | \item{boundary_df}{A \code{data.frame} consisting of three columns: "x" 14 | (x-coordinates), "y" (y-coordinates), and "id" (polygon group ID). This 15 | \code{data.frame} defines the boundary (as a closed polygon) of the plotted 16 | pattern.} 17 | 18 | \item{aspect_ratio}{Unused.} 19 | 20 | \item{legend}{Unused.} 21 | } 22 | \description{ 23 | This function can be used to plot a single geologic pattern as defined in the 24 | \href{https://ngmdb.usgs.gov/fgdc_gds/geolsymstd.php}{FGDC Digital Cartographic Standard for Geologic Map Symbolization} by the \href{https://www.usgs.gov/}{U.S. Geological Survey} and the \href{https://ngmdb.usgs.gov/fgdc_gds/index.php}{Geologic Data Subcommittee (GDS)} of the \href{https://www.fgdc.gov/}{Federal Geographic Data Committee (FGDC)}. The pattern is plotted on the 25 | existing canvas (i.e., use \code{\link[grid:grid.newpage]{grid::grid.newpage()}} to make a new canvas). 26 | } 27 | \details{ 28 | The following \code{params} are accepted: 29 | \describe{ 30 | \item{\strong{\code{pattern_alpha}}}{ Alpha transparency for pattern. default: 1} 31 | \item{\strong{\code{pattern_colour}}}{ Color used for strokes and points in 32 | the pattern. default: 'black'} 33 | \item{\strong{\code{pattern_fill}}}{ Color used to fill various closed shapes 34 | (e.g., circles) in the pattern. default: \code{NA}} 35 | \item{\strong{\code{pattern_scale}}}{ Scale. default: 2} 36 | \item{\strong{\code{pattern_type}}}{ Code for the FGDC pattern to use. See 37 | \code{\link[=geo_pattern]{geo_pattern()}} for more details. default: "101" } 38 | \item{\strong{\code{fill}}}{ Color used for the background. default: "white" } 39 | } 40 | } 41 | \section{Warning}{ 42 | Pattern fills are not supported on all graphics devices. 43 | Not all devices are under active development, and such devices are unlikely 44 | to add support for new features (such as pattern fills). The new features 45 | have only been implemented on a subset of graphics devices so far: 46 | \code{\link[=cairo_pdf]{cairo_pdf()}}, \code{\link[=cairo_ps]{cairo_ps()}}, \code{\link[=x11]{x11(type="cairo")}}, 47 | \code{\link[=png]{png(type="cairo")}}, 48 | \code{\link[=jpeg]{jpeg(type="cairo")}}, 49 | \code{\link[=tiff]{tiff(type="cairo")}}, \code{\link[=svg]{svg()}}, and \code{\link[=pdf]{pdf()}}. Although 50 | there is no support yet for \code{\link[=quartz]{quartz()}} or \code{\link[=windows]{windows()}}, almost all of the 51 | graphics devices above will work on all major platforms. Further, the 52 | \href{https://ragg.r-lib.org/}{ragg} and 53 | \href{https://svglite.r-lib.org/index.html}{svglite} packages contain graphics 54 | devices that support patterns. When using a graphics device where patterns 55 | are not supported, closed shapes will be rendered with a transparent fill. 56 | Note that, at least on Windows machines, the default device in RStudio and 57 | in the knitr package is \code{\link[=png]{png()}}, which does not support patterns. In 58 | RStudio, you can go to ‘Tools > Global Options > General > Graphics’ and 59 | choose the ‘Cairo PNG’ device from the dropdown menu to display patterns. 60 | Similar issues may arise when using RStudio on other operating systems. 61 | } 62 | 63 | \examples{ 64 | # use the function directly to make a hexagon with the pattern 65 | library(grid) 66 | x <- 0.5 + 0.5 * cos(seq(2 * pi / 4, by = 2 * pi / 6, length.out = 6)) 67 | y <- 0.5 + 0.5 * sin(seq(2 * pi / 4, by = 2 * pi / 6, length.out = 6)) 68 | grid.newpage() 69 | grid.pattern_geo(params = list(pattern_type = "633", pattern_scale = 4), 70 | boundary_df = data.frame(x, y, id = 1)) 71 | \dontshow{if (require(ggpattern)) withAutoprint(\{ # examplesIf} 72 | # use the function via ggpattern by specifying `pattern = 'geo'` 73 | library(ggplot2) 74 | library(ggpattern) 75 | df <- data.frame(trt = c("a", "b", "c"), outcome = c(2.3, 1.9, 3.2)) 76 | ggplot(df, aes(trt, outcome)) + 77 | geom_col_pattern(aes(color = trt, pattern_type = trt), pattern = 'geo', 78 | pattern_color = "black", fill = "white", pattern_fill = "white") + 79 | scale_pattern_type_manual(values = c("101", "313", "634")) + 80 | scale_color_viridis_d() + 81 | theme(legend.key.size = unit(1.5, 'cm')) 82 | \dontshow{\}) # examplesIf} 83 | } 84 | \seealso{ 85 | FGDC patterns: 86 | \code{\link{fgdc_dict}()}, 87 | \code{\link{fgdc_names}}, 88 | \code{\link{geo_pattern}()}, 89 | \code{\link{scale_fill_geopattern}()} 90 | } 91 | \concept{patterns} 92 | -------------------------------------------------------------------------------- /vignettes/traits.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Plotting trait data" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Plotting trait data} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set(collapse = TRUE, fig.width = 7, fig.height = 5, fig.align = "center") 12 | ``` 13 | 14 |
15 | Many packages exist to visualize trait data for biological species. __deeptime__ similarly has a few novel ways to help you plot your data in useful ways. We'll first load some packages and example data so we can demonstrate some of this functionality. 16 | 17 | ```{r message = FALSE} 18 | # Load deeptime 19 | library(deeptime) 20 | # Load other packages 21 | library(ggplot2) 22 | library(dplyr) 23 | # Load dispRity for example data 24 | library(dispRity) 25 | data(demo_data) 26 | # Load paleotree for example data 27 | library(phytools) 28 | data(mammal.tree) 29 | data(mammal.data) 30 | ``` 31 | 32 | ## Plot disparity through time 33 | A common way to visualize trait data, especially for fossil species, is to show the two-dimensional trait distribution for several time intervals. This allows the viewer to easily compare the trait distribution through time. However, producing such a plot has historically been very time intensive, often involving the use of custom code and image editing software (e.g., [Inkscape](https://inkscape.org/)). While a single function to accomplish such a visualization still does not exist for `{ggplot2}` (yet...), the `coord_trans_xy()` function can be used to generate a similar plot with sheared trait space across several time intervals. 34 | 35 | ```{r} 36 | # make transformer 37 | library(ggforce) 38 | trans <- linear_trans(shear(.75, 0)) 39 | 40 | # prepare data to be plotted 41 | crinoids <- as.data.frame(demo_data$wright$matrix[[1]][, 1:2]) 42 | crinoids$time <- "before extinction" 43 | crinoids$time[demo_data$wright$subsets$after$elements] <- "after extinction" 44 | 45 | # a box to outline the trait space 46 | square <- data.frame(V1 = c(-.6, -.6, .6, .6), V2 = c(-.4, .4, .4, -.4)) 47 | 48 | ggplot() + 49 | geom_segment( 50 | data = data.frame( 51 | x = -.6, y = seq(-.4, .4, .2), 52 | xend = .6, yend = seq(-0.4, .4, .2) 53 | ), 54 | aes(x = x, y = y, xend = xend, yend = yend), 55 | linetype = "dashed", color = "grey" 56 | ) + 57 | geom_segment( 58 | data = data.frame( 59 | x = seq(-.6, .6, .2), y = -.4, 60 | xend = seq(-.6, .6, .2), yend = .4 61 | ), 62 | aes(x = x, y = y, xend = xend, yend = yend), 63 | linetype = "dashed", color = "grey" 64 | ) + 65 | geom_polygon(data = square, aes(x = V1, y = V2), fill = NA, color = "black") + 66 | geom_point(data = crinoids, aes(x = V1, y = V2), color = "black") + 67 | coord_trans_xy(trans = trans, expand = FALSE) + 68 | labs(x = "PCO1", y = "PCO2") + 69 | theme_classic() + 70 | facet_wrap(~time, ncol = 1, strip.position = "right") + 71 | theme(panel.spacing = unit(1, "lines"), panel.background = element_blank()) 72 | ``` 73 | 74 | ### Disparity in base R 75 | The `disparity_through_time()` function accomplishes nearly all of the work for you if you are comfortable plotting within the `{lattice}` framework (base R). Note that it may take some tweaking (especially the `aspect` argument) to get the results to look the way you want. 76 | 77 | ```{r, fig.height = 4} 78 | crinoids$time <- factor(crinoids$time) 79 | disparity_through_time(time ~ V2 * V1, 80 | data = crinoids, groups = time, aspect = c(1.5, .6), 81 | xlim = c(-.6, .6), ylim = c(-.5, .5), 82 | col.regions = "lightyellow", col.point = c("red", "blue"), 83 | par.settings = list( 84 | axis.line = list(col = "transparent"), 85 | layout.heights = 86 | list( 87 | top.padding = -20, main.key.padding = 0, 88 | key.axis.padding = 0, axis.xlab.padding = 0, 89 | xlab.key.padding = 0, key.sub.padding = 0, 90 | bottom.padding = -20 91 | ), 92 | layout.widths = 93 | list( 94 | left.padding = -10, key.ylab.padding = 0, 95 | ylab.axis.padding = 0, axis.key.padding = 0, 96 | right.padding = 0 97 | ) 98 | ) 99 | ) 100 | ``` 101 | 102 | ## Phylomorphospaces 103 | Often, trait data will be accompanied with a phylogeny. You may want to visualize both your phylogeny, the traits of your species, and the evolution of the trait along your phylogeny. To accomplish this, you can create a two-dimensional phylomorphospace. The `{phytools}` package has the `phytools::phylomorphospace()` function for accomplishing this in base R. The `geom_phylomorpho()` function in __deeptime__ will help you accomplish this with `ggplot()`. Note that labels can be added using `geom_label()` or `ggrepel::geom_label_repel()`, but they are not demonstrated here because they would obscure the phylogenetic relationships. 104 | ```{r message = FALSE, warning = FALSE} 105 | mammal.data$label <- rownames(mammal.data) 106 | 107 | ggplot(mammal.data, aes(x = bodyMass, y = homeRange, label = label)) + 108 | geom_phylomorpho(mammal.tree) + 109 | theme_classic() 110 | ``` 111 | 112 |
113 | -------------------------------------------------------------------------------- /man/scale_geo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/scales.R 3 | \name{scale_color_geo} 4 | \alias{scale_color_geo} 5 | \alias{scale_colour_geo} 6 | \alias{scale_fill_geo} 7 | \alias{scale_discrete_geo} 8 | \title{Geological Time Scale color scales} 9 | \usage{ 10 | scale_color_geo(dat, ...) 11 | 12 | scale_fill_geo(dat, ...) 13 | 14 | scale_discrete_geo(dat, aesthetics, ...) 15 | } 16 | \arguments{ 17 | \item{dat}{Either A) a string indicating a built-in dataframe with interval 18 | data from the ICS ("periods", "epochs", "stages", "eons", or "eras"), 19 | B) a string indicating a timescale from macrostrat (see list here: 20 | \url{https://macrostrat.org/api/defs/timescales?all}), 21 | or C) a custom data.frame of time interval boundaries 22 | (see \code{\link[=coord_geo]{coord_geo()}}).} 23 | 24 | \item{...}{ 25 | Arguments passed on to \code{\link[ggplot2:discrete_scale]{ggplot2::discrete_scale}} 26 | \describe{ 27 | \item{\code{scale_name}}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} The name of the scale 28 | that should be used for error messages associated with this scale.} 29 | \item{\code{name}}{The name of the scale. Used as the axis or legend title. If 30 | \code{waiver()}, the default, the name of the scale is taken from the first 31 | mapping used for that aesthetic. If \code{NULL}, the legend title will be 32 | omitted.} 33 | \item{\code{minor_breaks}}{One of: 34 | \itemize{ 35 | \item \code{NULL} for no minor breaks 36 | \item \code{waiver()} for the default breaks (none for discrete, one minor break 37 | between each major break for continuous) 38 | \item A numeric vector of positions 39 | \item A function that given the limits returns a vector of minor breaks. Also 40 | accepts rlang \link[rlang:as_function]{lambda} function notation. When 41 | the function has two arguments, it will be given the limits and major 42 | break positions. 43 | }} 44 | \item{\code{labels}}{One of the options below. Please note that when \code{labels} is a 45 | vector, it is highly recommended to also set the \code{breaks} argument as a 46 | vector to protect against unintended mismatches. 47 | \itemize{ 48 | \item \code{NULL} for no labels 49 | \item \code{waiver()} for the default labels computed by the 50 | transformation object 51 | \item A character vector giving labels (must be same length as \code{breaks}) 52 | \item An expression vector (must be the same length as breaks). See ?plotmath for details. 53 | \item A function that takes the breaks as input and returns labels 54 | as output. Also accepts rlang \link[rlang:as_function]{lambda} function 55 | notation. 56 | }} 57 | \item{\code{limits}}{One of: 58 | \itemize{ 59 | \item \code{NULL} to use the default scale values 60 | \item A character vector that defines possible values of the scale and their 61 | order 62 | \item A function that accepts the existing (automatic) values and returns 63 | new ones. Also accepts rlang \link[rlang:as_function]{lambda} function 64 | notation. 65 | }} 66 | \item{\code{na.translate}}{Unlike continuous scales, discrete scales can easily show 67 | missing values, and do so by default. If you want to remove missing values 68 | from a discrete scale, specify \code{na.translate = FALSE}.} 69 | \item{\code{na.value}}{If \code{na.translate = TRUE}, what aesthetic value should the 70 | missing values be displayed as? Does not apply to position scales 71 | where \code{NA} is always placed at the far right.} 72 | \item{\code{drop}}{Should unused factor levels be omitted from the scale? 73 | The default, \code{TRUE}, uses the levels that appear in the data; 74 | \code{FALSE} includes the levels in the factor. Please note that to display 75 | every level in a legend, the layer should use \code{show.legend = TRUE}.} 76 | \item{\code{guide}}{A function used to create a guide or its name. See 77 | \code{\link[ggplot2:guides]{guides()}} for more information.} 78 | \item{\code{call}}{The \code{call} used to construct the scale for reporting messages.} 79 | \item{\code{super}}{The super class to use for the constructed scale} 80 | }} 81 | 82 | \item{aesthetics}{Character string or vector of character strings listing the 83 | name(s) of the aesthetic(s) that this scale works with. This can be useful, for 84 | example, to apply colour settings to the \code{colour} and \code{fill} aesthetics at the 85 | same time, via \code{aesthetics = c("colour", "fill")}.} 86 | } 87 | \description{ 88 | Color scales using the colors in the Geological Time Scale graphics. 89 | } 90 | \examples{ 91 | library(ggplot2) 92 | df <- data.frame( 93 | x = runif(1000, 0, 10), y = runif(1000, 0, 10), 94 | color = sample(periods$name, 1000, TRUE), shape = 21 95 | ) 96 | ggplot(df) + 97 | geom_point(aes(x = x, y = y, fill = color), shape = 21) + 98 | scale_fill_geo("periods", name = "Period") + 99 | theme_classic() 100 | 101 | # cut continuous variable into discrete 102 | df <- data.frame(x = runif(1000, 0, 1000), y = runif(1000, 0, 8)) 103 | df$color <- cut(df$x, c(periods$min_age, periods$max_age[22]), periods$name) 104 | ggplot(df) + 105 | geom_point(aes(x = x, y = y, color = color)) + 106 | scale_x_reverse() + 107 | scale_color_geo("periods", name = "Period") + 108 | coord_geo(xlim = c(1000, 0), ylim = c(0, 8)) + 109 | theme_classic() 110 | } 111 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(print,ggarrange2) 4 | export(CoordGeo) 5 | export(CoordGeoPolar) 6 | export(CoordGeoRadial) 7 | export(CoordTransFlip) 8 | export(CoordTransXY) 9 | export(FacetGridColor) 10 | export(FacetNestedColor) 11 | export(FacetNestedWrapColor) 12 | export(FacetWrapColor) 13 | export(GuideGeo) 14 | export(coord_geo) 15 | export(coord_geo_polar) 16 | export(coord_geo_radial) 17 | export(coord_trans_flip) 18 | export(coord_trans_xy) 19 | export(disparity_through_time) 20 | export(facet_grid_color) 21 | export(facet_grid_geo) 22 | export(facet_nested_color) 23 | export(facet_nested_geo) 24 | export(facet_nested_wrap_color) 25 | export(facet_nested_wrap_geo) 26 | export(facet_wrap_color) 27 | export(facet_wrap_geo) 28 | export(fgdc_dict) 29 | export(geo_grob) 30 | export(geo_pattern) 31 | export(geom_phylomorpho) 32 | export(geom_points_range) 33 | export(geom_text_clade) 34 | export(geom_text_phylo) 35 | export(get_scale_data) 36 | export(ggarrange2) 37 | export(gggeo_scale) 38 | export(gggeo_scale_old) 39 | export(grid.pattern_geo) 40 | export(gtable_frame2) 41 | export(guide_geo) 42 | export(panel.disparity) 43 | export(scale_color_geo) 44 | export(scale_colour_geo) 45 | export(scale_discrete_geo) 46 | export(scale_fill_geo) 47 | export(scale_fill_geopattern) 48 | export(stat_points_range) 49 | import(deeptimedata) 50 | import(grImport2) 51 | import(rlang) 52 | import(scales) 53 | importFrom(curl,nslookup) 54 | importFrom(ggfittext,geom_fit_text) 55 | importFrom(ggforce,linear_trans) 56 | importFrom(ggh4x,FacetNested) 57 | importFrom(ggh4x,FacetNestedWrap) 58 | importFrom(ggh4x,strip_nested) 59 | importFrom(ggplot2,CoordCartesian) 60 | importFrom(ggplot2,CoordFlip) 61 | importFrom(ggplot2,CoordPolar) 62 | importFrom(ggplot2,CoordRadial) 63 | importFrom(ggplot2,CoordTrans) 64 | importFrom(ggplot2,FacetGrid) 65 | importFrom(ggplot2,FacetWrap) 66 | importFrom(ggplot2,Geom) 67 | importFrom(ggplot2,GeomLabel) 68 | importFrom(ggplot2,GeomLinerange) 69 | importFrom(ggplot2,GeomPoint) 70 | importFrom(ggplot2,GeomPointrange) 71 | importFrom(ggplot2,GeomText) 72 | importFrom(ggplot2,GuideAxis) 73 | importFrom(ggplot2,ScaleDiscrete) 74 | importFrom(ggplot2,Stat) 75 | importFrom(ggplot2,aes) 76 | importFrom(ggplot2,annotate) 77 | importFrom(ggplot2,calc_element) 78 | importFrom(ggplot2,coord_polar) 79 | importFrom(ggplot2,coord_radial) 80 | importFrom(ggplot2,discrete_scale) 81 | importFrom(ggplot2,draw_key_pointrange) 82 | importFrom(ggplot2,element_blank) 83 | importFrom(ggplot2,element_line) 84 | importFrom(ggplot2,geom_rect) 85 | importFrom(ggplot2,geom_segment) 86 | importFrom(ggplot2,geom_text) 87 | importFrom(ggplot2,geom_vline) 88 | importFrom(ggplot2,ggplot) 89 | importFrom(ggplot2,ggplotGrob) 90 | importFrom(ggplot2,ggproto) 91 | importFrom(ggplot2,ggproto_parent) 92 | importFrom(ggplot2,has_flipped_aes) 93 | importFrom(ggplot2,last_plot) 94 | importFrom(ggplot2,layer) 95 | importFrom(ggplot2,new_guide) 96 | importFrom(ggplot2,position_nudge) 97 | importFrom(ggplot2,remove_missing) 98 | importFrom(ggplot2,scale_color_identity) 99 | importFrom(ggplot2,scale_fill_identity) 100 | importFrom(ggplot2,scale_fill_manual) 101 | importFrom(ggplot2,scale_x_continuous) 102 | importFrom(ggplot2,scale_x_reverse) 103 | importFrom(ggplot2,scale_y_continuous) 104 | importFrom(ggplot2,set_last_plot) 105 | importFrom(ggplot2,standardise_aes_names) 106 | importFrom(ggplot2,theme) 107 | importFrom(ggplot2,theme_void) 108 | importFrom(ggplot2,transform_position) 109 | importFrom(ggplot2,waiver) 110 | importFrom(ggplot2,xlim) 111 | importFrom(ggplot2,zeroGrob) 112 | importFrom(grDevices,col2rgb) 113 | importFrom(grDevices,dev.interactive) 114 | importFrom(grDevices,dev.new) 115 | importFrom(grDevices,n2mfrow) 116 | importFrom(grid,addGrob) 117 | importFrom(grid,editGrob) 118 | importFrom(grid,gList) 119 | importFrom(grid,gPath) 120 | importFrom(grid,gTree) 121 | importFrom(grid,gpar) 122 | importFrom(grid,grid.draw) 123 | importFrom(grid,grid.ls) 124 | importFrom(grid,grid.newpage) 125 | importFrom(grid,grid.polygon) 126 | importFrom(grid,grobHeight) 127 | importFrom(grid,grobName) 128 | importFrom(grid,grobWidth) 129 | importFrom(grid,is.grob) 130 | importFrom(grid,is.unit) 131 | importFrom(grid,nullGrob) 132 | importFrom(grid,pattern) 133 | importFrom(grid,rectGrob) 134 | importFrom(grid,reorderGrob) 135 | importFrom(grid,textGrob) 136 | importFrom(grid,unit) 137 | importFrom(grid,unit.c) 138 | importFrom(grid,viewport) 139 | importFrom(gridExtra,gtable_cbind) 140 | importFrom(gridExtra,gtable_rbind) 141 | importFrom(gtable,gtable) 142 | importFrom(gtable,gtable_add_cols) 143 | importFrom(gtable,gtable_add_grob) 144 | importFrom(gtable,gtable_add_padding) 145 | importFrom(gtable,gtable_add_rows) 146 | importFrom(gtable,gtable_col) 147 | importFrom(gtable,gtable_filter) 148 | importFrom(gtable,gtable_height) 149 | importFrom(gtable,gtable_matrix) 150 | importFrom(gtable,gtable_row) 151 | importFrom(gtable,gtable_width) 152 | importFrom(lattice,panel.cloud) 153 | importFrom(lattice,panel.wireframe) 154 | importFrom(lattice,wireframe) 155 | importFrom(lifecycle,deprecated) 156 | importFrom(methods,is) 157 | importFrom(rlang,"%||%") 158 | importFrom(rlang,":=") 159 | importFrom(rlang,arg_match0) 160 | importFrom(rlang,exec) 161 | importFrom(rlang,is_function) 162 | importFrom(scales,label_dictionary) 163 | importFrom(scales,rescale) 164 | importFrom(scales,squish_infinite) 165 | importFrom(scales,transform_identity) 166 | importFrom(stats,setNames) 167 | importFrom(utils,modifyList) 168 | importFrom(utils,packageVersion) 169 | importFrom(utils,read.csv) 170 | -------------------------------------------------------------------------------- /man/geom_phylomorpho.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/phylomorpho.R 3 | \name{geom_phylomorpho} 4 | \alias{geom_phylomorpho} 5 | \title{Plot a 2-D phylomorphospace in ggplot2} 6 | \usage{ 7 | geom_phylomorpho( 8 | tree, 9 | mapping = NULL, 10 | data = NULL, 11 | position = "identity", 12 | ..., 13 | seg_args = list(), 14 | point_args = list(), 15 | arrow = NULL, 16 | arrow.fill = NULL, 17 | lineend = "butt", 18 | linejoin = "round", 19 | na.rm = FALSE, 20 | show.legend = NA, 21 | inherit.aes = TRUE 22 | ) 23 | } 24 | \arguments{ 25 | \item{tree}{An object of class "phylo".} 26 | 27 | \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and 28 | \code{inherit.aes = TRUE} (the default), it is combined with the default mapping 29 | at the top level of the plot. You must supply \code{mapping} if there is no plot 30 | mapping.} 31 | 32 | \item{data}{The data to be displayed in this layer. There are three 33 | options: 34 | 35 | If \code{NULL}, the default, the data is inherited from the plot 36 | data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. 37 | 38 | A \code{data.frame}, or other object, will override the plot 39 | data. All objects will be fortified to produce a data frame. See 40 | \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. 41 | 42 | A \code{function} will be called with a single argument, 43 | the plot data. The return value must be a \code{data.frame}, and 44 | will be used as the layer data. A \code{function} can be created 45 | from a \code{formula} (e.g. \code{~ head(.x, 10)}).} 46 | 47 | \item{position}{A position adjustment to use on the data for this layer. This 48 | can be used in various ways, including to prevent overplotting and 49 | improving the display. The \code{position} argument accepts the following: 50 | \itemize{ 51 | \item The result of calling a position function, such as \code{position_jitter()}. 52 | This method allows for passing extra arguments to the position. 53 | \item A string naming the position adjustment. To give the position as a 54 | string, strip the function name of the \code{position_} prefix. For example, to 55 | use \code{position_jitter()}, give the position as \code{"jitter"}. 56 | }} 57 | 58 | \item{...}{Other arguments passed on to both \code{\link[ggplot2:geom_segment]{ggplot2::geom_segment()}} and 59 | \code{\link[ggplot2:geom_point]{ggplot2::geom_point()}}.} 60 | 61 | \item{seg_args}{A list of arguments passed only to \code{\link[ggplot2:geom_segment]{ggplot2::geom_segment()}}.} 62 | 63 | \item{point_args}{A list of arguments passed only to \code{\link[ggplot2:geom_point]{ggplot2::geom_point()}}.} 64 | 65 | \item{arrow}{specification for arrow heads, as created by \code{\link[grid:arrow]{grid::arrow()}}.} 66 | 67 | \item{arrow.fill}{fill colour to use for the arrow head (if closed). \code{NULL} 68 | means use \code{colour} aesthetic.} 69 | 70 | \item{lineend}{Line end style (round, butt, square).} 71 | 72 | \item{linejoin}{Line join style (round, mitre, bevel).} 73 | 74 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 75 | a warning. If \code{TRUE}, missing values are silently removed.} 76 | 77 | \item{show.legend}{logical. Should this layer be included in the legends? 78 | \code{NA}, the default, includes if any aesthetics are mapped. 79 | \code{FALSE} never includes, and \code{TRUE} always includes. 80 | It can also be a named logical vector to finely select the aesthetics to 81 | display. To include legend keys for all levels, even 82 | when no data exists, use \code{TRUE}. If \code{NA}, all levels are shown in legend, 83 | but unobserved levels are omitted.} 84 | 85 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 86 | rather than combining with them. This is most useful for helper functions 87 | that define both data and aesthetics and shouldn't inherit behaviour from 88 | the default plot specification, e.g. \code{\link[ggplot2:annotation_borders]{annotation_borders()}}.} 89 | } 90 | \description{ 91 | This behaves similar to \code{\link[phytools:phylomorphospace]{phytools::phylomorphospace()}}, but is for plotting a 92 | 2-D phylomorphospace with \code{\link[ggplot2:ggplot]{ggplot2::ggplot()}}. This function works like any 93 | other \code{ggplot2} geom; it can be combined with other geoms (see the example 94 | below), and the output can be modified using scales, themes, etc. 95 | } 96 | \details{ 97 | The ancestral states are estimated using \code{\link[phytools:fastAnc]{phytools::fastAnc()}}. Note that 98 | \code{phytools} is not necessarily installed with \code{deeptime}, but it is required 99 | to use this function. Following the estimation of the ancestral states, the 100 | nodes are connected using \code{\link[ggplot2:geom_segment]{ggplot2::geom_segment()}}, while the tips are 101 | indicated using \code{\link[ggplot2:geom_point]{ggplot2::geom_point()}}. 102 | 103 | The default expectation is that the order of the data is the same order as 104 | the tip labels of the tree (\code{tree$tip.label}). However, if this is not the 105 | case, you can map the optional \code{label} aesthetic to a column in the data that 106 | contains the tip names (see example below). 107 | } 108 | \examples{ 109 | library(ggplot2) 110 | \dontshow{if (require(ape)) withAutoprint(\{ # examplesIf} 111 | library(ape) 112 | tr <- rtree(10) 113 | dat <- data.frame( 114 | x = runif(10), y = runif(10), label = tr$tip.label, 115 | row.names = tr$tip.label 116 | ) 117 | ggplot(dat, aes(x = x, y = y, label = label)) + 118 | geom_phylomorpho(tr) + 119 | geom_label(size = 5) 120 | \dontshow{\}) # examplesIf} 121 | } 122 | -------------------------------------------------------------------------------- /R/phylomorpho.R: -------------------------------------------------------------------------------- 1 | #' Plot a 2-D phylomorphospace in ggplot2 2 | #' 3 | #' This behaves similar to [phytools::phylomorphospace()], but is for plotting a 4 | #' 2-D phylomorphospace with [ggplot2::ggplot()]. This function works like any 5 | #' other `ggplot2` geom; it can be combined with other geoms (see the example 6 | #' below), and the output can be modified using scales, themes, etc. 7 | #' 8 | #' The ancestral states are estimated using [phytools::fastAnc()]. Note that 9 | #' `phytools` is not necessarily installed with `deeptime`, but it is required 10 | #' to use this function. Following the estimation of the ancestral states, the 11 | #' nodes are connected using [ggplot2::geom_segment()], while the tips are 12 | #' indicated using [ggplot2::geom_point()]. 13 | #' 14 | #' The default expectation is that the order of the data is the same order as 15 | #' the tip labels of the tree (`tree$tip.label`). However, if this is not the 16 | #' case, you can map the optional `label` aesthetic to a column in the data that 17 | #' contains the tip names (see example below). 18 | #' 19 | #' @param tree An object of class "phylo". 20 | #' @param position A position adjustment to use on the data for this layer. This 21 | #' can be used in various ways, including to prevent overplotting and 22 | #' improving the display. The `position` argument accepts the following: 23 | #' * The result of calling a position function, such as `position_jitter()`. 24 | #' This method allows for passing extra arguments to the position. 25 | #' * A string naming the position adjustment. To give the position as a 26 | #' string, strip the function name of the `position_` prefix. For example, to 27 | #' use `position_jitter()`, give the position as `"jitter"`. 28 | #' @param seg_args A list of arguments passed only to [ggplot2::geom_segment()]. 29 | #' @param point_args A list of arguments passed only to [ggplot2::geom_point()]. 30 | #' @param ... Other arguments passed on to both [ggplot2::geom_segment()] and 31 | #' [ggplot2::geom_point()]. 32 | #' @importFrom ggplot2 layer 33 | #' @inheritParams ggplot2::layer 34 | #' @inheritParams ggplot2::geom_segment 35 | #' @export 36 | #' @examples 37 | #' library(ggplot2) 38 | #' @examplesIf require(ape) 39 | #' library(ape) 40 | #' tr <- rtree(10) 41 | #' dat <- data.frame( 42 | #' x = runif(10), y = runif(10), label = tr$tip.label, 43 | #' row.names = tr$tip.label 44 | #' ) 45 | #' ggplot(dat, aes(x = x, y = y, label = label)) + 46 | #' geom_phylomorpho(tr) + 47 | #' geom_label(size = 5) 48 | geom_phylomorpho <- function(tree, mapping = NULL, data = NULL, 49 | position = "identity", ..., 50 | seg_args = list(), point_args = list(), 51 | arrow = NULL, arrow.fill = NULL, 52 | lineend = "butt", linejoin = "round", 53 | na.rm = FALSE, show.legend = NA, 54 | inherit.aes = TRUE) { 55 | rlang::check_installed("phytools", reason = "to use `geom_phylomorpho()`") 56 | if (!is(tree, "phylo")) { 57 | cli::cli_abort("`tree` must be a phylo object.") 58 | } 59 | mapping2 <- mapping 60 | mapping2$label <- NULL 61 | list( 62 | layer( 63 | data = data, 64 | mapping = mapping, 65 | stat = StatPhylomorpho, 66 | geom = "segment", 67 | position = position, 68 | show.legend = show.legend, 69 | inherit.aes = inherit.aes, 70 | params = c(list( 71 | tree = tree, 72 | arrow = arrow, 73 | arrow.fill = arrow.fill, 74 | lineend = lineend, 75 | linejoin = linejoin, 76 | na.rm = na.rm, 77 | ... 78 | ), seg_args) 79 | ), 80 | layer( 81 | data = data, 82 | mapping = mapping2, 83 | stat = "identity", 84 | geom = "point", 85 | position = position, 86 | show.legend = show.legend, 87 | inherit.aes = inherit.aes, 88 | params = c(list( 89 | na.rm = na.rm, 90 | ... 91 | ), point_args) 92 | ) 93 | ) 94 | } 95 | 96 | #' @importFrom ggplot2 ggproto Stat 97 | StatPhylomorpho <- ggproto("StatPhylomorpho", Stat, 98 | required_aes = c("x", "y"), 99 | optional_aes = c("label"), 100 | compute_group = function(data, params) { 101 | data 102 | }, 103 | compute_panel = function(self, data, scales, params, tree) { 104 | if (nrow(data) != length(tree$tip.label)) { 105 | cli::cli_abort("`data` must contain the same number of rows as species in 106 | `tree`.") 107 | } 108 | if ("label" %in% colnames(data)) { 109 | rownames(data) <- data$label 110 | data$label <- NULL 111 | } else { 112 | rownames(data) <- tree$tip.label 113 | } 114 | # copied from phytools 115 | A <- apply(data, 2, phytools::fastAnc, tree = tree) 116 | aa <- setNames( 117 | c(data[tree$tip.label, "x"], A[, 1]), 118 | c(seq_along(tree$tip.label), rownames(A)) 119 | ) 120 | bb <- setNames( 121 | c(data[tree$tip.label, "y"], A[, 2]), 122 | c(seq_along(tree$tip.label), rownames(A)) 123 | ) 124 | XX <- matrix(aa[as.character(tree$edge)], nrow(tree$edge), 2) 125 | YY <- matrix(bb[as.character(tree$edge)], nrow(tree$edge), 2) 126 | xx <- setNames(c(XX[1, 1], XX[, 2]), c(tree$edge[1, 1], tree$edge[, 2])) 127 | xx <- xx[order(as.numeric(names(xx)))] 128 | yy <- setNames(c(YY[1, 1], YY[, 2]), c(tree$edge[1, 1], tree$edge[, 2])) 129 | yy <- yy[order(as.numeric(names(yy)))] 130 | df <- data.frame( 131 | x = xx[tree$edge[, 1]], xend = xx[tree$edge[, 2]], 132 | y = yy[tree$edge[, 1]], yend = yy[tree$edge[, 2]] 133 | ) 134 | return(df) 135 | } 136 | ) 137 | -------------------------------------------------------------------------------- /R/get_scale_data.R: -------------------------------------------------------------------------------- 1 | #' Get geological timescale data 2 | #' 3 | #' This function takes a name of a geological timescale and returns data for the 4 | #' timescale. Valid names include those of built-in `data.frames` ([periods()], 5 | #' [epochs()], [stages()], [eons()], or [eras()]), partial matches of those 6 | #' names (e.g., "per" or "age"), and partial or exact matches to those hosted 7 | #' by Macrostrat (see Details below). Note that the colors in the built-in 8 | #' `data.frames` are according to the Commission for the Geological Map of the 9 | #' World. If you would like to obtain custom Macrostrat colors that are better 10 | #' for mapping, you should specify the full name of a timescale (e.g., 11 | #' "international periods") and set `true_colors` to `FALSE`. Note that these 12 | #' colors only vary for the Precambrian. 13 | #' 14 | #' @details The following timescales are available from the Macrostrat API as of 15 | #' `r Sys.Date()`: 16 | #' \itemize{ 17 | #' `r macrostrat_timescales()` 18 | #' } 19 | #' 20 | #' The most up-to-date list can be found via the Macrostrat API [here](https://macrostrat.org/api/defs/timescales?all). 21 | #' 22 | #' @param name The name of the desired timescale. 23 | #' @param true_colors Return original international time scale colors? (as 24 | #' opposed to custom Macrostrat plotting colors) 25 | #' @return A `data.frame` with the following columns: 26 | #' \item{name}{the names of the time intervals} 27 | #' \item{max_age}{the oldest boundaries of the time intervals, in millions of 28 | #' years} 29 | #' \item{min_age}{the youngest boundaries of the time intervals, in millions 30 | #' of years} 31 | #' \item{abbr}{either traditional abbreviations of the names of the time 32 | #' intervals (if they exist) or custom abbreviations created with R} 33 | #' \item{color}{hex color codes associated with the time intervals (if 34 | #' applicable)} 35 | #' \item{lab_color}{default label colors for the time interals, either white 36 | #' or black, whichever has better contrast with the background color, based 37 | #' on [recommendations by the International Telecommunication Union](https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en)} 38 | #' @importFrom utils read.csv 39 | #' @importFrom curl nslookup 40 | #' @export 41 | get_scale_data <- function(name, true_colors = TRUE) { 42 | check_required(name) 43 | check_bool(true_colors) 44 | possible_names <- c("periods", "epochs", "stages", "eras", "eons") 45 | name_match <- grep(name, possible_names, ignore.case = TRUE) 46 | if (length(name_match) > 0) { 47 | if (length(name_match) > 1) { 48 | cli::cli_abort("`name` matches multiple built-in timescales. Please be 49 | more specific.") 50 | } else { 51 | name <- possible_names[name_match] 52 | if (name == "periods") { 53 | dat <- deeptime::periods 54 | } else if (name == "epochs") { 55 | dat <- deeptime::epochs 56 | } else if (name == "stages") { 57 | dat <- deeptime::stages 58 | } else if (name == "eras") { 59 | dat <- deeptime::eras 60 | } else if (name == "eons") { 61 | dat <- deeptime::eons 62 | } 63 | } 64 | } else { 65 | # try to get the timescale from macrostrat 66 | # check that we are online and macrostrat is online 67 | tryCatch(# nocov start 68 | { 69 | nslookup("macrostrat.org") 70 | }, 71 | error = function(e) { 72 | cli::cli_abort("Macrostrat is not available. Either the site is down or 73 | you are not connected to the internet.") 74 | } 75 | )# nocov end 76 | avail_scales <- read.csv(url(paste0("https://macrostrat.org/api/v2/defs/", 77 | "timescales?all&format=csv")), 78 | stringsAsFactors = FALSE) 79 | # check exact matches 80 | name_match <- match(tolower(name), tolower(avail_scales$timescale)) 81 | if (is.na(name_match)) { 82 | # check partial matches 83 | name_match <- grep(name, avail_scales$timescale, ignore.case = TRUE) 84 | if (length(name_match) == 0) { 85 | cli::cli_abort("`name` does not match a built-in or Macrostrat 86 | timescale.") 87 | } else if (length(name_match) > 1) { 88 | cli::cli_abort("`name` matches multiple Macrostrat timescales. Please be 89 | more specific.") 90 | } 91 | } 92 | # get full timescale name and retrieve data from Macrostrat 93 | name <- avail_scales$timescale[name_match] 94 | URL <- url(paste0("https://macrostrat.org/api/v2/defs/intervals", 95 | "?format=csv×cale=", gsub(" ", "%20", name), 96 | ifelse(true_colors, "&true_colors=true", ""))) 97 | raw_dat <- tryCatch( 98 | { 99 | read.csv(URL, header = TRUE, stringsAsFactors = FALSE) 100 | }, 101 | error = function(e) {# nocov start 102 | cli::cli_abort("Macrostrat is not available. Either the site is down 103 | or you are not connected to the internet.") 104 | }# nocov end 105 | ) 106 | clean_dat <- raw_dat[, c("name", "b_age", "t_age", "abbrev", "color")] 107 | colnames(clean_dat) <- c("name", "max_age", "min_age", "abbr", "color") 108 | no_abbr <- (is.na(clean_dat$abbr) | clean_dat$abbr == "") 109 | clean_dat$abbr[no_abbr] <- 110 | abbreviate(clean_dat$name, minlength = 1, 111 | use.classes = TRUE, named = FALSE)[no_abbr] 112 | clean_dat$abbr[clean_dat$name == "Stage 10"] <- "S10" # fix abbreviation 113 | dat <- clean_dat 114 | dat$lab_color <- white_or_black(dat$color) 115 | } 116 | dat 117 | } 118 | 119 | # Determine best label colors based on luminance as per 120 | # https://stackoverflow.com/a/1855903/4660582 121 | # values are from https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en 122 | #' @importFrom grDevices col2rgb 123 | white_or_black <- function(colors) { 124 | rgbs <- col2rgb(colors) 125 | luminance <- apply(rgbs, 2, function(x) { 126 | (0.299 * x[1] + 0.587 * x[2] + 0.114 * x[3]) / 255 127 | }) 128 | ifelse(luminance > .5, "black", "white") 129 | } 130 | 131 | # generate docs for available Macrostrat timescales 132 | macrostrat_timescales <- function() {# nocov start 133 | scales <- read.csv(url(paste0("https://macrostrat.org/api/v2/defs/timescales", 134 | "?all&format=csv")), 135 | stringsAsFactors = FALSE) 136 | return(paste0("\\item ", scales$timescale, collapse = "\n")) 137 | }# nocov end 138 | -------------------------------------------------------------------------------- /R/disparity_through_time.R: -------------------------------------------------------------------------------- 1 | calculateAxisComponents <- function(...) { 2 | asNamespace("lattice")$calculateAxisComponents(...) 3 | } 4 | 5 | #' Combined wireframe and cloud panel 6 | #' 7 | #' Plots the provided data on 2-D surfaces within a 3-D framework. See 8 | #' [disparity_through_time()]. 9 | #' @param x,y,z,groups,subscripts,... Same as for [lattice::panel.cloud()] 10 | #' @return No return value, plots the results of both [lattice::panel.cloud()] 11 | #' and [lattice::panel.wireframe()]. 12 | #' @importFrom lattice panel.wireframe panel.cloud 13 | #' @export 14 | panel.disparity <- function(x, y, z, groups, subscripts, ...) { 15 | args <- list(...) 16 | xlabelinfo <- calculateAxisComponents(args$xlim, 17 | at = args$scales.3d$x.scales$at, 18 | num.limit = NULL, 19 | labels = args$scales.3d$x.scales$labels, 20 | logsc = args$scales.3d$x.scales$log, 21 | abbreviate = args$scales.3d$x.scales$abbreviate, 22 | minlength = args$scales.3d$x.scales$minlength, 23 | format.posixt = args$scales.3d$x.scales$format, 24 | n = args$scales.3d$x.scales$tick.number 25 | ) 26 | ylabelinfo <- calculateAxisComponents(args$ylim, 27 | at = args$scales.3d$y.scales$at, 28 | num.limit = NULL, 29 | labels = args$scales.3d$y.scales$labels, 30 | logsc = args$scales.3d$y.scales$log, 31 | abbreviate = args$scales.3d$y.scales$abbreviate, 32 | minlength = args$scales.3d$y.scales$minlength, 33 | format.posixt = args$scales.3d$y.scales$format, 34 | n = args$scales.3d$y.scales$tick.number 35 | ) 36 | zlabelinfo <- calculateAxisComponents(args$zlim, 37 | at = args$scales.3d$z.scales$at, 38 | num.limit = NULL, 39 | labels = args$scales.3d$z.scales$labels, 40 | logsc = args$scales.3d$z.scales$log, 41 | abbreviate = args$scales.3d$z.scales$abbreviate, 42 | minlength = args$scales.3d$z.scales$minlength, 43 | format.posixt = args$scales.3d$z.scales$format, 44 | n = args$scales.3d$z.scales$tick.number 45 | ) 46 | tmp <- expand.grid(x = sort(union(xlabelinfo$at, xlabelinfo$num.limit)), 47 | y = sort(union(ylabelinfo$at, ylabelinfo$num.limit)), 48 | gr = zlabelinfo$at) 49 | panel.wireframe(x = tmp$x, y = tmp$y, z = tmp$gr, groups = tmp$gr, 50 | subscripts = seq_len(nrow(tmp)), ...) 51 | panel.cloud(x = x, y = y, z = z, groups = groups, 52 | subscripts = subscripts, par.box = list("col" = NA), ...) 53 | } 54 | 55 | #' Disparity through time plot using lattice 56 | #' 57 | #' Plots points on 2-D surfaces within a a 3-D framework. See 58 | #' [lattice::wireframe()] and [lattice::panel.cloud()] for customization 59 | #' options. 60 | #' 61 | #' @param x a formula (most likely of the form `z ~ x * y`) 62 | #' @param data a data frame in which variables in the formula are to be 63 | #' evaluated 64 | #' @param groups a variable in `data` to be used as a grouping variable (this is 65 | #' probably the z variable) 66 | #' @param scales a list specifying how the axes are drawn (see 67 | #' [lattice::xyplot()] for details) 68 | #' @param pch the point type 69 | #' @param col.point color(s) for points on surfaces 70 | #' @param drape logical, whether the surfaces should be colored based on 71 | #' `col.regions` and `alpha.regions` 72 | #' @param col.regions color(s) for surfaces 73 | #' @param alpha.regions alpha value(s) for surfaces 74 | #' @param colorkey logical, should a legend be drawn (or a list describing the 75 | #' legend; see [lattice::levelplot()] for details) 76 | #' @param screen a list of the rotations that should be applied to each axis 77 | #' @param R.mat a transformational matrix that is applied to the orientation of 78 | #' the axes 79 | #' @param aspect a numeric vector of length 2, giving the relative aspects of 80 | #' the y-size/x-size and z-size/x-size of the enclosing cube 81 | #' @param perspective logical, whether to plot a perspective view 82 | #' @param par.settings plotting settings (see [lattice::trellis.par.set()]) 83 | #' @param lattice.options lattice settings (see [lattice::lattice.options()]) 84 | #' @param ... Other arguments passed to [lattice::wireframe()] 85 | #' @return An object of class `"trellis"`, as output by [lattice::wireframe()]. 86 | #' @importFrom lattice wireframe 87 | #' @export 88 | #' @examples 89 | #' g <- data.frame( 90 | #' x = runif(100, 0, 60), y = runif(100, 0, 10), 91 | #' z = factor(rep(periods$name[1:5], each = 20), 92 | #' levels = periods$name[1:5] 93 | #' ) 94 | #' ) 95 | #' disparity_through_time(z ~ x * y, 96 | #' data = g, groups = z, aspect = c(1.5, 2), 97 | #' xlim = c(0, 60), ylim = c(0, 10), col.regions = "lightgreen", 98 | #' col.point = c("red", "blue") 99 | #' ) 100 | disparity_through_time <- 101 | function(x, data, groups, pch = 16, col.point = c("blue"), 102 | scales = list( 103 | arrows = FALSE, distance = 1, col = "black", 104 | z = list(rot = 90) 105 | ), 106 | colorkey = FALSE, 107 | screen = list(z = 90, x = 70, y = 180), aspect = c(1.5, 4), 108 | drape = TRUE, col.regions = c("white"), alpha.regions = c(1), 109 | perspective = FALSE, R.mat = matrix( 110 | c( 111 | 1, 1, 0, 0, 112 | 0, 1, 0, 0, 113 | 0, 0, 1, 0, 114 | 0, 0, 0, 1 115 | ), 116 | 4, 4 117 | ), 118 | par.settings = list( 119 | axis.line = list(col = "transparent"), 120 | layout.heights = list( 121 | top.padding = 0, 122 | main.key.padding = 0, 123 | key.axis.padding = 0, 124 | axis.xlab.padding = 0, 125 | xlab.key.padding = 0, 126 | key.sub.padding = 0, 127 | bottom.padding = 0 128 | ), 129 | layout.widths = list( 130 | left.padding = 0, 131 | key.ylab.padding = 0, 132 | ylab.axis.padding = 0, 133 | axis.key.padding = 0, 134 | right.padding = 0 135 | ) 136 | ), 137 | lattice.options = list(axis.padding = list(factor = 0)), ...) { 138 | eval(substitute(lattice::wireframe( 139 | x = x, data = data, groups = groups, pch = pch, col.point = col.point, 140 | scales = scales, colorkey = colorkey, screen = screen, 141 | panel = deeptime::panel.disparity, aspect = aspect, drape = drape, 142 | col.regions = col.regions, alpha.regions = alpha.regions, 143 | perspective = perspective, R.mat = R.mat, 144 | par.settings = par.settings, lattice.options = lattice.options, ... 145 | )), envir = parent.frame()) 146 | } 147 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' Eon data from the International Commission on Stratigraphy (v2024/12) 2 | #' 3 | #' A dataset containing the boundary ages, abbreviations, and colors for the 4 | #' eons of the Geologic Time Scale. Based on The ICS International 5 | #' Chronostratigraphic Chart (v2024/12), by Cohen, Finney, Gibbard, and Fan. 6 | #' 7 | #' @format A data frame with 3 rows and 5 variables: 8 | #' \describe{ 9 | #' \item{name}{eon name} 10 | #' \item{max_age}{maximum age, in millions of years} 11 | #' \item{min_age}{minimum age, in millions of years} 12 | #' \item{abbr}{eon name abbreviations} 13 | #' \item{color}{the colors for each eon, according to the Commission for the 14 | #' Geological Map of the World} 15 | #' \item{lab_color}{the label colors for each eon, either white or black, 16 | #' whichever has better contrast with the background color, based on 17 | #' [recommendations by the International Telecommunication Union](https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en)} 18 | #' } 19 | #' @family built-in timescales 20 | #' @source via 21 | "eons" 22 | 23 | #' Era data from the International Commission on Stratigraphy (v2024/12) 24 | #' 25 | #' A dataset containing the boundary ages, abbreviations, and colors for the 26 | #' eras of the Geologic Time Scale. Based on The ICS International 27 | #' Chronostratigraphic Chart (v2024/12), by Cohen, Finney, Gibbard, and Fan. 28 | #' 29 | #' @format A data frame with 10 rows and 5 variables: 30 | #' \describe{ 31 | #' \item{name}{era name} 32 | #' \item{max_age}{maximum age, in millions of years} 33 | #' \item{min_age}{minimum age, in millions of years} 34 | #' \item{abbr}{era name abbreviations} 35 | #' \item{color}{the colors for each era, according to the Commission for the 36 | #' Geological Map of the World} 37 | #' \item{lab_color}{the label colors for each era, either white or black, 38 | #' whichever has better contrast with the background color, based on 39 | #' [recommendations by the International Telecommunication Union](https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en)} 40 | #' } 41 | #' @family built-in timescales 42 | #' @source via 43 | "eras" 44 | 45 | #' Period data from the International Commission on Stratigraphy (v2024/12) 46 | #' 47 | #' A dataset containing the boundary ages, abbreviations, and colors for the 48 | #' periods of the Geologic Time Scale. Based on The ICS International 49 | #' Chronostratigraphic Chart (v2024/12), by Cohen, Finney, Gibbard, and Fan. 50 | #' 51 | #' @format A data frame with 22 rows and 5 variables: 52 | #' \describe{ 53 | #' \item{name}{period name} 54 | #' \item{max_age}{maximum age, in millions of years} 55 | #' \item{min_age}{minimum age, in millions of years} 56 | #' \item{abbr}{period name abbreviations} 57 | #' \item{color}{the colors for each period, according to the Commission for 58 | #' the Geological Map of the World} 59 | #' \item{lab_color}{the label colors for each period, either white or black, 60 | #' whichever has better contrast with the background color, based on 61 | #' [recommendations by the International Telecommunication Union](https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en)} 62 | #' } 63 | #' @family built-in timescales 64 | #' @source via 65 | "periods" 66 | 67 | #' Epoch data from the International Commission on Stratigraphy (v2024/12) 68 | #' 69 | #' A dataset containing the boundary ages, abbreviations, and colors for the 70 | #' epochs of the Geologic Time Scale. Based on The ICS International 71 | #' Chronostratigraphic Chart (v2024/12), by Cohen, Finney, Gibbard, and Fan. 72 | #' 73 | #' @format A data frame with 34 rows and 5 variables: 74 | #' \describe{ 75 | #' \item{name}{epoch name} 76 | #' \item{max_age}{maximum age, in millions of years} 77 | #' \item{min_age}{minimum age, in millions of years} 78 | #' \item{abbr}{epoch name abbreviations} 79 | #' \item{color}{the colors for each epoch, according to the Commission for the 80 | #' Geological Map of the World} 81 | #' \item{lab_color}{the label colors for each epoch, either white or black, 82 | #' whichever has better contrast with the background color, based on 83 | #' [recommendations by the International Telecommunication Union](https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en)} 84 | #' } 85 | #' @family built-in timescales 86 | #' @source via 87 | "epochs" 88 | 89 | #' Stage data from the International Commission on Stratigraphy (v2024/12) 90 | #' 91 | #' A dataset containing the boundary ages, abbreviations, and colors for the 92 | #' stages of the Geologic Time Scale. Based on The ICS International 93 | #' Chronostratigraphic Chart (v2024/12), by Cohen, Finney, Gibbard, and Fan. 94 | #' 95 | #' @format A data frame with 102 rows and 5 variables: 96 | #' \describe{ 97 | #' \item{name}{stage name} 98 | #' \item{max_age}{maximum age, in millions of years} 99 | #' \item{min_age}{minimum age, in millions of years} 100 | #' \item{abbr}{stage name abbreviations} 101 | #' \item{color}{the colors for each stage, according to the Commission for the 102 | #' Geological Map of the World} 103 | #' \item{lab_color}{the label colors for each stage, either white or black, 104 | #' whichever has better contrast with the background color, based on 105 | #' [recommendations by the International Telecommunication Union](https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en)} 106 | #' } 107 | #' @family built-in timescales 108 | #' @source via 109 | "stages" 110 | 111 | #' Pattern numbers and names for patterns from the FGDC Digital Cartographic 112 | #' Standard for Geologic Map Symbolization 113 | #' 114 | #' A dataset containing the FGDC pattern numbers and verbatim names from the 115 | #' [FGDC Digital Cartographic Standard for Geologic Map 116 | #' Symbolization](https://ngmdb.usgs.gov/fgdc_gds/geolsymstd.php) by the [U.S. 117 | #' Geological Survey](https://www.usgs.gov/) and the [Geologic Data Subcommittee 118 | #' (GDS)](https://ngmdb.usgs.gov/fgdc_gds/index.php) of the [Federal Geographic 119 | #' Data Committee (FGDC)](https://www.fgdc.gov/). Only patterns with names are 120 | #' included (i.e., patterns 601-733). 121 | #' 122 | #' These pattern numbers and names were originally extracted by Daven Quinn and 123 | #' are hosted on [GitHub](https://github.com/davenquinn/geologic-patterns/). 124 | #' 125 | #' @format A data frame with 117 rows and 2 variables: 126 | #' \describe{ 127 | #' \item{code}{the pattern number according to the FGDC standard} 128 | #' \item{name}{the verbatim name for the pattern according to the FGDC standard} 129 | #' } 130 | #' @family patterns 131 | #' @source 132 | #' 133 | #' via 134 | "fgdc_names" 135 | -------------------------------------------------------------------------------- /man/scale_fill_geopattern.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.R 3 | \name{scale_fill_geopattern} 4 | \alias{scale_fill_geopattern} 5 | \title{Geologic pattern fill scale} 6 | \usage{ 7 | scale_fill_geopattern(na.value = "grey50", ...) 8 | } 9 | \arguments{ 10 | \item{na.value}{The aesthetic value to use for missing (NA) values. May be 11 | either a color or a \link[grid:patterns]{GridPattern} object (such as that 12 | returned by \code{\link[=geo_pattern]{geo_pattern()}}).} 13 | 14 | \item{...}{ 15 | Arguments passed on to \code{\link[ggplot2:discrete_scale]{ggplot2::discrete_scale}} 16 | \describe{ 17 | \item{\code{scale_name}}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} The name of the scale 18 | that should be used for error messages associated with this scale.} 19 | \item{\code{name}}{The name of the scale. Used as the axis or legend title. If 20 | \code{waiver()}, the default, the name of the scale is taken from the first 21 | mapping used for that aesthetic. If \code{NULL}, the legend title will be 22 | omitted.} 23 | \item{\code{breaks}}{One of: 24 | \itemize{ 25 | \item \code{NULL} for no breaks 26 | \item \code{waiver()} for the default breaks (the scale limits) 27 | \item A character vector of breaks 28 | \item A function that takes the limits as input and returns breaks 29 | as output. Also accepts rlang \link[rlang:as_function]{lambda} function 30 | notation. 31 | }} 32 | \item{\code{minor_breaks}}{One of: 33 | \itemize{ 34 | \item \code{NULL} for no minor breaks 35 | \item \code{waiver()} for the default breaks (none for discrete, one minor break 36 | between each major break for continuous) 37 | \item A numeric vector of positions 38 | \item A function that given the limits returns a vector of minor breaks. Also 39 | accepts rlang \link[rlang:as_function]{lambda} function notation. When 40 | the function has two arguments, it will be given the limits and major 41 | break positions. 42 | }} 43 | \item{\code{labels}}{One of the options below. Please note that when \code{labels} is a 44 | vector, it is highly recommended to also set the \code{breaks} argument as a 45 | vector to protect against unintended mismatches. 46 | \itemize{ 47 | \item \code{NULL} for no labels 48 | \item \code{waiver()} for the default labels computed by the 49 | transformation object 50 | \item A character vector giving labels (must be same length as \code{breaks}) 51 | \item An expression vector (must be the same length as breaks). See ?plotmath for details. 52 | \item A function that takes the breaks as input and returns labels 53 | as output. Also accepts rlang \link[rlang:as_function]{lambda} function 54 | notation. 55 | }} 56 | \item{\code{limits}}{One of: 57 | \itemize{ 58 | \item \code{NULL} to use the default scale values 59 | \item A character vector that defines possible values of the scale and their 60 | order 61 | \item A function that accepts the existing (automatic) values and returns 62 | new ones. Also accepts rlang \link[rlang:as_function]{lambda} function 63 | notation. 64 | }} 65 | \item{\code{na.translate}}{Unlike continuous scales, discrete scales can easily show 66 | missing values, and do so by default. If you want to remove missing values 67 | from a discrete scale, specify \code{na.translate = FALSE}.} 68 | \item{\code{drop}}{Should unused factor levels be omitted from the scale? 69 | The default, \code{TRUE}, uses the levels that appear in the data; 70 | \code{FALSE} includes the levels in the factor. Please note that to display 71 | every level in a legend, the layer should use \code{show.legend = TRUE}.} 72 | \item{\code{guide}}{A function used to create a guide or its name. See 73 | \code{\link[ggplot2:guides]{guides()}} for more information.} 74 | \item{\code{call}}{The \code{call} used to construct the scale for reporting messages.} 75 | }} 76 | } 77 | \description{ 78 | Fill scale using the \href{https://ngmdb.usgs.gov/fgdc_gds/geolsymstd.php}{FGDC Digital Cartographic Standard for Geologic Map Symbolization}. Fill values 79 | should correspond to specific pattern codes (see "Details"). 80 | } 81 | \details{ 82 | For specific codes, see the "pattern numbers" in the \href{https://ngmdb.usgs.gov/fgdc_gds/geolsymstd/fgdc-geolsym-patternchart.pdf}{full pattern chart} 83 | for valid \code{code} values. Daven Quinn has also assembled more accessible 84 | documentation of the \href{https://davenquinn.com/projects/geologic-patterns/#pattern-reference}{map patterns/codes} 85 | and \href{https://davenquinn.com/projects/geologic-patterns/#series-600}{lithology patterns/codes}. 86 | The set of patterns with names is also included in the built-in dataset 87 | \link{fgdc_names} (and a label dictionary is available using \code{\link[=fgdc_dict]{fgdc_dict()}}. 88 | \code{\link[rmacrostrat:def_lithologies]{rmacrostrat::def_lithologies()}} can also be used to look up pattern codes 89 | for various lithologies (see the "fill" column). Note that codes associated 90 | with color variants (e.g., "101-M") are supported but will result in the 91 | default color variant instead (usually black and white, e.g., "101-K"). 92 | 93 | These patterns were originally processed and optimized by Daven Quinn and 94 | are hosted on \href{https://github.com/davenquinn/geologic-patterns/}{GitHub}. 95 | } 96 | \section{Warning}{ 97 | Pattern fills are not supported on all graphics devices. 98 | Not all devices are under active development, and such devices are unlikely 99 | to add support for new features (such as pattern fills). The new features 100 | have only been implemented on a subset of graphics devices so far: 101 | \code{\link[=cairo_pdf]{cairo_pdf()}}, \code{\link[=cairo_ps]{cairo_ps()}}, \code{\link[=x11]{x11(type="cairo")}}, 102 | \code{\link[=png]{png(type="cairo")}}, 103 | \code{\link[=jpeg]{jpeg(type="cairo")}}, 104 | \code{\link[=tiff]{tiff(type="cairo")}}, \code{\link[=svg]{svg()}}, and \code{\link[=pdf]{pdf()}}. Although 105 | there is no support yet for \code{\link[=quartz]{quartz()}} or \code{\link[=windows]{windows()}}, almost all of the 106 | graphics devices above will work on all major platforms. Further, the 107 | \href{https://ragg.r-lib.org/}{ragg} and 108 | \href{https://svglite.r-lib.org/index.html}{svglite} packages contain graphics 109 | devices that support patterns. When using a graphics device where patterns 110 | are not supported, closed shapes will be rendered with a transparent fill. 111 | Note that, at least on Windows machines, the default device in RStudio and 112 | in the knitr package is \code{\link[=png]{png()}}, which does not support patterns. In 113 | RStudio, you can go to ‘Tools > Global Options > General > Graphics’ and 114 | choose the ‘Cairo PNG’ device from the dropdown menu to display patterns. 115 | Similar issues may arise when using RStudio on other operating systems. 116 | } 117 | 118 | \examples{ 119 | library(ggplot2) 120 | vals <- c("101", "313", "603", "733") 121 | ggplot(mpg, aes(factor(cyl), fill = vals[factor(cyl)])) + 122 | geom_bar() + 123 | scale_fill_geopattern(name = NULL) 124 | } 125 | \seealso{ 126 | FGDC patterns: 127 | \code{\link{fgdc_dict}()}, 128 | \code{\link{fgdc_names}}, 129 | \code{\link{geo_pattern}()}, 130 | \code{\link{grid.pattern_geo}()} 131 | } 132 | \concept{patterns} 133 | -------------------------------------------------------------------------------- /man/facet_wrap_color.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/facet_color.R 3 | \docType{data} 4 | \name{facet_wrap_color} 5 | \alias{facet_wrap_color} 6 | \alias{facet_wrap_geo} 7 | \alias{FacetWrapColor} 8 | \title{Wrap a 1d ribbon of panels into 2d with colored strips} 9 | \usage{ 10 | facet_wrap_color( 11 | facets, 12 | colors, 13 | nrow = NULL, 14 | ncol = NULL, 15 | scales = "fixed", 16 | shrink = TRUE, 17 | labeller = "label_value", 18 | lab_colors = "auto", 19 | as.table = TRUE, 20 | drop = TRUE, 21 | dir = "h", 22 | strip.position = "top", 23 | axes = "margins", 24 | axis.labels = "all" 25 | ) 26 | 27 | facet_wrap_geo( 28 | facets, 29 | colors = stages, 30 | nrow = NULL, 31 | ncol = NULL, 32 | scales = "fixed", 33 | shrink = TRUE, 34 | labeller = "label_value", 35 | lab_colors = "auto", 36 | as.table = TRUE, 37 | drop = TRUE, 38 | dir = "h", 39 | strip.position = "top", 40 | axes = "margins", 41 | axis.labels = "all" 42 | ) 43 | } 44 | \arguments{ 45 | \item{facets}{A set of variables or expressions quoted by \code{\link[ggplot2:vars]{vars()}} 46 | and defining faceting groups on the rows or columns dimension. 47 | The variables can be named (the names are passed to \code{labeller}). 48 | 49 | For compatibility with the classic interface, can also be a 50 | formula or character vector. Use either a one sided formula, \code{~a + b}, 51 | or a character vector, \code{c("a", "b")}.} 52 | 53 | \item{colors}{Specifies which colors to use to replace the strip backgrounds. 54 | Either A) a function that returns a color for a given strip label, B) the 55 | character name of a function that does the same, C) a named character 56 | vector with names matching strip labels and values indicating the desired 57 | colors, or D) a data.frame representing a lookup table with columns named 58 | "name" (matching strip labels) and "color" (indicating desired colors). If 59 | the function returns \code{NA}, the default background color will be used.} 60 | 61 | \item{nrow, ncol}{Number of rows and columns.} 62 | 63 | \item{scales}{Should scales be fixed (\code{"fixed"}, the default), 64 | free (\code{"free"}), or free in one dimension (\code{"free_x"}, 65 | \code{"free_y"})?} 66 | 67 | \item{shrink}{If \code{TRUE}, will shrink scales to fit output of 68 | statistics, not raw data. If \code{FALSE}, will be range of raw data 69 | before statistical summary.} 70 | 71 | \item{labeller}{A function that takes one data frame of labels and 72 | returns a list or data frame of character vectors. Each input 73 | column corresponds to one factor. Thus there will be more than 74 | one with \code{vars(cyl, am)}. Each output 75 | column gets displayed as one separate line in the strip 76 | label. This function should inherit from the "labeller" S3 class 77 | for compatibility with \code{\link[ggplot2:labeller]{labeller()}}. You can use different labeling 78 | functions for different kind of labels, for example use \code{\link[ggplot2:label_parsed]{label_parsed()}} for 79 | formatting facet labels. \code{\link[ggplot2:label_value]{label_value()}} is used by default, 80 | check it for more details and pointers to other options.} 81 | 82 | \item{lab_colors}{Specifies which colors to use for the strip labels. Either 83 | A) a function that returns a color for a given strip label, B) the 84 | character name of a function that does the same, C) a named character 85 | vector with names matching strip labels and values indicating the desired 86 | colors, D) a data.frame representing a lookup table with columns named 87 | "name" (matching strip labels) and "lab_color" (indicating desired colors), 88 | or E) "auto" (the default), which set the labels to black or white, 89 | whichever has better contrast with the background color, based on 90 | \href{https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en}{recommendations by the International Telecommunication Union}. 91 | If the function returns \code{NA}, the default label color will be used.} 92 | 93 | \item{as.table}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}} The \code{as.table} argument 94 | is now absorbed into the \code{dir} argument via the two letter options. 95 | If \code{TRUE}, the facets are laid out like a table with highest values at the 96 | bottom-right. If \code{FALSE}, the facets are laid out like a plot with the 97 | highest value at the top-right.} 98 | 99 | \item{drop}{If \code{TRUE}, the default, all factor levels not used in the 100 | data will automatically be dropped. If \code{FALSE}, all factor levels 101 | will be shown, regardless of whether or not they appear in the data.} 102 | 103 | \item{dir}{Direction: either \code{"h"} for horizontal, the default, or \code{"v"}, 104 | for vertical. When \code{"h"} or \code{"v"} will be combined with \code{as.table} to 105 | set final layout. Alternatively, a combination of \code{"t"} (top) or 106 | \code{"b"} (bottom) with \code{"l"} (left) or \code{"r"} (right) to set a layout directly. 107 | These two letters give the starting position and the first letter gives 108 | the growing direction. For example \code{"rt"} will place the first panel in 109 | the top-right and starts filling in panels right-to-left.} 110 | 111 | \item{strip.position}{By default, the labels are displayed on the top of 112 | the plot. Using \code{strip.position} it is possible to place the labels on 113 | either of the four sides by setting \code{strip.position = c("top", 114 | "bottom", "left", "right")}} 115 | 116 | \item{axes}{Determines which axes will be drawn in case of fixed scales. 117 | When \code{"margins"} (default), axes will be drawn at the exterior margins. 118 | \code{"all_x"} and \code{"all_y"} will draw the respective axes at the interior 119 | panels too, whereas \code{"all"} will draw all axes at all panels.} 120 | 121 | \item{axis.labels}{Determines whether to draw labels for interior axes when 122 | the scale is fixed and the \code{axis} argument is not \code{"margins"}. When 123 | \code{"all"} (default), all interior axes get labels. When \code{"margins"}, only 124 | the exterior axes get labels, and the interior axes get none. When 125 | \code{"all_x"} or \code{"all_y"}, only draws the labels at the interior axes in the 126 | x- or y-direction respectively.} 127 | } 128 | \description{ 129 | \code{facet_wrap_color} behaves similarly to \code{\link[ggplot2:facet_wrap]{ggplot2::facet_wrap()}} in that it 130 | wraps a 1d sequence of panels into 2d. The main difference is that it also 131 | allows the user to specify the background and label colors of the individual 132 | facet strips using the \code{colors} and \code{lab_colors} arguments. This is generally 133 | a better use of screen space than \code{\link[=facet_grid_color]{facet_grid_color()}} because most displays 134 | are roughly rectangular. 135 | } 136 | \details{ 137 | \code{facet_wrap_geo(...)} is an alias of \code{facet_wrap_color()} with the default of 138 | \code{colors} set to \code{stages}. 139 | } 140 | \examples{ 141 | library(ggplot2) 142 | df <- data.frame(x = 1:10, y = 1:10, period = c("Permian", "Triassic")) 143 | ggplot(df) + 144 | geom_point(aes(x, y)) + 145 | facet_wrap_color(vars(period), colors = periods) 146 | } 147 | \seealso{ 148 | Other faceting functions: 149 | \code{\link{facet_grid_color}()}, 150 | \code{\link{facet_nested_color}()}, 151 | \code{\link{facet_nested_wrap_color}()} 152 | } 153 | \concept{faceting functions} 154 | \keyword{datasets} 155 | -------------------------------------------------------------------------------- /man/facet_grid_color.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/facet_color.R 3 | \docType{data} 4 | \name{facet_grid_color} 5 | \alias{facet_grid_color} 6 | \alias{facet_grid_geo} 7 | \alias{FacetGridColor} 8 | \title{Lay out panels in a grid with colored strips} 9 | \usage{ 10 | facet_grid_color( 11 | colors, 12 | rows = NULL, 13 | cols = NULL, 14 | scales = "fixed", 15 | space = "fixed", 16 | shrink = TRUE, 17 | labeller = "label_value", 18 | lab_colors = "auto", 19 | as.table = TRUE, 20 | switch = NULL, 21 | drop = TRUE, 22 | margins = FALSE, 23 | axes = "margins", 24 | axis.labels = "all" 25 | ) 26 | 27 | facet_grid_geo( 28 | colors = stages, 29 | rows = NULL, 30 | cols = NULL, 31 | scales = "fixed", 32 | space = "fixed", 33 | shrink = TRUE, 34 | labeller = "label_value", 35 | lab_colors = "auto", 36 | as.table = TRUE, 37 | switch = NULL, 38 | drop = TRUE, 39 | margins = FALSE, 40 | axes = "margins", 41 | axis.labels = "all" 42 | ) 43 | } 44 | \arguments{ 45 | \item{colors}{Specifies which colors to use to replace the strip backgrounds. 46 | Either A) a function that returns a color for a given strip label, B) the 47 | character name of a function that does the same, C) a named character 48 | vector with names matching strip labels and values indicating the desired 49 | colors, or D) a data.frame representing a lookup table with columns named 50 | "name" (matching strip labels) and "color" (indicating desired colors). If 51 | the function returns \code{NA}, the default background color will be used.} 52 | 53 | \item{rows, cols}{A set of variables or expressions quoted by 54 | \code{\link[ggplot2:vars]{vars()}} and defining faceting groups on the rows or columns 55 | dimension. The variables can be named (the names are passed to 56 | \code{labeller}). 57 | 58 | For compatibility with the classic interface, \code{rows} can also be 59 | a formula with the rows (of the tabular display) on the LHS and 60 | the columns (of the tabular display) on the RHS; the dot in the 61 | formula is used to indicate there should be no faceting on this 62 | dimension (either row or column).} 63 | 64 | \item{scales}{Are scales shared across all facets (the default, 65 | \code{"fixed"}), or do they vary across rows (\code{"free_x"}), 66 | columns (\code{"free_y"}), or both rows and columns (\code{"free"})?} 67 | 68 | \item{space}{If \code{"fixed"}, the default, all panels have the same size. 69 | If \code{"free_y"} their height will be proportional to the length of the 70 | y scale; if \code{"free_x"} their width will be proportional to the 71 | length of the x scale; or if \code{"free"} both height and width will 72 | vary. This setting has no effect unless the appropriate scales also vary.} 73 | 74 | \item{shrink}{If \code{TRUE}, will shrink scales to fit output of 75 | statistics, not raw data. If \code{FALSE}, will be range of raw data 76 | before statistical summary.} 77 | 78 | \item{labeller}{A function that takes one data frame of labels and 79 | returns a list or data frame of character vectors. Each input 80 | column corresponds to one factor. Thus there will be more than 81 | one with \code{vars(cyl, am)}. Each output 82 | column gets displayed as one separate line in the strip 83 | label. This function should inherit from the "labeller" S3 class 84 | for compatibility with \code{\link[ggplot2:labeller]{labeller()}}. You can use different labeling 85 | functions for different kind of labels, for example use \code{\link[ggplot2:label_parsed]{label_parsed()}} for 86 | formatting facet labels. \code{\link[ggplot2:label_value]{label_value()}} is used by default, 87 | check it for more details and pointers to other options.} 88 | 89 | \item{lab_colors}{Specifies which colors to use for the strip labels. Either 90 | A) a function that returns a color for a given strip label, B) the 91 | character name of a function that does the same, C) a named character 92 | vector with names matching strip labels and values indicating the desired 93 | colors, D) a data.frame representing a lookup table with columns named 94 | "name" (matching strip labels) and "lab_color" (indicating desired colors), 95 | or E) "auto" (the default), which set the labels to black or white, 96 | whichever has better contrast with the background color, based on 97 | \href{https://www.itu.int/rec/R-REC-BT.601-7-201103-I/en}{recommendations by the International Telecommunication Union}. 98 | If the function returns \code{NA}, the default label color will be used.} 99 | 100 | \item{as.table}{If \code{TRUE}, the default, the facets are laid out like 101 | a table with highest values at the bottom-right. If \code{FALSE}, the 102 | facets are laid out like a plot with the highest value at the top-right.} 103 | 104 | \item{switch}{By default, the labels are displayed on the top and 105 | right of the plot. If \code{"x"}, the top labels will be 106 | displayed to the bottom. If \code{"y"}, the right-hand side 107 | labels will be displayed to the left. Can also be set to 108 | \code{"both"}.} 109 | 110 | \item{drop}{If \code{TRUE}, the default, all factor levels not used in the 111 | data will automatically be dropped. If \code{FALSE}, all factor levels 112 | will be shown, regardless of whether or not they appear in the data.} 113 | 114 | \item{margins}{Either a logical value or a character 115 | vector. Margins are additional facets which contain all the data 116 | for each of the possible values of the faceting variables. If 117 | \code{FALSE}, no additional facets are included (the 118 | default). If \code{TRUE}, margins are included for all faceting 119 | variables. If specified as a character vector, it is the names of 120 | variables for which margins are to be created.} 121 | 122 | \item{axes}{Determines which axes will be drawn. When \code{"margins"} 123 | (default), axes will be drawn at the exterior margins. \code{"all_x"} and 124 | \code{"all_y"} will draw the respective axes at the interior panels too, whereas 125 | \code{"all"} will draw all axes at all panels.} 126 | 127 | \item{axis.labels}{Determines whether to draw labels for interior axes when 128 | the \code{axes} argument is not \code{"margins"}. When \code{"all"} (default), all 129 | interior axes get labels. When \code{"margins"}, only the exterior axes get 130 | labels and the interior axes get none. When \code{"all_x"} or \code{"all_y"}, only 131 | draws the labels at the interior axes in the x- or y-direction 132 | respectively.} 133 | } 134 | \description{ 135 | \code{facet_grid_color} behaves similarly to \code{\link[ggplot2:facet_grid]{ggplot2::facet_grid()}} in that it 136 | forms a matrix of panels defined by row and column faceting variables. The 137 | main difference is that it also allows the user to specify the background and 138 | label colors of the individual facet strips using the \code{colors} and 139 | \code{lab_colors} arguments. If you have only one variable with many levels, try 140 | \code{\link[=facet_wrap_color]{facet_wrap_color()}}. 141 | } 142 | \details{ 143 | \code{facet_grid_geo(...)} is an alias of \code{facet_grid_color()} with the default of 144 | \code{colors} set to \code{stages}. 145 | } 146 | \examples{ 147 | library(ggplot2) 148 | df <- data.frame(x = 1:10, y = 1:10, period = c("Permian", "Triassic")) 149 | ggplot(df) + 150 | geom_point(aes(x, y)) + 151 | facet_grid_color(cols = vars(period), colors = periods) 152 | } 153 | \seealso{ 154 | Other faceting functions: 155 | \code{\link{facet_nested_color}()}, 156 | \code{\link{facet_nested_wrap_color}()}, 157 | \code{\link{facet_wrap_color}()} 158 | } 159 | \concept{faceting functions} 160 | \keyword{datasets} 161 | --------------------------------------------------------------------------------