Skip to content

Commit 10c92ef

Browse files
authored
Merge pull request #16 from Permian-Global-Research/new-reticulate
New reticulate
2 parents 81ebdf2 + 76d70f9 commit 10c92ef

23 files changed

+459
-366
lines changed

.Rbuildignore

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
^air.toml$
88
^example-data$
99
^data-raw$
10+
^\.github$

.github/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.html

.github/workflows/R-CMD-check.yaml

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
8+
name: R-CMD-check.yaml
9+
10+
permissions: read-all
11+
12+
jobs:
13+
R-CMD-check:
14+
runs-on: ${{ matrix.config.os }}
15+
16+
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
17+
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
config:
22+
- {os: macos-latest, r: 'release'}
23+
- {os: windows-latest, r: 'release'}
24+
- {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
25+
- {os: ubuntu-latest, r: 'release'}
26+
- {os: ubuntu-latest, r: 'oldrel-1'}
27+
28+
env:
29+
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
30+
R_KEEP_PKG_SOURCE: yes
31+
32+
steps:
33+
- uses: actions/checkout@v4
34+
35+
- uses: r-lib/actions/setup-pandoc@v2
36+
37+
- uses: r-lib/actions/setup-r@v2
38+
with:
39+
r-version: ${{ matrix.config.r }}
40+
http-user-agent: ${{ matrix.config.http-user-agent }}
41+
use-public-rspm: true
42+
43+
- uses: r-lib/actions/setup-r-dependencies@v2
44+
with:
45+
extra-packages: any::rcmdcheck
46+
needs: check
47+
48+
- uses: r-lib/actions/check-r-package@v2
49+
with:
50+
upload-snapshots: true
51+
build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'

DESCRIPTION

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: vrtility
22
Title: Expermimental package for efficient raster processing with GDAL VRTs
3-
Version: 0.0.1.3
3+
Version: 0.0.1.4
44
Authors@R:
55
person("Hugh", "Graham", , "hugh.graham@permianglobal.com", role = c("aut", "cre"),
66
comment = c(ORCID = "0000-0001-9451-5010"))
@@ -19,7 +19,7 @@ Imports:
1919
httr,
2020
lubridate,
2121
purrr,
22-
reticulate,
22+
reticulate (>= 1.41.0.1),
2323
rlang,
2424
rstac,
2525
scales,

NAMESPACE

+3-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ S3method(vrt_collect,doc_items)
1212
S3method(vrt_compute,default)
1313
S3method(vrt_compute,vrt_block)
1414
S3method(vrt_compute,vrt_collection)
15+
S3method(vrt_compute,vrt_stack)
1516
S3method(vrt_compute,vrt_stack_warped)
1617
S3method(vrt_set_maskfun,default)
1718
S3method(vrt_set_maskfun,vrt_block)
@@ -23,19 +24,17 @@ S3method(vrt_stack,vrt_collection)
2324
S3method(vrt_warp,vrt_block)
2425
S3method(vrt_warp,vrt_collection)
2526
export(bbox_to_projected)
26-
export(bbox_to_wkt)
2727
export(bitmask_numba)
2828
export(bitmask_numpy)
29-
export(build_vrtility_python)
3029
export(median_numba)
3130
export(median_numpy)
3231
export(plot_raster_src)
3332
export(save_vrt)
3433
export(sentinel2_stac_query)
34+
export(set_py_env_vals)
3535
export(sign_planetary_computer)
3636
export(stac_query)
3737
export(to_wkt)
38-
export(validate_bbox)
3938
export(vrt_cache_destroy)
4039
export(vrt_cache_set)
4140
export(vrt_collect)
@@ -45,4 +44,4 @@ export(vrt_set_maskfun)
4544
export(vrt_set_pixelfun)
4645
export(vrt_stack)
4746
export(vrt_warp)
48-
export(vrtility_python_pkg_install)
47+
export(vrtility_py_require)

R/cache-mgmt.R

+13
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,16 @@ vrt_cache_destroy <- function() {
9999

100100
invisible()
101101
}
102+
103+
#' onload cache checks
104+
#' @noRd
105+
#' @keywords internal
106+
cache_init_checks <- function() {
107+
op <- options()
108+
op_vrtility <- list(
109+
vrt.cache = tempdir()
110+
)
111+
112+
toset <- !(names(op_vrtility) %in% names(op))
113+
if (any(toset)) options(op_vrtility[toset])
114+
}

R/env-mgmt.R

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ compute_with_py_env <- function(
99

1010
if (is.na(py_bin)) {
1111
cli::cli_abort(c(
12-
"Cannot locate the {cli::style_bold('VRTILITY_PYTHON')} environment",
12+
"Cannot locate an appropriate python environment",
1313
"i" = "You may need to run
14-
{cli::code_highlight('`build_vrtility_python()`')} to install it"
14+
{cli::code_highlight('`vrtility_py_require()`')} to install it"
1515
))
1616
}
1717

R/gdal-options.R

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#' gdal .onLoad options
2+
#' @noRd
3+
#' @keywords internal
4+
#' @details Creates two sets of options:
5+
#' `vrt.gdal.config.options` and `vrt.gdal.warp.options`
6+
gdal_init_opts <- function() {
7+
gdal_config_opts <- c(
8+
# Enable Python this is required for vrtility pixel functions
9+
GDAL_VRT_ENABLE_PYTHON = "YES",
10+
# cache related
11+
VSI_CACHE = "TRUE",
12+
GDAL_CACHEMAX = "50%",
13+
VSI_CACHE_SIZE = "25000000", # Increase cache size
14+
# CPL_VSIL_CURL_CHUNK_SIZE = "262144",
15+
# CPL_VSIL_CURL_CACHE_SIZE = "33554432",
16+
17+
# Optimize HTTP connections
18+
GDAL_HTTP_MAX_RETRY = "5",
19+
GDAL_HTTP_RETRY_DELAY = "3",
20+
GDAL_HTTP_MULTIPLEX = "YES",
21+
CPL_VSIL_CURL_ALLOWED_EXTENSIONS = ".tif .TIF",
22+
CPL_VSIL_CURL_USE_HEAD = "NO",
23+
24+
# General options
25+
GDAL_DISABLE_READDIR_ON_OPEN = "EMPTY_DIR",
26+
GDAL_MAX_DATASET_POOL_SIZE = "500",
27+
GDAL_INGESTED_BYTES_AT_OPEN = "32000",
28+
GDAL_HTTP_VERSION = "2",
29+
GDAL_HTTP_MERGE_CONSECUTIVE_RANGES = "YES",
30+
GDAL_NUM_THREADS = "ALL_CPUS"
31+
)
32+
33+
gdal_warp_opts <- c(
34+
# Resampling
35+
"-r",
36+
"near",
37+
38+
# Compression options
39+
"-co",
40+
"COMPRESS=LZW", # CHANGED: Often faster than DEFLATE for many datasets
41+
"-co",
42+
"PREDICTOR=2",
43+
"-co",
44+
"NUM_THREADS=ALL_CPUS",
45+
"-co",
46+
"BIGTIFF=YES",
47+
48+
# Tiling options - optimized for COGs
49+
"-co",
50+
"TILED=YES",
51+
"-co",
52+
"BLOCKXSIZE=256",
53+
"-co",
54+
"BLOCKYSIZE=256",
55+
"-co",
56+
"COPY_SRC_OVERVIEWS=YES",
57+
58+
# Memory and threading options
59+
"-wm",
60+
"50%",
61+
"-multi",
62+
# "-wo",
63+
# "NUM_THREADS=ALL_CPUS",
64+
65+
# Overview options
66+
"-ovr",
67+
"AUTO"
68+
)
69+
70+
op <- options()
71+
op_gdal <- list(
72+
vrt.gdal.config.options = gdal_config_opts,
73+
vrt.gdal.warp.options = gdal_warp_opts
74+
)
75+
76+
toset <- !(names(op_gdal) %in% names(op))
77+
if (any(toset)) options(op_gdal[toset])
78+
}

R/package.R

+50-116
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,53 @@
1-
#' GDAL VRT utilities for R
1+
#' @title vrtility: GDAL VRT utilities for R
2+
#'
3+
#' @description vrtility is a package for building raster (primarily remote sensing)
4+
#' processing pipelines. It makes use of GDAL's VRT (virtual raster format)
5+
#' capabilities for efficient processing of large raster datasets. This
6+
#' package's primary focus is on the use of GDAL VRT pixel functions. These
7+
#' pixel functions (currently implemented with python) are used to apply
8+
#' cloud masks and summarise pixel values (e.g. median) from multiple images
9+
#' (i.e create a composite image). We hope to add C++ or expression based
10+
#' pixel functions in time.
11+
#' @section Spatial helpers:
12+
#' \describe{
13+
#' \item{\code{\link{bbox_to_projected}}}{Convert a long/lat bounding box to a projected bounding box}
14+
#' \item{\code{\link{to_wkt}}}{Get a wkt string from a numeric epsg code or character such as a proj4 string}
15+
#' }
16+
#' @section STAC helpers:
17+
#' \describe{
18+
#' \item{\code{\link{stac_query}}}{Query a STAC catalog}
19+
#' \item{\code{\link{sentinel2_stac_query}}}{Query a STAC catalog for Sentinel-2 data}
20+
#' \item{\code{\link{sign_planetary_computer}}}{Sign a URL for the Planetary Computer}
21+
#' }
22+
#' @section VRT utilities:
23+
#' \describe{
24+
#' \item{\code{\link{vrt_collect}}}{Create a vrt_collection object}
25+
#' \item{\code{\link{vrt_set_maskfun}}}{Set a mask function for a vrt object}
26+
#' \item{\code{\link{vrt_stack}}}{Create a vrt_stack object}
27+
#' \item{\code{\link{vrt_set_pixelfun}}}{Set a pixel function for a vrt stack object}
28+
#' \item{\code{\link{vrt_warp}}}{Warp a vrt_x object to a warped vrt}
29+
#' \item{\code{\link{vrt_compute}}}{Compute a vrt pipeline (using GDAL)}
30+
#' }
31+
#' @section VRT pixel functions:
32+
#' \describe{
33+
#' \item{\code{\link{vrt_set_pixelfun}}}{Set a pixel function for a vrt stack object}
34+
#' \item{\code{\link{bitmask_numba}}}{A pixel function to apply a bitmask}
35+
#' \item{\code{\link{bitmask_numpy}}}{A pixel function to compute the median}
36+
#' \item{\code{\link{median_numba}}}{A pixel function to compute the median}
37+
#' \item{\code{\link{median_numpy}}}{A pixel function to compute the median}
38+
#' }
39+
#' @section python environment helpers:
40+
#' \describe{
41+
#' \item{\code{\link{vrtility_py_require}}}{Require a python package}
42+
#' \item{\code{\link{set_py_env_vals}}}{Set python environment variables as options}
43+
#' }
44+
#' @section VRT helpers:
45+
#' \describe{
46+
#' \item{\code{\link{save_vrt}}}{Save a VRT object to a file}
47+
#' \item{\code{\link{vrt_schema}}}{(data object)The official GDAL VRT schema as a character object}
48+
#' }
49+
#'
250
#'
3-
#' THE GDAL VRT (Virtual Format) is an extremely powerful tool for combining
4-
#' and manipulating raster data. This package provides a set of utilities
5-
#' for working with VRTs in R. It is primarily focussed on harnessing the
6-
#' power of VRT pixel functions to carry out complex raster operations. This
7-
#' is achieved through the use of python and in particular the numba library
8-
#' which allows for the creation of fast, compiled functions that can be
9-
#' used in the VRT. All very much a work in progress...
1051
#'
1152
#' @docType package
1253
#' @aliases vrtility-package
@@ -15,114 +56,7 @@
1556

1657

1758
.onLoad <- function(libname, pkgname) {
18-
python_init_checks()
59+
vrtility_py_require(c("numpy", "numba"))
1960
cache_init_checks()
2061
gdal_init_opts()
2162
}
22-
23-
python_init_checks <- function() {
24-
vrtility_python <- Sys.getenv("VRTILITY_PYTHON", unset = NA)
25-
26-
if (!is.na(vrtility_python)) {
27-
reticulate::use_virtualenv(vrtility_python, required = TRUE)
28-
set_py_env_vals(vrtility_python)
29-
} else {
30-
if (reticulate::virtualenv_exists("vrtilitypy")) {
31-
reticulate::use_virtualenv("vrtilitypy", required = TRUE)
32-
set_py_env_vals("vrtilitypy")
33-
} else {
34-
cli::cli_inform(
35-
c(
36-
"!" = "Cannot locate the {cli::style_bold('VRTILITY_PYTHON')} environment",
37-
"i" = "Run {cli::code_highlight('`build_vrtility_python()`')} to install it"
38-
),
39-
class = "packageStartupMessage"
40-
)
41-
}
42-
}
43-
}
44-
45-
cache_init_checks <- function() {
46-
op <- options()
47-
op_vrtility <- list(
48-
vrt.cache = tempdir()
49-
)
50-
51-
toset <- !(names(op_vrtility) %in% names(op))
52-
if (any(toset)) options(op_vrtility[toset])
53-
}
54-
55-
gdal_init_opts <- function() {
56-
gdal_config_opts <- c(
57-
# Existing good settings
58-
GDAL_VRT_ENABLE_PYTHON = "YES",
59-
VSI_CACHE = "TRUE",
60-
GDAL_CACHEMAX = "50%",
61-
62-
# Optimize VSI caching for COGs
63-
VSI_CACHE_SIZE = "25000000", # Increase cache size
64-
# CPL_VSIL_CURL_CHUNK_SIZE = "262144",
65-
# CPL_VSIL_CURL_CACHE_SIZE = "33554432",
66-
67-
# Optimize HTTP connections
68-
GDAL_HTTP_MAX_RETRY = "5",
69-
GDAL_HTTP_RETRY_DELAY = "3",
70-
GDAL_HTTP_MULTIPLEX = "YES",
71-
CPL_VSIL_CURL_ALLOWED_EXTENSIONS = ".tif .TIF", # NEW: Allow both case variants
72-
CPL_VSIL_CURL_USE_HEAD = "NO", # NEW: Skip HEAD requests
73-
74-
# Existing settings
75-
GDAL_DISABLE_READDIR_ON_OPEN = "EMPTY_DIR",
76-
GDAL_MAX_DATASET_POOL_SIZE = "500",
77-
GDAL_INGESTED_BYTES_AT_OPEN = "32000",
78-
GDAL_HTTP_VERSION = "2",
79-
GDAL_HTTP_MERGE_CONSECUTIVE_RANGES = "YES",
80-
GDAL_NUM_THREADS = "ALL_CPUS"
81-
)
82-
83-
gdal_warp_opts <- c(
84-
# Resampling
85-
"-r",
86-
"near",
87-
88-
# Compression options
89-
"-co",
90-
"COMPRESS=LZW", # CHANGED: Often faster than DEFLATE for many datasets
91-
"-co",
92-
"PREDICTOR=2",
93-
"-co",
94-
"NUM_THREADS=ALL_CPUS",
95-
"-co",
96-
"BIGTIFF=YES",
97-
98-
# Tiling options - optimized for COGs
99-
"-co",
100-
"TILED=YES",
101-
"-co",
102-
"BLOCKXSIZE=256", # CHANGED: 256 often better aligns with internal COG structure
103-
"-co",
104-
"BLOCKYSIZE=256", # CHANGED: 256 often better aligns with internal COG structure
105-
"-co",
106-
"COPY_SRC_OVERVIEWS=YES", # NEW: Copy source overviews when available
107-
108-
# Memory and threading options
109-
"-wm",
110-
"50%",
111-
"-multi",
112-
# "-wo",
113-
# "NUM_THREADS=ALL_CPUS",
114-
115-
# Overview options
116-
"-ovr",
117-
"AUTO" # NEW: Use overviews when available
118-
)
119-
120-
op <- options()
121-
op_gdal <- list(
122-
vrt.gdal.config.options = gdal_config_opts,
123-
vrt.gdal.warp.options = gdal_warp_opts
124-
)
125-
126-
toset <- !(names(op_gdal) %in% names(op))
127-
if (any(toset)) options(op_gdal[toset])
128-
}

0 commit comments

Comments
 (0)