R/gbif_photos.r

Defines functions makemapfiles pick_browser foo dirhandler gbif_photos

Documented in gbif_photos

#' View photos from GBIF.
#'
#' @importFrom whisker whisker.render
#' @export
#' @param input Input output from occ_search
#' @param output Output folder path. If not given uses temporary folder.
#' @param which One of map or table (default).
#' @param browse (logical) Browse output (default: `TRUE`)
#' @details The max number of photos you can see when which="map" is ~160,
#' so cycle through if you have more than that.
#' @section BEWARE: The maps in the table view may not show up correctly if
#' you are using RStudio
#' @examples \dontrun{
#' res <- occ_search(mediaType = 'StillImage', limit = 100)
#' gbif_photos(res)
#' gbif_photos(res, which='map')
#'
#' res <- occ_search(scientificName = "Aves", mediaType = 'StillImage',
#'   limit=150)
#' gbif_photos(res)
#' gbif_photos(res, output = '~/barfoo')
#' }

gbif_photos <- function(input, output = NULL, which='table', browse = TRUE) {
  if (!inherits(input, "gbif")) stop("input should be of class gbif")
  input <- input$media
  which <- match.arg(which, c("map", "table"))
  if (which == 'map') {
    photos <- foo(input)
    outfile <- dirhandler(output)
    filepath <- system.file("singlemaplayout.html", package = "rgbif")
    ff <- paste(readLines(filepath), collapse = "\n")
    rr <- whisker.render(ff)
    write(rr, file = outfile)
    if (browse) utils::browseURL(outfile, browser = pick_browser()) else outfile
  } else {
    if (length(input) > 20) {
      outdir <- dirhandler(output, 'dir')
      input <- split(input, ceiling(seq_along(input)/20))
      filenames <- replicate(length(input), path.expand(tempfile(fileext = ".html", tmpdir = outdir)))
      filenames <- as.list(filenames)
      links <- list()
      for (i in seq_along(filenames)) links[[i]] <- list(url = filenames[[i]], pagenum = i)

      for (i in seq_along(input)) {
        photos <- foo(input[[i]])
        mappaths <- makemapfiles(photos, outdir)
        photos <- Map(function(x,y) c(x, mappath = y), photos, mappaths)
        rendered <- whisker.render(template)
        paginated <- whisker.render(pagination)
        rendered <- paste0(rendered, paginated, footer)
        write(rendered, file = filenames[[i]])
      }

      if (browse) utils::browseURL(filenames[[1]], browser = pick_browser()) else filenames[[1]]
    } else {
      outfile <- dirhandler(output)
      outdir <- dirname(outfile)
      photos <- foo(input)
      mappaths <- makemapfiles(photos, outdir)
      photos <- Map(function(x,y) c(x, mappath = y), photos, mappaths)
      rendered <- whisker.render(template)
      rendered <- paste0(rendered, footer)
      write(rendered, file = outfile)
      if (browse) utils::browseURL(outfile, browser = pick_browser()) else outfile
    }
  }
}

dirhandler <- function(x, which="file"){
  if (is.null(x)) {
    dir <- tempdir()
    dir.create(dir, recursive = TRUE, showWarnings = FALSE)
    switch(which, file = file.path(dir, "index.html"), dir = dir)
  } else {
    if (!file.exists(x)) dir.create(x, recursive = TRUE, showWarnings = FALSE)
    switch(which, file = file.path(x, "index.html"), dir = x)
  }
}

foo <- function(x){
  photos <- lapply(x, function(y){
    y <- y[[1]]
    if (is.null(y$decimalLatitude) || is.null(y$decimalLongitude)) {
      NULL
    } else {
      tmp <- y[c('key','species','decimalLatitude','decimalLongitude','country')]
      tmp[sapply(tmp, is.null)] <- "none"
      names(tmp) <- c('key','species','decimalLatitude','decimalLongitude','country')
      list(c(tmp, y[!names(y) %in% c('key','species','decimalLatitude','decimalLongitude','country')][[1]][c(3:4)]))
    }
  })
  do.call(c, unname(rgbif_compact(photos)))
}

pick_browser <- function() {
  sysname <- Sys.info()[['sysname']]
  if (.Platform$OS.type == "windows") {
    NULL
  } else if (Sys.info()[['sysname']] == "Darwin") {
    "open"
  } else if (.Platform$OS.type == "unix") {
    "xdg-open"
  } else {
    getOption("browser")
  }
}

template <- '
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>rgbif - photos</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="View photos from GBIF query">
<meta name="author" content="ecoengine">

<link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">

</head>

<body>

<div class="container">

<center><h2>rgbif photo viewer</h2></center>

<table class="table table-striped table-hover" align="center">
<thead>
<tr>
<th>Species</th>
<th>Photo</th>
<th>Location</th>
</tr>
</thead>
<tbody>
{{#photos}}
<tr>
<td><i>{{species}}</i></td>
<td><a href="{{{references}}}"><img src="{{{identifier}}}" height="200" style="border-radius: 10px 10px 10px 10px; max-width: 400px"></a></td>
<td><iframe src="{{mappath}}" width="400" height="200" frameborder="0"></iframe></td>
</tr>
{{/photos}}
</tbody>
</table>
</div>
'

pagination <- '
<center>
  <ul class="pagination pagination-lg">
    {{#links}}
    <li><a href="{{url}}">{{pagenum}}</a></li>
    {{/links}}
  </ul>
</center>
'

footer <- '
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>

</body>
</html>'

makemapfiles <- function(x, dir){
  mapfiles <- list()
  for (i in seq_along(x)) {
    file <- path.expand(tempfile("map", tmpdir = dir, fileext = ".html"))
    mapfiles[[i]] <- file
    tmp <- whisker.render(map, data = x[[i]])
    write(tmp, file = file)
  }
  mapfiles
}

map <- '
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Single marker</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox.js/v2.4.0/mapbox.js"></script>
<link href="https://api.mapbox.com/mapbox.js/v2.4.0/mapbox.css" rel="stylesheet" />

<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>

<div id="map"></div>

<script>
L.mapbox.accessToken = "pk.eyJ1IjoicmVjb2xvZ3kiLCJhIjoiZWlta1B0WSJ9.u4w33vy6kkbvmPyGnObw7A";

var map = L.mapbox.map("map", "mapbox.streets")
    .setView([{{decimalLatitude}}, {{decimalLongitude}}], 5);

L.mapbox.featureLayer({
    type: "Feature",
    geometry: {
        type: "Point",
        coordinates: [ {{decimalLongitude}}, {{decimalLatitude}} ]
    },
    properties: {
        "title": "{{species}}",
        "marker-size": "large",
        "marker-color": "#FB8A24",
        "marker-symbol": "garden"
}
}).addTo(map);
</script>

  </body>
  </html>
'

Try the rgbif package in your browser

Any scripts or data that you put into this service are public.

rgbif documentation built on Sept. 11, 2023, 9:06 a.m.