Giter Club home page Giter Club logo

vapour's Introduction

vapour

R_build_status CRAN_Status_Badge CRAN_Download_Badge

Overview

The vapour package provides access to the basic read functions available in GDAL for both raster and vector data sources.

The functions are deliberately lower-level than these data models and provide access to the component entities independently.

For vector data:

  • read access to fields alone
  • read raw binary geometry alone, or geometry in text forms (GeoJSON, WKT, GML, KML).
  • read access to the extent of geometries
  • helper functions to summarize feature identity and geometry status
  • limit/skip control on records read
  • execution of OGRSQL with control of SQL dialect
  • read in the context of a bounding box spatial filter can be applied via the extent argument

For raster data:

  • read access to the list of available rasters within a collection source (subdatasets).
  • read access to structural metadata for individual raster sources.
  • read access for raw data using GDAL’s RasterIO framework and its dynamic image decimation / replication resampling algorithms.
  • read access for raw data using GDAL’s Warper framework and its dynamic image warping, a superset of the RasterIO capabilities.

The warper works for data sources that contain overviews (or pyramid levels-of-detail) as it automatically chooses an appropriate level for the request made, files, urls, database connections, online tiled image servers, and all the various ways of specifying GDAL data sources.

The workflows available are intended to support development of applications in R for these vector and raster data without being constrained to any particular data model.

Installation

Install from CRAN, this should work on MacOS and Windows because CRAN provide binaries.

install.packages("vapour")

The development version can be installed from Github.

options(repos = c(
    hypertidy = 'https://hypertidy.r-universe.dev',
    CRAN = 'https://cloud.r-project.org'))
install.packages("vapour")

To install the development version the more github-traditional way:

remotes::install_github("hypertidy/vapour")

You will need development tools for building R packages.

On Linux, I’m using latest ubuntu and R usually, check CRAN on ubuntu (search for “ubuntu cran”).

then

apt install --no-install-recommends software-properties-common dirmngr
add-apt-repository ppa:ubuntugis/ubuntugis-unstable --yes

apt update

## Install 3rd parties

## NetCDF and geo-spatial wunderkind
apt install libgdal-dev 

then install.packages("vapour") or whatever you use.

Purpose

The goal of vapour is to provide a basic GDAL API package for R. The key functions provide vector geometry or attributes and raster data and raster metadata.

The priority is to give low-level access to key functionality rather than comprehensive coverage of the library. The real advantage of vapour is the flexibility of a modular workflow, not the outright efficiency.

A parallel goal is to be freed from the powerful but sometimes limiting high-level data models of GDAL itself, specifically these are simple features and affine-based regular rasters composed of 2D slices. (GDAL will possibly remove these limitations over time but still there will always be value in having modularity in an ecosystem of tools.)

GDAL’s dynamic resampling of arbitrary raster windows is also very useful for interactive tools on local data, and is radically under-utilized. A quick example, topography data is available from Amazon compute servers, first we need a config for the source:

elevation.tiles.prod <- 
 '<GDAL_WMS>
  <Service name="TMS">
    <ServerUrl>https://s3.amazonaws.com/elevation-tiles-prod/geotiff/${z}/${x}/${y}.tif</ServerUrl>
  </Service>
  <DataWindow>
    <UpperLeftX>-20037508.34</UpperLeftX>
    <UpperLeftY>20037508.34</UpperLeftY>
    <LowerRightX>20037508.34</LowerRightX>
    <LowerRightY>-20037508.34</LowerRightY>
    <TileLevel>14</TileLevel>
    <TileCountX>1</TileCountX>
    <TileCountY>1</TileCountY>
    <YOrigin>top</YOrigin>
  </DataWindow>
  <Projection>EPSG:3857</Projection>
  <BlockSizeX>512</BlockSizeX>
  <BlockSizeY>512</BlockSizeY>
  <BandsCount>1</BandsCount>
  <DataType>Int16</DataType>
  <ZeroBlockHttpCodes>403,404</ZeroBlockHttpCodes>
  <DataValues>
    <NoData>-32768</NoData>
  </DataValues>
  <Cache/>
</GDAL_WMS>'
## we want an extent
ex <- c(-1, 1, -1, 1) * 5000  ## 10km wide/high region
## Madrid is at this location
pt <- cbind(-3.716667, 40.416667)
crs <- sprintf("+proj=laea +lon_0=%f +lat_0=%f +datum=WGS84", pt[1,1,drop = TRUE], pt[1,2, drop = TRUE])
dm <- c(256, 256)


vals <- vapour::vapour_warp_raster(elevation.tiles.prod, extent = ex, dimension = dm, projection = crs)
## now we can use this in a matrix
image(m <- matrix(vals[[1]], nrow = dm[2], ncol = dm[1])[,dm[2]:1 ])

## using the image list format
x <- list(x = seq(ex[1], ex[2], length.out = dm[1] + 1), y = seq(ex[3] ,ex[4], length.out = dm[1] + 1), z = m)
image(x)

## or as a spatial object
library(terra)
#> terra 1.7.23
r <- rast(ext(ex), nrows = dm[2], ncols = dm[1], crs = crs, vals = vals[[1]])
contour(r, add = TRUE)

If we want more detail, go ahead:

dm <- c(512, 512)
vals <- vapour::vapour_warp_raster(elevation.tiles.prod, extent = ex, dimension = dm, projection = crs)
(r <- rast(ext(ex), nrows = dm[2], ncols = dm[1], crs = crs, vals = vals[[1]]))
#> class       : SpatRaster 
#> dimensions  : 512, 512, 1  (nrow, ncol, nlyr)
#> resolution  : 19.53125, 19.53125  (x, y)
#> extent      : -5000, 5000, -5000, 5000  (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=laea +lat_0=40.416667 +lon_0=-3.716667 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs 
#> source(s)   : memory
#> name        : lyr.1 
#> min value   :   562 
#> max value   :   742
plot(r, col = hcl.colors(24))

GDAL is obstinately format agnostic, the A stands for Abstraction and we like that in R too, just gives us the data. Here we created a base matrix image object, and a raster package RasterLayer, but we could use the spatstat im, or objects in stars or terra packages, it makes no difference to the read-through-warp process.

This partly draws on work done in the sf package and the terra package and in packages rgdal and rgdal2. I’m amazed that something as powerful and general as GDAL is still only available through these lenses, but maybe more folks will get interested over time.

Examples

The package documentation page gives an overview of available functions.

help("vapour-package")

See the vignettes and documentation for examples WIP.

Context

Examples of packages that use vapour are in development, especially whatarelief and ggdal.

Limitations, work-in-progress and other discussion:

#4

We’ve kept a record of a minimal GDAL wrapper package here:

https://github.com/diminutive/gdalmin

Code of conduct

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

vapour's People

Contributors

jeroen avatar jsta avatar kalibera avatar mdsumner avatar mpadge avatar olivroy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

vapour's Issues

CRAN plan

I think we've learnt enough to put out a bare bones release. The key C++ functionality to wrap is these, either as slightly overlapping implementations or as building blocks:

  • open and read from data source (return a minimal summary)
  • execute SQL against data source, or pass in an index for features to read
  • read the attributes only
  • read the geometry only (in an optional format)
  • read the geometry bounds only

Focus on just these features as a minimal core since we can build higher-level collections and descriptions of multiple data sources from these components

These functions

  • vapour_read_attributes - a list of column vectors
  • vapour_read_geometry - a list of native blobs
  • vapour_read_geometry_text - a vector of JSON, WKT, KML, or GML
  • vapour_read_extent - a list of extent vectors

Each function is standalone, opening and closing the data source, defaulting to the 0-th layer and only accepting a layer index, optionally executing a SQL string, and ignoring the layer index if sql is given.

attributes

This all has to be revisited

  • report on underlying type (not the R interpretation)
  • read long vectors
  • control over conversion to R

virtual file system

A VSIReadDirEx example thanks to @obrl-soil

remotes::install_github("hypertidy/vapour@VSI_list")
u <- "/vsizip//vsicurl/http://dapds00.nci.org.au/thredds/fileServer/rr2/national_geophysical_compilations/http/radmap_v3_2015_filtered_dose/radmap_v3_2015_filtered_dose.ers.zip"
vapour:::VSI_list(u)

[1] "radmap_v3_2015_filtered_dose"     "radmap_v3_2015_filtered_dose.ers"
[3] "radmap_v3_2015_filtered_dose.isi" "radmap_v3_2015_filtered_dose.txt"

Doc is here: https://www.gdal.org/gdal_virtual_file_systems.html

Discussed on twitter: https://twitter.com/obrl_soil/status/1087674550198820864

would be good to flesh this out a bit more, and get some functionality of gdal_ls.py in R.

default window?

Should raster_io build the right default window?

Options:

  • build the window and print it out, but stop
  • allow a native = FALSE arg, if set to TRUE it reads the window (does it override the input window?)
  • allow a c(ox, oy, srcx, srcy) usage and set c(ox, oy, srcx, srcy, srcx, srcy) as a default helper
  • default to c(0, 0, srcx, srcy, 10, 10) ?

Currently window is not optional, it must be passed in. Probably best to write more functions that wrap raster_io, though it's likely most of them won't get used much. The extent, resolution, native, and max-size are the likely candidates

  • rio_dim - provide the entire window with a given dimension output
  • rio_ext - provide native data within an extent
  • rio_res - ??

add limit_n helpers

Read n attribute rows, or n geometries in sequence and add helper for "has geometry".

## this can't work yet because of the fid_select sleight of hand, 
## so needs to catch that issue earlier and return infor
vapour_has_geometry <- function(dsource, layer = 0L) {
  ## convert from character layer to integer if required
  if (!is.numeric(layer)) layer <- index_layer(dsource, layer)
  sql <- sprintf("SELECT Geom FROM %s LIMIT %i", 
                 vapour_layer_names(dsource)[layer + 1], 
                 1L)
  err <- try(vapour_read_geometry(dsource, layer = layer, sql = sql), silent = TRUE)
  !inherits(err, "try-error")
}


#' Read n features from a layer. 
#' 
#' Uses OGRSQL, which could be fragile depending on the layer name quoting required. 
#' @inheritParams vapour_read_attributes
vapour_read_limit_n <- function(dsource, layer = 0L, limit = 1L) {
  ## convert from character layer to integer if required
  if (!is.numeric(layer)) layer <- index_layer(dsource, layer)
  sql <- sprintf("SELECT * FROM %s LIMIT %i", 
                 vapour_layer_names(dsource)[layer + 1], 
                 as.integer(limit))
  as.data.frame(vapour_read_attributes(mvfile, 
                         sql = sql), stringsAsFactors = FALSE)
}

library(vapour)
file <- "list_locality_postcode_meander_valley.tab"
mvfile <- system.file(file.path("extdata/tab", file), package="vapour")

vapour_read_limit_n(mvfile)

more raster info

  • include subdataset count and indication of which one was chosen (might not make sense given the sds wrapping?)
  • all the band metadata ...
  • existence of overviews
  • band type
  • RATs

barebones shared dataset

Use rgdal2 as a basic model, though there's no need for the rgdal2.h templating now with XPtr.

https://github.com/thk686/rgdal2

Also these:

http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2014-December/008254.html

// http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2015-June/008818.html

// HELP: I can't see how to XPtr<T> this function so that I can re-use it in another
// function, is the XPtr<GDALDataset> somehow special or is it that I have to declare
// that template more broadly (how?)

// [[Rcpp::export]]
SEXP vapour_GDAL_open(CharacterVector filename,
                      LogicalVector readonly) {
  GDALAllRegister();

  Rprintf(filename[0]);
  GDALAccess access = readonly ? GA_ReadOnly : GA_Update;
  //poDataset = (GDALDataset *) GDALOpen( filename[0], GA_ReadOnly );
  XPtr<GDALDataset>  gdaldataset((GDALDataset *)GDALOpen(filename[0], access));
  return gdaldataset;
}

OGRSQL examples

Various things to explore, discuss ...

mvfile <- system.file(file.path("extdata/tab", file), package="vapour")
layer <- gsub(".tab$", "", basename(mvfile))
## get the number of features by FID (DISTINCT should be redundant here)
vapour_read_attributes(mvfile, sql = sprintf("SELECT COUNT(DISTINCT FID) AS nfeatures FROM %s", layer))

## note how TAB is 1-based 
vapour_read_attributes(mvfile, sql = sprintf("SELECT COUNT(*) AS n FROM %s WHERE FID < 2", layer))
#$n
#[1] 1

## but SHP is 0-based
shp <- system.file("shape/nc.shp", package="sf")
vapour_read_attributes(shp, sql = sprintf("SELECT COUNT(*) AS n FROM %s WHERE FID < 2", "nc"))
#$n
#[1] 2

match FID facility

We need to be able to loop over features and only keep those that match an input set of FIDS from vapour_read_names, alternatively a sequential integer set

clarify names

clarify the old sql behaviour, we can remove the warning when FID gets inserted

hellish bug

The read_geometry_text examples include a direct path to inst/filename.something, and I think this causes a total lock up in RStudio - I've had to soft reboot each time with check, and just running examples.

Don't do that in examples ...

dimXY is wrong for L1b

Using this file NSS.GHRR.ND.D94182.S1520.E1650.B1625960.GC

I get RasterXSize of 51, which is the standard pixel count of the GCPs, not the XSize which is 409.

Use poDataSet->GetRasterXSize() rather than the size of the first band ...

get control points

Add to the vapour_raster_info output, for use in targetting scenes in L1B.

read extent behaviour for missing geometry

for a missing geometry, we get c(0, 0, 0, 0) but if all are missing we get a list of NULL

Can use this for summarizing the geometry-state, but the 0s should be NAs, or a NULL.

non-file sources

We need these to work

DAP/Thredds

u <- "http://rs-data1-mel.csiro.au/thredds/dodsC/imos-srs/sst/ghrsst/L3S-3d/ngt/2018/20180404152000-ABOM-L3S_GHRSST-SSTskin-AVHRR_D-3d_night-v02.0-fv01.0.nc"


 u <- "http://coastwatch.pfeg.noaa.gov/erddap/griddap/erdQSwind3day"

count geometries

To replace the geometry part of #35

  • write fun like vapour_read_geometry_cpp to simply count the non-null geometries, and record the total count
  • include a stop_if_any_valid and stop_if_any_null option
  • wrap this to provide various metrics

interface for gdalwarp with -geoloc

This works great for L1B, which has in-built geolocation arrays that present as GCPs:

## local stere projection grid overlapping  near Mawson station
## GCdata/NSS.GHRR.ND.D94182.S1520.E1650.B1625960.GC

## template %s are input and output
gdalwarp %s %s -geoloc -r bilinear \
-te -1157398.178974 -1276821.259254 1158383.248024 \ 1277541.239696 -tr 1000 1000 \
 -t_srs '+proj=stere +lon_0=64.000000 +lat_0=-66.000000 +lat_ts=-71 +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0'

Wrap the logic up to call GDAL directly on the file, extract the geoloc and apply the warping based on a raster input grid.

Bonus points:

  • detect that there's no overlap
  • figure out the Snyder satellite projection params and use as the target rather than an input
  • input a longlat bbox and generate the image for a local area in longlat
  • optionally clean up the extent to be whole grain on a given res
  • allow band selection

examples of queries (for sf)

manifold

vapour_layer_names("ODBC:manifold8")
#[1] "Drawing Table" "Table"    

## this CRASHES R presumably because of "Geom (I)"? 
#vapour_read_attributes("ODBC:manifold8", sql = "SELECT * FROM [Drawing Table]")

## ok
 vapour_read_attributes("ODBC:manifold8", sql = "SELECT * FROM [Table]")
#$`Column`
#[1] 1 4

#$`Column 2`
#[1] 2 3

now sf

 st_layers("ODBC:manifold8")
Driver: ODBC 
Available layers:
     layer_name geometry_type features fields
1 Drawing Table                      0     15
2         Table                      0      2
Warning messages:
1: In CPL_get_layers(dsn, options, do_count) :
  GDAL Error 1: GetFeatureCount() failed on query SELECT COUNT(*) FROM Drawing Table.
Unexpected token 'Drawing' at line 1.
2: In CPL_get_layers(dsn, options, do_count) :
  GDAL Error 1: GetFeatureCount() failed on query SELECT COUNT(*) FROM Table.
Unexpected token 'Table' at line 1.
> 


read_sf("ODBC:manifold8", "Table")
Simple feature collection with 0 features and 2 fields
bbox:           xmin: NA ymin: NA xmax: NA ymax: NA
epsg (SRID):    NA
proj4string:    NA
# A tibble: 0 x 3
# ... with 3 variables: Column <int>, `Column 2` <int>, geometry <GEOMETRY>
Warning message:
In CPL_read_ogr(dsn, layer, query, as.character(options), quiet,  :
  GDAL Error 1: GetFeatureCount() failed on query SELECT COUNT(*) FROM Table.
Unexpected token 'Table' at line 1.

complete deprecation of vapour_read_geometry_cpp

Even though message is "vapour_read_feature_what is deprecated. Use 'vapour_read_geometry_cpp' instead", my previous concerns still abide that enabling direct calls to _cpp fns ought not be done. I'm not sure which should be deprecated here, but something, right?

Install error: object 'f' not found

I'm having difficulty running install_github on master. During compilation I see:

...
** tests
** byte-compile and prepare package for lazy loading
Error in structure(list(source = x, info = raster_info(x)), class = "ssraster") :
object 'f' not found
...

Error reading over symlink

Do you have any idea why vapour (and gdalUtils) fails to read from a symlink but system("ogrinfo") and sf::st_layers works?

some index-prototypes

first is a sp object with the spex bbox of every polygon

library(vapour)
file <- (system.file("shape/nc.shp", package="sf"))
library(dplyr)
file <- raadfiles:::get_raw_raad_filenames() %>%
  dplyr::filter(grepl("TASVEG", file, ignore.case = TRUE))
file <- ".../tas.gov.au/TASVEG/GDB/TASVEG3.gdb"

read_extent <- function(x, layer = 1L, ...) {
  layers <- vapour::vapour_layer_names(x)
  if (is.numeric(layer)) one_layer <- layers[layer]
  if (is.character(layer)) one_layer <- layer
if (!one_layer %in% layers) warning("layer not found!")
  out <- do.call(rbind, purrr::map(vapour::vapour_read_extent(x),
         ~spex::spex(raster::extent(.x), crs = "+init=epsg:4326")))
  out$dsn <- x
  fids <- as.integer(seq_len(dim(out)[1L]))
  out$sql <- sprintf("SELECT * FROM %s WHERE FID = %i", one_layer,
                     fids)
  out$fid <- fids
  out$layer <- one_layer
  out
}
system.time(x <- read_extent(file))
# user   system  elapsed 
# 2283.033   29.665 2312.259 
# > pryr::object_size(x)
# 922 MB
# > length(x)
# [1] 463954

This is simplistic, but nice since we can use directly in mapedit and call back to the source to read in those geometries:

ind <- mapedit::selectFeatures(x)
y <- purrr::map(ind$sql, ~vapour::vapour_read_geometry(file, sql = .x))

The second is super fast, we get an sf POLYGON of every bounding box within seconds.

## vs 6seconds
system.time(e <- vapour_read_extent(file))
dummy <- sf::st_as_sfc(spex::spex(raster::extent(e[[1]]), crs = NA_character_))
f <- function(x) {out <- dummy; 
                  out[[1]][[1]] <- matrix(x[c(1, 1, 2, 2, 1, 
                                       3, 4, 4, 3, 3)], ncol = 2); 
                  attr(out, "bbox") <- structure(setNames(x[c(1, 3,2, 4)], c("xmin", "ymin", "xmax", "ymax")), class = "bbox")
                  out}

## very fast to build the sf index to this huge GDB
bblist <- do.call(c, purrr::map(e, f))

MacOS test

I'm looking for assistance to see that install on MacOS will work.

If you have a chance to try installing vapour on Apple machines that would be really helpful, let me know how you go!

The sf package has the following prerequisites (and these would be more or less the same requirement for vapour):

brew unlink gdal
brew tap osgeo/osgeo4mac && brew tap --repair
brew install proj
brew install geos

brew install gdal2 --with-armadillo --with-complete --with-libkml --with-unsupported
brew link --force gdal2

If that works, please try the following to install vapour:

devtools::install_github("hypertidy/vapour")

Options

The line brew install geos can probably be ignored.

resample options args

Process the input resample arg to be lowercase for comparison, so that we can have "Gauss" or "gauss", and "Cubicspline" or "CubicSpline"

sql/layer simplification?

Fooling around with this got me thinking:

conn <- dplyr::src_sqlite(system.file("gpkg/nc.gpkg", package = "sf"))$con
st_read(conn, query = "SELECT geom AS geometry  FROM 'nc.gpkg'")

## otherwise 
dplyr::src_sqlite(conn, "nc.gpkg")

Because, why not try executing the layer argument as SQL if it's not an existing layer in the DSN?

All the functions have layer , sql arguments except for vapour_layer_names which only has sql, so I think this can work. Logic is

  • is it a number? (is it within range of the number of layers, watch out for factors)
  • is it an existing layer? (ignore case)
  • does it start with "SELECT " - we are read-only

Fixes for 0.2.0

Execution haltedchecking Rd \usage sections ... WARNING
Undocumented arguments in documentation object 'vapour_gdal_version'
‘dsource’

Also OSM test fails on skip_n, spurious message needs more care

32-bit signed bound on 64-bit unsigned type

Please fix from CRAN

We see (gcc 8)

sds_io.cpp: In function ‘Rcpp::CharacterVector sds_info_cpp(const char*)’:
sds_io.cpp:48:28: warning: comparison of integer expressions of 
different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ 
[-Wsign-compare]
      for (size_t ii = 0; ii < dscount; ii++) {
                          ~~~^~~~~~~~~
I don't see why you picked a 64-bit unsigned type with a 32-bit signed 
bound but if int does not suffice to enumerate them, this needs revision.

Follow-up Q: is this code copied from GDAL itself?

VRT sql problem

This isn't a vapour issue, but it'd be good to know what the solution is - some obscure escape syntax?

vrtemplate <- function() {
  '<OGRVRTDataSource>
 <OGRVRTLayer name="nc.gpkg">
  <SrcDataSource>%s</SrcDataSource>
  <SrcSQL>%s</SrcSQL>
  </OGRVRTLayer>
  </OGRVRTDataSource>'
}

updateVRT <- function(dsn, sql) {
  sprintf(vrtemplate(), dsn, sql)
  
} 
write_vrt_tmp <- function(x) {
  tmp <- sprintf("%s.vrt", tempfile())
  writeLines(x, tmp)
  tmp
}

this works

library(sf)
f <- system.file("gpkg/nc.gpkg", package = "sf")
## st_layers(f)
## must quote a layer name like "nc.gpkg"
tmp <- write_vrt_tmp(updateVRT(f, "SELECT * FROM 'nc.gpkg' WHERE AREA > 0.15"))
read_sf(tmp)
## this works
vapour_read_attributes(f, sql = "SELECT NAME FROM 'nc.gpkg' WHERE AREA < 0.15")

But, try < in VRT and fail

tmp <- write_vrt_tmp(updateVRT(f, "SELECT * FROM 'nc.gpkg' WHERE AREA < 0.15"))
read_sf(tmp)
#Cannot open data source /tmp/RtmpY5ksju/file614e257431d5.vrt
#Error in CPL_read_ogr(dsn, layer, as.character(options), quiet, type,  : 
#  Open failed.
#In addition: Warning message:
#In CPL_read_ogr(dsn, layer, as.character(options), quiet, type,  :
# GDAL Error 1: Line 3: Didn't find expected '=' for value of attribute '<'.

demand-detail plot

This is a raw example using raster_io to read just the level-of-detail required for a requested plot.

#' Plot GDAL matrix.
#'
#' Plot a matrix directly read via GDAL to match the current device size.
#'
#' The data is read in at the resolution required by the current device, assuming it's a single
#' panel.  TODO: read off the space to plot into from the device, and
#' read only that window from the source at the right resolution.
#' @param filename source
#' @param add add to the plot
#' @importFrom vapour raster_io raster_info
#' @export
#' @examples
#' ## this file takes 5s to read in total from NetCDF, 24 seconds via GDAL
#' filename <- "/rdsi/PRIVATE/raad/data_local/www.bodc.ac.uk/gebco/GRIDONE_2D.nc"
#' #filename <- raadtools::topofile()
#' #filename <- "D:/data/topography/etopo2/subset.tif"
#' library(vapour)
#' ## read in to match the device and it's quicker
#' plot_raster(filename)
#' #zoom(wrld_simpl, new = FALSE)
#' #plot_raster(filename, ext = spex::spex(), add = T, col = rainbow(100))
#' #maps::map(add = TRUE)
#' ## library(sf); plot(st_transform(sst_c, 4326), add = T)
#' ##for (i in sample(seq_len(nrow(wrld_simpl)))) {plot_raster(filename, ext = raster::extent(wrld_simpl[i, ])); plot(wrld_simpl[i, ], add = TRUE)}
plot_raster <- function(filename, add = FALSE, ext = NULL, cols = NULL) {
  ri <- vapour::raster_info(filename)
  xlim <- ri$geotransform[1]
  xlim <- c(xlim[1], xlim[1] + ri$dimXY[1] * ri$geotransform[2])
  ylim <- ri$geotransform[4]
  ylim <- c(ylim[1] + ri$dimXY[2] * ri$geotransform[6], ylim)
  flip <- function(x) x[,ncol(x):1]
  brks <- seq(ri$minmax[1], ri$minmax[2], length = 100)
  cols <- if (is.null(cols))  viridis::viridis(99) else  colorRampPalette(cols)(length(brks)-1)

  dv <- dev.size("px")
  rlocal <- raster::raster(raster::extent(xlim, ylim), nrow= ri$dimXY[2], ncol = ri$dimXY[1])
  window <- c(0, 0, ri$dimXY)
  if (!is.null(ext)) {
    ## this index is Y-up
    index  <- spex:::as_double(tabularaster::index_extent(rlocal, ext))
    indexYdown <- c(index[1:2], nrow(rlocal) - index[4:3])
    window <- c(indexYdown[1], indexYdown[3],
                indexYdown[2] - indexYdown[1], indexYdown[4] - indexYdown[3])
    rlocal <- raster::crop(rlocal, ext, snap = "out")
  }

  z <- flip(matrix(raster_io(filename, c(window, dv[1], dv[2])), dv[1]))

  dim(rlocal) <- rev(dim(z))
  l <- list(x = raster::xFromCol(rlocal),
            y = rev(raster::yFromRow(rlocal)),
            z = z)
  if(!add && dev.cur() == 1) {
    print(add)
    add <- TRUE
    par(mar = rep(0, 4))
    plot(xlim, ylim, type = "n", xaxs = "i", yaxs = "i")
  }

  image(l, useRaster = TRUE,
        col = cols, breaks = brks, add = add)

}

rename raster_io

I think this name is a problem because vapour::raster_io is readonly (RasterIO is obvsly rw), and possible confusion with the rasterio python package.

vapour_read_* and raster_* is also a bit annoying, it's only because vapour started as being only about vector sources.

maybe we can do

  • vapour_sds_names (replace _sds_info, analogous to _layer_names)
  • vapour_read_raster (replace raster_io, analogous to _read_geometry) - or _read_band
  • vapour_raster_info (replace raster_info)

And then we also need a vapour_layer_info to complete the set, and this is how we'd get the CRS for the vector layer, the attribute names and types (good for DBI, and whatever other md is there).

Then we still have this annoying vapour_ prefix, but at least it's consistent and we can change simply.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.