| Title: | Global Positioning by Atmospheric Pressure |
|---|---|
| Description: | R package to determine the position and trajectory of a bird based on light-weight data-logger measuring at lease atmospheric pressure. |
| Authors: | Raphaël Nussbaumer [aut, cre, cph] (ORCID: <https://orcid.org/0000-0002-8185-1020>), Mathieu Gravey [aut] (ORCID: <https://orcid.org/0000-0002-0871-1507>) |
| Maintainer: | Raphaël Nussbaumer <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 3.6.3 |
| Built: | 2026-10-08 16:46:44 UTC |
| Source: | https://github.com/Rafnuss/GeoPressureR |
This function returns a list with the four morphological information necessary to construct the power curve: mass, wing span, wing aspect ratio, and body frontal area.
When any of these variables are missing, we query the AVONET database (doi:10.6084/m9.figshare.16586228.v5) using the scientific name from the Clements Checklist.
bird_create( scientific_name, mass = NULL, wing_span = NULL, wing_aspect = NULL, wing_area = NULL, body_frontal_area = NULL, species_name = lifecycle::deprecated() )bird_create( scientific_name, mass = NULL, wing_span = NULL, wing_aspect = NULL, wing_area = NULL, body_frontal_area = NULL, species_name = lifecycle::deprecated() )
scientific_name |
Scientific name of the species |
mass |
Mass of the bird in kilograms |
wing_span |
Wing span in meters |
wing_aspect |
Wing aspect ratio (no unit) |
wing_area |
Wing area in meter square |
body_frontal_area |
Body frontal area in meter square |
species_name |
List containing mass, wing span, wing aspect ratio, and body frontal area.
Other bird:
print.bird()
Other movement:
graph_set_movement(),
plot_graph_movement(),
speed2prob(),
tag_download_wind()
# Using AVONET dataset bird_create("Acrocephalus arundinaceus") # Using AVONET dataset + custom values bird_create("Acrocephalus arundinaceus", wing_aspect = 8) # Import your own bird. You will need mass, and at least two of wing_span, # wing_aspect or wing_area. bird_create("Madynuss nutshell", mass = 8, wing_span = 0.2, wing_aspect = 4)# Using AVONET dataset bird_create("Acrocephalus arundinaceus") # Using AVONET dataset + custom values bird_create("Acrocephalus arundinaceus", wing_aspect = 8) # Import your own bird. You will need mass, and at least two of wing_span, # wing_aspect or wing_area. bird_create("Madynuss nutshell", mass = 8, wing_span = 0.2, wing_aspect = 4)
Reads the NetCDF files and extracts the variable requested along each flight defined by the edges.
Time: linear interpolation using the resolution requested with rounding_interval
Space: nearest neighbour interpolation by default, or bi-linear with pracma::interp2 if
interp_spatial_linear=TRUE. Note: spatial interpolation is limited to 0.1° for computational
reasons.
Pressure/altitude: linear interpolation using the exact pressure values
edge_add_wind( graph, edge_s, edge_t, pressure = NULL, variable = c("u_component_of_wind", "v_component_of_wind"), rounding_interval = 60, interp_spatial_linear = FALSE, return_averaged_variable = lifecycle::deprecated(), file = function(stap_id, tag_id) { glue::glue("./data/wind/{tag_id}/{tag_id}_{stap_id}.nc") }, quiet = FALSE )edge_add_wind( graph, edge_s, edge_t, pressure = NULL, variable = c("u_component_of_wind", "v_component_of_wind"), rounding_interval = 60, interp_spatial_linear = FALSE, return_averaged_variable = lifecycle::deprecated(), file = function(stap_id, tag_id) { glue::glue("./data/wind/{tag_id}/{tag_id}_{stap_id}.nc") }, quiet = FALSE )
graph |
either a |
edge_s |
a index of the source node of the edge. Either a vector with 3D index or a matrix of 3 columns, one for each dimension. |
edge_t |
a index of the target node of the edge. Either a vector with 3D index or a matrix of 3 columns, one for each dimension. |
pressure |
pressure measurement of the associated |
variable |
variables to extract, named exactly as in |
rounding_interval |
temporal resolution on which to query the variable (min). Default is to match ERA5 native resolution (1hr). |
interp_spatial_linear |
logical to interpolate the variable linearly over space, if |
return_averaged_variable |
|
file |
absolute or relative path of the ERA5 wind data file to be downloaded. Function taking as arguments (1) the stationary period identifier and (2) the tag_id. |
quiet |
logical to hide messages about the progress |
A data.frame with one row per time step, edge, and variable:
edge_id edge index
val value of the variable at each time step
pressure pressure at each time step
date datetime of each time step
w weight for averaging
var variable name, as passed to variable
lat latitude at each time step
lon longitude at each time step
## Not run: withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map(extent = c(-16, 23, 0, 50), scale = 1) |> geopressure_map(quiet = TRUE) }) graph <- graph_create(tag, quiet = TRUE) wind <- edge_add_wind(graph, edge_s = graph$s, edge_t = graph$t, quiet = TRUE) ## End(Not run)## Not run: withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map(extent = c(-16, 23, 0, 50), scale = 1) |> geopressure_map(quiet = TRUE) }) graph <- graph_create(tag, quiet = TRUE) wind <- edge_add_wind(graph, edge_s = graph$s, edge_t = graph$t, quiet = TRUE) ## End(Not run)
For each stationary period (stap_id) with usable twilight
events, estimate a single longitude, latitude, and effective zenith angle by
minimizing the squared spherical distance to the corresponding iso-zenith
small circles.
Each twilight defines a small circle on the Earth: the set of locations at a fixed angular distance (zenith angle) from the subsolar point at that time. The fitted location is the point that is, in a least-squares sense, closest to all those circles simultaneously.
For a stationary period with twilight-specific subsolar points s_i, the
fitted longitude lon, latitude lat, and zenith angle z minimize
mean_i ( d((lon, lat), s_i) - z )^2 + P_prior(z)
where d((lon, lat), s_i) is the great-circle angular distance from the
candidate location to the subsolar point at twilight i. The first term is
the mean squared residual to the iso-zenith small circles, normalized by the
number of twilight events so its influence does not depend on sample size.
P_prior(z) is an optional Gaussian penalty on the fitted zenith angle:
1/2 * ((z - mu) / sigma)^2
where mu = zenith_prior_mean and sigma = zenith_prior_sd. This acts as a
prior on the effective zenith angle while leaving longitude and latitude
driven by the twilight geometry.
geolight_fit_location( tag, fitted_location_duration = Inf, extent = NULL, zenith_bounds = c(70, 110), zenith_prior_mean = 93, zenith_prior_sd = 1.3, zenith_prior_penalty_weight = 1e-05, compute_known = FALSE, quiet = FALSE )geolight_fit_location( tag, fitted_location_duration = Inf, extent = NULL, zenith_bounds = c(70, 110), zenith_prior_mean = 93, zenith_prior_sd = 1.3, zenith_prior_penalty_weight = 1e-05, compute_known = FALSE, quiet = FALSE )
tag |
A GeoPressureR tag object containing |
fitted_location_duration |
Minimum duration (in days) of stationary period(s) eligible to be
used as a fitted location from twilight times. Default is |
extent |
Numeric vector |
zenith_bounds |
Numeric vector of length 2 giving zenith bounds (degrees). |
zenith_prior_mean |
Gaussian prior mean for fitted zenith angle (degrees). |
zenith_prior_sd |
Gaussian prior standard deviation for fitted zenith angle (degrees). |
zenith_prior_penalty_weight |
Weight controlling how strongly automatically fitted
locations are pulled toward |
compute_known |
Logical; if FALSE, known stationary periods are copied from |
quiet |
Logical; if TRUE, suppress informative messages. |
A path data.frame derived from tag$stap with added columns:
lon, lat, zenith. Rows where fitting was not possible remain NA.
Other geolight:
geolight_map(),
geolight_solar(),
plot_twl_calib(),
twilight_create(),
twilight_label_read(),
twilight_label_write()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() }) tag <- tag_stap_daily(tag, quiet = TRUE) path <- geolight_fit_location(tag, fitted_location_duration = 5, quiet = TRUE)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() }) tag <- tag_stap_daily(tag, quiet = TRUE) path <- geolight_fit_location(tag, fitted_location_duration = 5, quiet = TRUE)
This function estimates a likelihood map for each stationary period based on twilight data. The function performs the following steps:
Calibrate twilight errors from true known locations and/or automatically fitted calibration locations. See below for details.
Compute a likelihood map for each twilight using the calibration.
Combine the likelihood maps of all twilights belonging to the same stationary periods with a log-linear pooling. See GeoPressureManual | Probability aggregation for more information on probability aggregation using log-linear pooling.
geolight_map( tag, twl_calib_adjust = 1.4, fitted_location_duration = Inf, zenith_prior_mean = 93, zenith_prior_sd = 1.3, zenith_prior_penalty_weight = 1e-05, refine_fitted_location_scale = 20, refine_fitted_location_max_iter = 2, twl_llp = function(n) log(n)/n, compute_known = FALSE, keep_twl = FALSE, quiet = FALSE ) geolight_map_aggregate( tag, compute_known = FALSE, twl_llp = function(n) log(n)/n, keep_twl = FALSE, quiet = FALSE ) geolight_map_calibrate( tag, twl_calib_adjust = 1.4, fitted_location_duration = Inf, zenith_prior_mean = 93, zenith_prior_sd = 1.3, zenith_prior_penalty_weight = 1e-05, refine_fitted_location_scale = 20, refine_fitted_location_max_iter = 2, quiet = FALSE ) geolight_map_likelihood(tag, compute_known = FALSE, quiet = FALSE)geolight_map( tag, twl_calib_adjust = 1.4, fitted_location_duration = Inf, zenith_prior_mean = 93, zenith_prior_sd = 1.3, zenith_prior_penalty_weight = 1e-05, refine_fitted_location_scale = 20, refine_fitted_location_max_iter = 2, twl_llp = function(n) log(n)/n, compute_known = FALSE, keep_twl = FALSE, quiet = FALSE ) geolight_map_aggregate( tag, compute_known = FALSE, twl_llp = function(n) log(n)/n, keep_twl = FALSE, quiet = FALSE ) geolight_map_calibrate( tag, twl_calib_adjust = 1.4, fitted_location_duration = Inf, zenith_prior_mean = 93, zenith_prior_sd = 1.3, zenith_prior_penalty_weight = 1e-05, refine_fitted_location_scale = 20, refine_fitted_location_max_iter = 2, quiet = FALSE ) geolight_map_likelihood(tag, compute_known = FALSE, quiet = FALSE)
tag |
a GeoPressureR |
twl_calib_adjust |
smoothing parameter for the kernel density (see |
fitted_location_duration |
Minimum duration (in days) of stationary period(s) eligible to be
used as an automatic (fitted) calibration site estimated from twilight times.
If enabled (finite duration), eligible stationary periods without known coordinates are fitted
from twilight times, then used like known locations for calibration.
Default is |
zenith_prior_mean |
Gaussian prior mean for the fitted zenith angle (degrees). |
zenith_prior_sd |
Gaussian prior standard deviation for the fitted zenith angle (degrees). |
zenith_prior_penalty_weight |
Weight controlling how strongly automatically fitted
calibration locations are pulled toward |
refine_fitted_location_scale |
Target spatial resolution, in kilometers, for fitted calibration-anchor refinement. This also defines the movement threshold for convergence. |
refine_fitted_location_max_iter |
Maximum number of fitted-location refinement iterations.
Use |
twl_llp |
log-linear pooling aggregation weight. |
compute_known |
logical defining if the map(s) for known stationary period should be
estimated based on twilight or hard defined by the known location |
keep_twl |
logical defining if the likelihood map of each twilight is retained. |
quiet |
logical to hide messages about the progress |
a tag with the likelihood of light as tag$map_light
Calibration can be based on:
a known location for at least one stationary period (set via tag_set_map(known = ...)), and/or
an automatically fitted calibration location (enabled via fitted_location_duration).
When fitted_location_duration is finite, stationary periods at least as long as this threshold and
without known coordinates can be fitted from twilight geometry and used as calibration locations.
If known locations are also present, the calibration combines the known and fitted locations. The
fitted-location step uses a weak Gaussian prior on the effective zenith angle, controlled by
zenith_prior_mean, zenith_prior_sd, and zenith_prior_penalty_weight.
After the initial fitted-location estimate, refine_fitted_location_max_iter > 0 optionally
refines automatically fitted calibration anchors by iteratively recalibrating the twilight-error
distribution for the same stationary period and moving the anchor to the local light-likelihood
mode. This is a calibration-anchor refinement, not a separate movement estimator. It is only
applied to fitted calibration locations; true known locations are kept fixed. Refined fitted
anchors have zenith set to NA because the initial fitted zenith no longer corresponds to the
refined coordinates. The default is 2 iterations.
Instead of calibrating the twilight errors in terms of duration, we directly model the zenith
angle error. We use a kernel distribution to fit the zenith angle during the known stationary
period(s). The twl_calib_adjust parameter allows to manually adjust how smooth you want the
fit of the zenith angle to be. Because the zenith angle error model is fitted with data from the
calibration site only, and we are using it for all locations of the bird’s journey, it is safer
to assume a broader/smoother distribution.
Other geolight:
geolight_fit_location(),
geolight_solar(),
plot_twl_calib(),
twilight_create(),
twilight_label_read(),
twilight_label_write()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { # Read geolocator data and set map parameters tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 10, known = data.frame( stap_id = 1, known_lon = 17.05, known_lat = 48.9 ) ) |> twilight_create() |> twilight_label_read() }) # Visualize twilights plot(tag, type = "twilight") # Calibrate twilight to zenith angle and visualize tag <- geolight_map_calibrate(tag) plot_twl_calib(tag) # Compute likelihood for each twilight and visualize tag <- geolight_map_likelihood(tag) plot(tag, type = "map_light_twl") # Aggregate twilights to stationary periods and visualize tag <- geolight_map_aggregate(tag, quiet = TRUE) plot(tag, type = "map_light")withr::with_dir(system.file("extdata", package = "GeoPressureR"), { # Read geolocator data and set map parameters tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 10, known = data.frame( stap_id = 1, known_lon = 17.05, known_lat = 48.9 ) ) |> twilight_create() |> twilight_label_read() }) # Visualize twilights plot(tag, type = "twilight") # Calibrate twilight to zenith angle and visualize tag <- geolight_map_calibrate(tag) plot_twl_calib(tag) # Compute likelihood for each twilight and visualize tag <- geolight_map_likelihood(tag) plot(tag, type = "map_light_twl") # Aggregate twilights to stationary periods and visualize tag <- geolight_map_aggregate(tag, quiet = TRUE) plot(tag, type = "map_light")
Compute solar zenith angles from time and location using the formulation implemented in the NOAA Solar Calculator, itself based on the astronomical algorithms of Meeus.
geolight_solar(date, lat, lon)geolight_solar(date, lat, lon)
date |
POSIXct vector of times. |
lat |
Numeric vector of latitudes (degrees north). |
lon |
Numeric vector of longitudes (degrees east). |
The computation is split internally into three steps:
geolight_solar_constants(): Time-only solar quantities (solar time and declination)
geolight_solar_zenith(): Geometric solar zenith angle
geolight_solar_refracted(): Approximate atmospheric refraction correction
lon is expressed in degrees east (positive eastward).
lat is expressed in degrees north.
All angles are in degrees unless stated otherwise.
date is provided as POSIXct and internally converted to Julian day.
When lat and lon are vectors, the result is a 3-D array with dimensions:
c(length(lat), length(lon), length(date))
When lat and lon are scalars, the result reduces to a vector of length
length(date).
Internally, the solar time is computed as NOAA's true solar time expressed as an angle (degrees) at Greenwich, without longitude adjustment. Longitude enters later through the hour angle:
hour_angle = solar_time + lon - 180
Values are intentionally not wrapped to [0, 360) because all downstream
trigonometric functions are periodic.
Atmospheric refraction is applied using NOAA's standard piecewise approximation as a function of solar elevation. This correction is approximate and does not account for local pressure or temperature.
Solar zenith angle(s) in degrees, corrected for atmospheric refraction.
NOAA Global Monitoring Laboratory. Solar Calculation Details. https://gml.noaa.gov/grad/solcalc/calcdetails.html
Meeus, J. (1998). Astronomical Algorithms. Willmann-Bell.
Other geolight:
geolight_fit_location(),
geolight_map(),
plot_twl_calib(),
twilight_create(),
twilight_label_read(),
twilight_label_write()
date <- as.POSIXct( c("2020-06-21 12:00:00", "2020-12-21 12:00:00"), tz = "UTC" ) z <- geolight_solar(date, lat = 46, lon = 6) zdate <- as.POSIXct( c("2020-06-21 12:00:00", "2020-12-21 12:00:00"), tz = "UTC" ) z <- geolight_solar(date, lat = 46, lon = 6) z
GeoLightViz is an interactive tool for reviewing twilight observations and
preparing light-based geolocation analyses. It displays the light record and
detected twilight events so that observations affected by shading or other
light obstructions can be marked as discarded. It can also be used to define
or edit stationary periods from twilight patterns, which is useful when
pressure or acceleration data are unavailable. When a map has been defined
with tag_set_map() and stationary periods are available, the app links the
light plot to a map of twilight likelihoods. You can explore candidate
locations and tune twilight calibration and likelihood aggregation settings
with visual feedback. Twilight labels and stationary periods can be saved or
exported from the app.
geolightviz( x, stapath = NULL, launch_browser = TRUE, run_bg = TRUE, quiet = FALSE, ... )geolightviz( x, stapath = NULL, launch_browser = TRUE, run_bg = TRUE, quiet = FALSE, ... )
x |
a GeoPressureR |
stapath |
optional stationary path data.frame (defaults to |
launch_browser |
If true (by default), the app runs in your browser, otherwise it runs on Rstudio. |
run_bg |
If true (by default), the app runs in a background R process using |
quiet |
logical, currently unused. |
... |
currently unused. |
See the GeoLightViz chapter of the GeoPressureManual for an overview of the app's controls and workflow.
When run_bg = TRUE, an invisible callr r_process running the app.
When run_bg = FALSE, the return value of shiny::runApp().
Interactive maps always offer Esri basemaps (gray canvas, imagery and topographic). CARTO, Mapbox and MapTiler basemaps are added to the layer control only when their API key is stored in your system keyring. Get a key from each provider:
CARTO: "Get your API key" on CARTO Basemaps.
Mapbox: Access tokens page of your account (see Mapbox documentation).
MapTiler: API keys page of your MapTiler Cloud account (see MapTiler documentation).
Then store each key once:
keyring::key_set_with_value("CARTO_API_KEY", password = "<your CARTO API key>")
keyring::key_set_with_value("MAPBOX_ACCESS_TOKEN", password = "<your Mapbox token>")
keyring::key_set_with_value("MAPTILER_API_KEY", password = "<your MapTiler API key>")
Mapbox access tokens are visible in the browser when a map is rendered. Use a public, read-only token rather than a secret token.
GeoPressureManual | GeoLightViz
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() }) geolightviz(tag, run_bg = FALSE, launch_browser = FALSE)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() }) geolightviz(tag, run_bg = FALSE, launch_browser = FALSE)
The geopressure_map() function computes a likelihood map for each stationary period based on
pressure measurements. It is a wrapper of the following two child functions:
geopressure_map_mismatch() computes the mismatch maps between the pressure sensor
measurements and the ERA5 reanalysis database.
geopressure_map_likelihood() converts the mismatch maps into a likelihood map.
See below for details. For more background on the method behind these functions, please refer to Nussbaumer et al. (2023a; doi:10.1111/2041-210X.14043).
geopressure_map( tag, max_sample = 250, margin = 30, sd = 1, thr_mask = 0.9, log_linear_pooling_weight = function(n) log(n)/n, timeout = 300, workers = "auto", era5_dataset = "land", keep_mask = FALSE, keep_mse = FALSE, compute_known = FALSE, debug = FALSE, quiet = FALSE ) geopressure_map_likelihood( tag, sd = 1, log_linear_pooling_weight = function(n) log(n)/n, keep_mse = TRUE ) geopressure_map_mismatch( tag, max_sample = 250, margin = 30, thr_mask = 0.9, timeout = 300, workers = "auto", era5_dataset = "land", compute_known = FALSE, keep_mask = TRUE, debug = FALSE, quiet = FALSE )geopressure_map( tag, max_sample = 250, margin = 30, sd = 1, thr_mask = 0.9, log_linear_pooling_weight = function(n) log(n)/n, timeout = 300, workers = "auto", era5_dataset = "land", keep_mask = FALSE, keep_mse = FALSE, compute_known = FALSE, debug = FALSE, quiet = FALSE ) geopressure_map_likelihood( tag, sd = 1, log_linear_pooling_weight = function(n) log(n)/n, keep_mse = TRUE ) geopressure_map_mismatch( tag, max_sample = 250, margin = 30, thr_mask = 0.9, timeout = 300, workers = "auto", era5_dataset = "land", compute_known = FALSE, keep_mask = TRUE, debug = FALSE, quiet = FALSE )
tag |
a GeoPressureR |
max_sample |
the computation of the maps is only performed on |
margin |
the margin is used in the mask map to accept measurement errors, small-scale topography, and vertical movements of the bird (unit in meters, 1hPa~10m). |
sd |
standard deviation of the pressure error. Numeric of length 1 or number of stationary periods. |
thr_mask |
threshold of the percentage of data points outside the elevation range to be considered not possible. |
log_linear_pooling_weight |
weighting function of the log-linear pooling, taking the number of samples of the stationary periods used and returning the weight of the aggregation. See GeoPressureManual | Probability aggregation for more details. |
timeout |
duration before the code is interrupted both for the request on
GeoPressureAPI and on GEE (in seconds, see |
workers |
number of parallel requests on GEE. Integer between 1 and 99. |
era5_dataset |
ERA5 product: |
keep_mask |
logical defining if the mask map is returned in |
keep_mse |
logical defining if the MSE map is returned in |
compute_known |
logical defining if the map(s) for known stationary period should be
estimated based on twilight or hard defined by the known location |
debug |
logical to display additional information to debug a request |
quiet |
logical to hide messages about the progress |
A map will only be computed for the stationary periods included in tag$stap$include and without
a known position tag$stap$known_l** as defined by tag_set_map(). At known stationary
periods, the likelihood map is a map of 0s with a single 1 at the pixel closest to the known
position.
Returns the same GeoPressureR tag object including the GeoPressureR map object
tag$map_pressure containing the likelihood map of each stationary period. See map_create()
for details.
If keep_mask and keep_mse are each true, tag also includes the tag$map_pressure_mse and
tag$map_pressure_mask maps, as well as tag$stap$nb_sample, indicating the number of
datapoints used to compute the MSE.
geopressure_map_mismatch() computes the mismatch maps on Google Earth Engine via the map
entry point of the GeoPressure API.
This consists of the following steps:
Pre-process pressure: the pressure measurements are first smoothed and downscaled to a
1-hour resolution in order to match ERA-5 resolution (see geopressure_map_preprocess()).
Generate requests: Send a single request to the GeoPressureAPI to generate the Google Earth Engine (GEE) URLs, one for each elevation/stationary period which can be used to compute the maps on the GEE server.
Send the requests: Call the URLs, which will start the computation on the GEE server. At this step, it does not wait for an answer, but sends the requests in parallel to be faster.
Compute and download the maps: When all requests are sent, we wait for the GEE server to return a geotiff file (map) for each elevation/ stationary period.
Post-process maps: Read these geotiff maps as matrix, create the corresponding
GeoPressureR map object with create_map().
The following two maps are returned for each stationary period:
map_pressure_mse: The Mean Square Error (MSE) between the data logger pressure time series and the reanalysis. The mean error is removed because we assume no specific altitude of the geolocator, thus allowing an altitudinal shift of the pressure time series.
map_pressure_mask (optionally): The mask of the proportion of pressure measurements
corresponding to altitude values found within the min and max ground elevation at each location.
The altitude value of the geolocator pressure time series is computed with the barometric formula
accounting for the temporal variation of pressure (surface-pressure) and temperature
(2m-temperature) based on ERA5 data. The min and max ground elevation of each pixel is computed
from SRTM-90. This map is only returned if keep_mask is TRUE.
For more details, read the GeoPressure API documentation .
It is possible to indicate different elevation levels when the bird was spending time at
locations with different elevations within a general area (~10km), and thus within the same
stationary period. This can be done by using tag$label="elev_x" for all measurements of the
same elevation level x. See more information on the labelling of elevation levels in the corresponding section in the GeoPressureManual.
Behind the scene, each of these elevation levels produces a new request on the GeoPressureAPI. The mismatch maps of all elevation levels belonging to the same stationary periods are combined (as a weighted average) to result in a single mismatch map per stationary period.
We convert the map of the mean square error and altitude mask computed
by geopressure_map_mismatch() into a likelihood map with,
where is the standard deviation (sd) of pressure and is the mask threshold
(thr_mask).
Because the auto-correlation of the time series is not accounted for in this equation, we use a
log-linear pooling weight of by default, where is the number of samples
in the time series (i.e., data points used to compute the MSE). See GeoPressureManual | Probability aggregation for details.
Important Note: Since GeoPressure v3.1.0, the threshold of the mask is happening directly
on the GEE server (i.e., during geopressure_map_mismatch()). This allows to compute the MSE
only for pixels which are within the threshold, thus reducing the computational cost
significantly.
Nussbaumer, Raphaël, Mathieu Gravey, Martins Briedis, and Felix Liechti. 2023. Global Positioning with Animal‐borne Pressure Sensors. Methods in Ecology and Evolution, 14, 1118–1129 doi:10.1111/2041-210X.14043.
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 4 ) }) tag <- geopressure_map_mismatch(tag, max_sample = 50, margin = 20, thr_mask = 0.95, keep_mask = TRUE, quiet = TRUE ) plot(tag, type = "map_pressure_mse", plot_leaflet = FALSE) plot(tag, type = "map_pressure_mask", plot_leaflet = FALSE) tag <- geopressure_map_likelihood(tag, sd = 1, log_linear_pooling_weight = function(n) log(n) / n ) plot(tag, type = "map_pressure")withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 4 ) }) tag <- geopressure_map_mismatch(tag, max_sample = 50, margin = 20, thr_mask = 0.95, keep_mask = TRUE, quiet = TRUE ) plot(tag, type = "map_pressure_mse", plot_leaflet = FALSE) plot(tag, type = "map_pressure_mask", plot_leaflet = FALSE) tag <- geopressure_map_likelihood(tag, sd = 1, log_linear_pooling_weight = function(n) log(n) / n ) plot(tag, type = "map_pressure")
geopressure_map()
Performs the following pre-processing for the pressure data.frame:
Remove discarded and flight pressure measurements.
Group pressure measurements by stationary period and elevation level.
Smooth and downscale pressure to a 1 hour resolution to match ERA5 data.
This function is used within geopressure_map_mismatch() but can be useful to check the
pressure data sent to the GeoPressureAPI.
geopressure_map_preprocess(tag, compute_known = FALSE)geopressure_map_preprocess(tag, compute_known = FALSE)
tag |
a GeoPressureR |
compute_known |
logical defining if the map(s) for known stationary period should be
estimated based on twilight or hard defined by the known location |
Pressure data.frame without flight and discarded values, on a 1 hour resolution.
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) pressure_processed <- geopressure_map_preprocess(tag) str(pressure_processed) # Plotting pressure displays the raw data (in grey) with the processed data from # `geopressure_map_preprocess` (as coloured line) plot_tag_pressure(tag)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) pressure_processed <- geopressure_map_preprocess(tag) str(pressure_processed) # Plotting pressure displays the raw data (in grey) with the processed data from # `geopressure_map_preprocess` (as coloured line) plot_tag_pressure(tag)
geopressure_timeseries() retrieves an hourly ERA5 surface-pressure time series at one
location. Supply a tag pressure series to also normalise ERA5 pressure and estimate altitude.
geopressure_timeseries_arco() and geopressure_timeseries_api() are shortcuts that force the
corresponding source.
geopressure_timeseries( lat, lon, pressure = NULL, start_time = NULL, end_time = NULL, quiet = FALSE, debug = FALSE, source = c("auto", "arco", "api"), era5_dataset = c("land", "single-levels") ) geopressure_timeseries_api( lat, lon, pressure = NULL, start_time = NULL, end_time = NULL, quiet = FALSE, debug = FALSE ) geopressure_timeseries_arco( lat, lon, pressure = NULL, start_time = NULL, end_time = NULL, quiet = FALSE, debug = FALSE, era5_dataset = c("land", "single-levels") )geopressure_timeseries( lat, lon, pressure = NULL, start_time = NULL, end_time = NULL, quiet = FALSE, debug = FALSE, source = c("auto", "arco", "api"), era5_dataset = c("land", "single-levels") ) geopressure_timeseries_api( lat, lon, pressure = NULL, start_time = NULL, end_time = NULL, quiet = FALSE, debug = FALSE ) geopressure_timeseries_arco( lat, lon, pressure = NULL, start_time = NULL, end_time = NULL, quiet = FALSE, debug = FALSE, era5_dataset = c("land", "single-levels") )
lat |
Numeric scalar latitude, between -90 and 90 degrees. |
lon |
Numeric scalar longitude, between -180 and 180 degrees. |
pressure |
Optional data.frame with a date-time |
start_time, end_time
|
Start and end of the requested interval when |
quiet |
Logical to suppress progress messages. |
debug |
Logical to display request details. |
source |
Data source: |
era5_dataset |
ERA5 product used by ARCO: |
A data.frame containing date, surface_pressure, lat, and lon. With pressure,
it also retains the input columns, renames value to pressure_tag, and adds
surface_pressure_norm and altitude.
source = "arco" reads ECMWF's Analysis-Ready Cloud-Optimised (ARCO) archive directly. It is
generally faster for a long time series at one location, supports ERA5-Land and global ERA5,
and requires an ECMWF API key plus the optional Rarr and ecmwfr packages.
source = "api" asks the hosted GeoPressureAPI to prepare the data. It needs no ECMWF key or
Rarr installation, but depends on that service and supports its fixed ERA5 configuration.
The default, source = "auto", uses ARCO when a key stored by ecmwfr::wf_set_key() is
available and GeoPressureAPI otherwise. Use geopressure_timeseries_arco() or
geopressure_timeseries_api() to select a backend explicitly.
With ARCO, era5_dataset = "single-levels" uses global ERA5 on a 0.25 degree grid and retains
locations over water. era5_dataset = "land" (the default) uses ERA5-Land on a 0.1 degree grid;
it has finer spatial resolution but is masked over oceans, so ocean locations are moved to the
closest land cell, and it must not be used when pressure is supplied because altitude is
then computed from it (see the Choosing era5_dataset section). GeoPressureAPI chooses its
ERA5 data internally and moves ocean locations onshore.
Without pressure, the requested interval is returned hourly. With ARCO and pressure, each tag
time is matched to its closest ERA5 hour and restored after matching; no temporal interpolation
is used. GeoPressureAPI receives the original tag timestamps and performs the matching remotely.
When altitude is produced, GeoPressureR uses the same barometric relation as GeoPressureAPI:
Here, is tag pressure, while , ,
and
are ERA5 surface pressure, 2 m temperature, and model-surface elevation. Model-surface elevation
is obtained from ERA5 surface geopotential divided by standard gravity. The constants are the
standard temperature lapse rate K/m, universal gas constant
J/(mol K), standard gravity m/s², and molar mass of dry air
kg/mol. Pressure is converted to Pa internally and altitude is returned in
metres above mean sea level.
era5_dataset
Use era5_dataset = "single-levels" whenever altitude is computed.
ERA5-Land's surface_pressure is not the exact hydrostatic image of the orography ERA5-Land
publishes as geopotential — the two disagree by up to ~10 hPa in steep terrain. The
term therefore fails to cancel from the relation above and the whole discrepancy
lands in the retrieved altitude. Measured against 41,653 hourly station-pressure observations
from 271 NOAA ISD stations (2–3576 m, Alps, July 2020), compared with surveyed station
elevation:
era5_dataset |
bias | MAE | RMSE |
"single-levels" |
−0.6 m | 9.0 m | 27.4 m |
"land" / "both" |
+2.5 m | 55.3 m | 76.9 m |
ERA5-Land replays the land component of ERA5 and assimilates no atmospheric observations of its
own, so it carries no independent information about absolute altitude. Substituting the
orography implied by its own surface pressure removes the error exactly and reproduces
"single-levels" to 0.1 m.
"land" and "both" remain the defaults for backward compatibility. They are appropriate for
retrieving other variables at 0.1 degree resolution, and for geopressure_map(), whose
pressure mismatch is differential and unaffected.
With era5_dataset = "single-levels" the altitude error separates into two parts that behave
very differently. A static per-site offset (median 3.7 m, p90 15 m) reflects station metadata
and sub-grid terrain and does not vary in time, while the temporal scatter (median SD 3.1 m,
p90 7.7 m) is the actual reanalysis error. Expect roughly 3 m for relative altitude changes
at a fixed location and 10 m mean absolute error for absolute altitude, degrading to tens
of metres in steep terrain — where it is a fixed offset rather than noise. Precision is nearly
independent of flight altitude: de-biased RMSE stays 2–7 m up to 1000 m above the model surface
and about 12 m at 1000–3000 m above it.
total_precipitation, surface_solar_radiation_downwards and
surface_thermal_radiation_downwards do not mean the same thing across backends when
era5_dataset = "land". GeoPressureAPI serves Earth Engine's ERA5-Land collection, where these
bands are overwritten by their *_hourly counterparts and are therefore hourly increments.
ARCO serves ECMWF's own ERA5-Land fields, which accumulate from 00 UTC. For
era5_dataset = "single-levels" both are hourly and agree. Take the difference between
consecutive hours if you need increments from ARCO over land.
ERA5 surface pressure is also shifted to the mean tag-pressure level within each elevation-label
group. Flight observations (stap_id == 0) and observations labelled "discard" are excluded
from the group means. The adjusted series is returned as surface_pressure_norm.
ARCO access and CDS downloads use the same ECMWF Personal Access Token. Create an ECMWF account, copy the token from your Climate Data Store profile, accept the dataset licence terms, and store the token once in your system keyring:
ecmwfr::wf_set_key("your-personal-access-token")
Do not put the token in a script or commit it to version control. GeoPressureR retrieves the
stored token with ecmwfr::wf_get_key() for all ECMWF-backed functions, including
geopressure_timeseries(), pressurepath_create(), and tag_download_wind().
Other pressurepath:
plot_pressurepath(),
pressurepath_create(),
pressurepath_variable_available()
geopressure_timeseries( lat = 46, lon = 6, start_time = "2020-01-01", end_time = "2020-01-02" )geopressure_timeseries( lat = 46, lon = 6, start_time = "2020-01-01", end_time = "2020-01-02" )
GeoPressureR is a R package which help researchers determine the position of a bird based on the data retrieved from multi-sensor geolocators.
The main novelty of this package is to match atmospheric pressure measurements to weather reanalysis database (ERA-5) and produce a probability maps of position.
In addition, we use a graphical model to combine pressure, light, acceleration and windspeed data into a trajectory model of the bird.
Maintainer: Raphaël Nussbaumer [email protected] (ORCID) [copyright holder]
Authors:
Raphaël Nussbaumer [email protected] (ORCID) [copyright holder]
Mathieu Gravey [email protected] (ORCID)
Useful links:
Report bugs at https://github.com/GeoPressure/GeoPressureR/issues
The geopressuretemplate() function manages the complete workflow for modelling bird
trajectories using geolocator data. It includes the creation tag object, the construction of
the likelihood maps (pressure and/or light), the creation of the graph model construction, and,
finally, the estimation of the trajectory products and the pressure path computation. Read the
Workflow chapter in the GeoPressureManual for more
information.
geopressuretemplate( id, config = config::get(config = id), quiet = FALSE, file = glue::glue("./data/interim/{id}.RData"), ... ) geopressuretemplate_config( id, config = config::get(config = id), assert_tag = TRUE, assert_graph = FALSE, ... ) geopressuretemplate_graph( id, config = config::get(config = id), quiet = FALSE, file = glue::glue("./data/interim/{id}.RData"), ... ) geopressuretemplate_pressurepath( id, config = config::get(config = id), quiet = FALSE, file = glue::glue("./data/interim/{id}.RData"), ... ) geopressuretemplate_tag( id, config = config::get(config = id), quiet = FALSE, file = glue::glue("./data/interim/{id}.RData"), ... )geopressuretemplate( id, config = config::get(config = id), quiet = FALSE, file = glue::glue("./data/interim/{id}.RData"), ... ) geopressuretemplate_config( id, config = config::get(config = id), assert_tag = TRUE, assert_graph = FALSE, ... ) geopressuretemplate_graph( id, config = config::get(config = id), quiet = FALSE, file = glue::glue("./data/interim/{id}.RData"), ... ) geopressuretemplate_pressurepath( id, config = config::get(config = id), quiet = FALSE, file = glue::glue("./data/interim/{id}.RData"), ... ) geopressuretemplate_tag( id, config = config::get(config = id), quiet = FALSE, file = glue::glue("./data/interim/{id}.RData"), ... )
id |
unique identifier of a tag. |
config |
configuration object specifying workflow parameters, which is loaded by default
using |
quiet |
Logical. If |
file |
A file path to save the intermediate results (e.g., tag, graph, and pressure paths).
Default is |
... |
Additional parameters to overwrite default or config values. Always prefer to modify
|
assert_tag |
Logical. If |
assert_graph |
Logical. If |
The geopressuretemplate function is a high-level entry point that coordinates multiple
steps for processing the geolocator data and produce trajectories. It relies on underlying child
functions for each step:
Tag Creation geopressuretemplate_tag(): Initializes and labels the tag object. It
also generates light and pressure likelihood maps:
tag_create(): Initializes the tag object.
tag_label(): Adds labels.
tag_set_map(): Sets the spatial and temporal parameters.
If "map_pressure" is in the config$geopressuretemplate$likelihood:
geopressure_map(): Computes the pressure likelihood.
If "map_light" is in the config$geopressuretemplate$likelihood:
twilight_create() |> twilight_read() |> geolight_map(): Computes the light likelihood.
Graph Creation geopressuretemplate_graph(): Builds a movement model graph
based tag data, and can include wind effects if specified. Outputs such as
marginal distributions, most likely paths, and simulation paths can be computed.
graph_create(): Creates the graph based on tag.
If config$graph_set_movement$type == "gs" (i.e., no wind):
graph_set_movement(): Sets the movement model without wind.
If config$graph_set_movement$type == "as" (i.e., with wind):
graph_add_wind(): Adds wind data to the graph.
graph_set_movement(): Sets the movement model with wind.
If "marginal" is in config$geopressuretemplate$outputs:
graph_marginal(): Computes the marginal distribution map.
If "most_likely" is in config$geopressuretemplate$outputs:
graph_most_likely(): Computes the most likely path based on the movement model.
If "simulation" is in config$geopressuretemplate$outputs:
graph_simulation(): Runs simulations to model multiple possible paths.
save(): Saves the computed graph and associated objects in data/interim/{id}.Rdata
Pressure Path Processing geopressuretemplate_pressurepath(): Computes pressurepaths
(pressurepath_create) using the content of the Rdata file and appending the pressurepath
data.frame to the same file.
If "most_likely" is in config$geopressuretemplate$pressurepath, computes the pressure path
for path_most_likely.
If "geopressureviz" is in config$geopressuretemplate$pressurepath computes the pressure
path for path_geopressureviz
Each of these child functions can be called individually or automatically as part of
the geopressuretemplate workflow.
The function returns nothing. Instead, it saves the processed outputs (tag, graph,
pressure paths, etc.) to the specified file.
# Run the complete geopressuretemplate workflow geopressuretemplate("18LX") # Overwrite parameters passed through ... geopressuretemplate("18LX", tag_set_map = list(scale = 2), geopressure_map = list(max_sample = 100, margin = 20) ) # Or run step-by-step # you can check that all the parameters are correctly set in the config file geopressuretemplate_config(id) # 1. creation of the tag tag <- geopressuretemplate_tag("18LX") # 2. creation of the graph geopressuretemplate_graph("18LX") # 3. Computation of the pressurepath geopressuretemplate_pressurepath("18LX")# Run the complete geopressuretemplate workflow geopressuretemplate("18LX") # Overwrite parameters passed through ... geopressuretemplate("18LX", tag_set_map = list(scale = 2), geopressure_map = list(max_sample = 100, margin = 20) ) # Or run step-by-step # you can check that all the parameters are correctly set in the config file geopressuretemplate_config(id) # 1. creation of the tag tag <- geopressuretemplate_tag("18LX") # 2. creation of the graph geopressuretemplate_graph("18LX") # 3. Computation of the pressurepath geopressuretemplate_pressurepath("18LX")
GeoPressureViz is an interactive app to inspect and manually edit migration paths together with the underlying map likelihoods and pressure time series by stationary period. It is useful to compare pressure-, light- and distance-based information before finalizing a path.
The app can start from a tag object already in memory, or from an interim .RData/.rda
file that contains at least tag (and optionally marginal, path_most_likely,
pressurepath, pressurepath_most_likely).
When run_bg = FALSE, the app stores the current edited path in the Shiny option
path_geopressureviz and returns it invisibly when the app closes. You can capture it from the
return value of this function or retrieve it afterwards in the same R session with
shiny::getShinyOption("path_geopressureviz").
When run_bg = TRUE, the function returns the background process object instead of the edited
path.
The app Save button writes the current path to ./data/interim/{id}-path-geopressureviz.csv.
Learn more about GeoPressureViz in the GeoPressureManual .
geopressureviz( x, path = NULL, marginal = NULL, launch_browser = TRUE, run_bg = TRUE )geopressureviz( x, path = NULL, marginal = NULL, launch_browser = TRUE, run_bg = TRUE )
x |
One of:
|
path |
Optional GeoPressureR
|
marginal |
map of the marginal probability computed with |
launch_browser |
If true (by default), the app runs in your browser, otherwise it runs on Rstudio. |
run_bg |
If true, the app runs in a background R session using the |
When run_bg = FALSE: The edited path, returned invisibly when the app closes. During
the app session, the current path is also stored in the Shiny option
shiny::getShinyOption("path_geopressureviz"), which can be read afterwards in the same R
session.
When run_bg = TRUE: The background process object. In this case the edited path is not
returned to the calling console session.
Interactive maps always offer Esri basemaps (gray canvas, imagery and topographic). CARTO, Mapbox and MapTiler basemaps are added to the layer control only when their API key is stored in your system keyring. Get a key from each provider:
CARTO: "Get your API key" on CARTO Basemaps.
Mapbox: Access tokens page of your account (see Mapbox documentation).
MapTiler: API keys page of your MapTiler Cloud account (see MapTiler documentation).
Then store each key once:
keyring::key_set_with_value("CARTO_API_KEY", password = "<your CARTO API key>")
keyring::key_set_with_value("MAPBOX_ACCESS_TOKEN", password = "<your Mapbox token>")
keyring::key_set_with_value("MAPTILER_API_KEY", password = "<your MapTiler API key>")
Mapbox access tokens are visible in the browser when a map is rendered. Use a public, read-only token rather than a secret token.
geopressureviz("18LX")geopressureviz("18LX")
graph
Reads the NetCDF files downloaded and interpolate the average windspeed experienced by the bird on each possible edge, as well as the corresponding airspeed.
In addition, the graph can be further pruned based on a threshold of airspeed thr_as.
See section 2.2.4 in Nussbaumer (2023b) for more technical details and the GeoPressureManual for an illustration on how to use it.
graph_add_wind(graph, thr_as = Inf, variable = lifecycle::deprecated(), ...)graph_add_wind(graph, thr_as = Inf, variable = lifecycle::deprecated(), ...)
graph |
a GeoPressureR graph object. |
thr_as |
threshold of airspeed (km/h). |
variable |
|
... |
Arguments passed on to
|
A graph object with windspeed and airspeed as ws and as respectively.
Nussbaumer, Raphaël, Mathieu Gravey, Martins Briedis, Felix Liechti, and Daniel Sheldon. 2023. Reconstructing bird trajectories from pressure and wind data using a highly optimized hidden Markov model. Methods in Ecology and Evolution, 14, 1118–1129 doi:10.1111/2041-210X.14082.
Other graph:
graph_create(),
graph_marginal(),
graph_most_likely(),
graph_set_movement(),
graph_simulation(),
print.graph()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map(extent = c(-16, 23, 0, 50), scale = 1) |> geopressure_map(quiet = TRUE) }) graph <- graph_create(tag, quiet = TRUE) graph <- graph_add_wind(graph, pressure = tag$pressure, quiet = TRUE)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map(extent = c(-16, 23, 0, 50), scale = 1) |> geopressure_map(quiet = TRUE) }) graph <- graph_create(tag, quiet = TRUE) graph <- graph_add_wind(graph, pressure = tag$pressure, quiet = TRUE)
graph
This function check the condition of a graph object.
graph_assert(graph, condition = "graph")graph_assert(graph, condition = "graph")
graph |
a GeoPressureR |
condition |
condition to assert |
logical indicating whether the graph object fulfil the condition.
graph_assert(graph, "movement")graph_assert(graph, "movement")
graph objectThis function returns a trellis graph representing the trajectory of a bird based on filtering and pruning the likelihood maps provided.
In the final graph, we only keep the likely nodes (i.e., position of the bird at each
stationary periods) defined as (1) those whose likelihood value are within the threshold of
percentile thr_likelihood of the total likelihood map and (2) those which are connected to
at least one edge of the previous and next stationary periods requiring an average ground speed
lower than thr_gs (in km/h).
For more details and illustration, see section 2.2 of Nussbaumer et al. (2023b) and the GeoPressureManual
graph_create( tag, thr_likelihood = 0.99, thr_gs = 150, likelihood = NULL, quiet = FALSE, geosphere_dist = lifecycle::deprecated(), geosphere_bearing = lifecycle::deprecated(), workers = lifecycle::deprecated() )graph_create( tag, thr_likelihood = 0.99, thr_gs = 150, likelihood = NULL, quiet = FALSE, geosphere_dist = lifecycle::deprecated(), geosphere_bearing = lifecycle::deprecated(), workers = lifecycle::deprecated() )
Graph as a list
s: source node (index in the 3d grid lat-lon-stap)
t: target node (index in the 3d grid lat-lon-stap)
gs: average ground speed required to make that transition (km/h) as complex number
representing the E-W as real and S-N as imaginary
obs: observation model, corresponding to the normalized likelihood in a 3D matrix of size
sz
sz: size of the 3d grid lat-lon-stap
stap: data.frame of all stationary periods (same as tag$stap)
equipment: node(s) of the first stap (index in the 3d grid lat-lon-stap)
retrieval: node(s) of the last stap (index in the 3d grid lat-lon-stap)
mask_water: logical matrix of water-land
param: list of parameters including thr_likelihood and thr_gs (same as tag$param)
Nussbaumer, Raphaël, Mathieu Gravey, Martins Briedis, Felix Liechti, and Daniel Sheldon. 2023. Reconstructing bird trajectories from pressure and wind data using a highly optimized hidden Markov model. Methods in Ecology and Evolution, 14, 1118–1129 doi:10.1111/2041-210X.14082.
Other graph:
graph_add_wind(),
graph_marginal(),
graph_most_likely(),
graph_set_movement(),
graph_simulation(),
print.graph()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) # Create graph graph <- graph_create(tag, thr_likelihood = 0.95, thr_gs = 100, quiet = TRUE) print(graph)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) # Create graph graph <- graph_create(tag, thr_likelihood = 0.95, thr_gs = 100, quiet = TRUE) print(graph)
Compute the marginal probability map from a graph. The computation uses the forward backward algorithm. For more details, see section 2.3.2 of Nussbaumer et al. (2023b) and the GeoPressureManual.
graph_marginal(graph, quiet = FALSE)graph_marginal(graph, quiet = FALSE)
graph |
a GeoPressureR |
quiet |
logical to hide messages about the progress. |
A list of the marginal maps for each stationary period (even those not modelled). Best to
include within tag.
Nussbaumer, Raphaël, Mathieu Gravey, Martins Briedis, Felix Liechti, and Daniel Sheldon. 2023. Reconstructing bird trajectories from pressure and wind data using a highly optimized hidden Markov model. Methods in Ecology and Evolution, 14, 1118–1129 doi:10.1111/2041-210X.14082.
Other graph:
graph_add_wind(),
graph_create(),
graph_most_likely(),
graph_set_movement(),
graph_simulation(),
print.graph()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) # Create graph graph <- graph_create(tag, quiet = TRUE) # Define movement model graph <- graph_set_movement(graph) # Compute marginal marginal <- graph_marginal(graph) plot(marginal)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) # Create graph graph <- graph_create(tag, quiet = TRUE) # Define movement model graph <- graph_set_movement(graph) # Compute marginal marginal <- graph_marginal(graph) plot(marginal)
Compute the trajectory which maximizes the joint probability using the Viterbi algorithm on the graph structure. For more details, see section 2.3.1 of Nussbaumer et al. (2023b) and the GeoPressureManual.
graph_most_likely(graph, quiet = FALSE)graph_most_likely(graph, quiet = FALSE)
graph |
a graph object. |
quiet |
logical to hide messages about the progress. |
Path data.frame containing the columns
-stap_id stationary period
j unique ID for each path, here always 1 as there is a single path.
ind indices of the coordinate in the 2D grid. Useful to retrieve map or graph information
lat latitude,
lon longitude
start datetime of the start of the stationary period (same as in stap)
end datetime of the end of the stationary period (same as in stap)
include logical if stationary period was modelled (same as in stap)
Nussbaumer, Raphaël, Mathieu Gravey, Martins Briedis, Felix Liechti, and Daniel Sheldon. 2023. Reconstructing bird trajectories from pressure and wind data using a highly optimized hidden Markov model. Methods in Ecology and Evolution, 14, 1118–1129 doi:10.1111/2041-210X.14082.
Other graph:
graph_add_wind(),
graph_create(),
graph_marginal(),
graph_set_movement(),
graph_simulation(),
print.graph()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) # Create graph graph <- graph_create(tag, quiet = TRUE) # Define movement model graph <- graph_set_movement(graph) # Compute most likely path path_most_likely <- graph_most_likely(graph, quiet = TRUE) plot_path(path_most_likely)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) # Create graph graph <- graph_create(tag, quiet = TRUE) # Define movement model graph <- graph_set_movement(graph) # Compute most likely path path_most_likely <- graph_most_likely(graph, quiet = TRUE) plot_path(path_most_likely)
graph
Configure the movement model of a graph by defining the value of the parameters needed to build
the transition graph_transition() through speed2prob().
Three methods are currently implemented with two parametric function "gamma" and "logis"
suitable when wind data is not available and are thus defining the probability of a groundspeed.
If wind data is available, it is recommended to use the "power" method which rely on the power
curve equation (energy vs airspeed) to estimate the probability of an airspeed. Read more about
this approach in section 2.2.5. of Nussbaumer et al. (2023b)
graph_set_movement( graph, type = ifelse("ws" %in% names(graph), "as", "gs"), method = ifelse("ws" %in% names(graph), "power", "gamma"), shape = 7, scale = 7, location = 40, bird = NULL, power2prob = function(power) (1/power)^3, low_speed_fix = 15, zero_speed_ratio = 1 )graph_set_movement( graph, type = ifelse("ws" %in% names(graph), "as", "gs"), method = ifelse("ws" %in% names(graph), "power", "gamma"), shape = 7, scale = 7, location = 40, bird = NULL, power2prob = function(power) (1/power)^3, low_speed_fix = 15, zero_speed_ratio = 1 )
graph |
a GeoPressureR |
type |
Ground speed |
method |
method used to convert the speed to probability ("gamma", "logis" or "power") |
shape |
parameter of the gamma distribution (km/h) |
scale |
parameter of the gamma and logistic distribution (km/h) |
location |
parameter for the logistic distribution (km/h) |
bird |
A GeoPressureR |
power2prob |
function taking power as a single argument and returning a probability |
low_speed_fix |
speed below which the probability remains the same, i.e. we assign the same
probability at |
zero_speed_ratio |
multiplicative ratio of the probability for speed zero. This ratio apply only when the bird is staying at the same location (fly and come back or stay within pixel size). This parameter (when greater than 1) is used to favour a bird to stay at the same location rather than perform short fly. |
Graph list with a new list graph$movement storing all the parameters needed to compute
the transition probability
Nussbaumer, Raphaël, Mathieu Gravey, Martins Briedis, Felix Liechti, and Daniel Sheldon. 2023. Reconstructing bird trajectories from pressure and wind data using a highly optimized hidden Markov model. Methods in Ecology and Evolution, 14, 1118–1129 doi:10.1111/2041-210X.14082.
Other graph:
graph_add_wind(),
graph_create(),
graph_marginal(),
graph_most_likely(),
graph_simulation(),
print.graph()
Other movement:
bird_create(),
plot_graph_movement(),
speed2prob(),
tag_download_wind()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) graph <- graph_create(tag, quiet = TRUE) graph <- graph_set_movement(graph, method = "gamma", shape = 4, scale = 6, low_speed_fix = 10 ) plot_graph_movement(graph) graph <- graph_set_movement(graph, method = "logis", shape = 4, location = 60, low_speed_fix = 10 ) plot_graph_movement(graph)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) graph <- graph_create(tag, quiet = TRUE) graph <- graph_set_movement(graph, method = "gamma", shape = 4, scale = 6, low_speed_fix = 10 ) plot_graph_movement(graph) graph <- graph_set_movement(graph, method = "logis", shape = 4, location = 60, low_speed_fix = 10 ) plot_graph_movement(graph)
This function randomly simulates multiple trajectories from a graph using the forward filtering backward sampling algorithm. For more details, see section 2.3.3 of Nussbaumer et al. (2023b) and the GeoPressureManual.
graph_simulation(graph, nj = 10, quiet = FALSE)graph_simulation(graph, nj = 10, quiet = FALSE)
graph |
a graph object. |
nj |
Number of simulations. |
quiet |
logical to hide messages about the progress. |
Path data.frame containing the columns
-stap_id stationary period
j unique ID for each simulation.
ind indices of the coordinate in the 2D grid. Useful to retrieve map or graph information
lat latitude,
lon longitude
start datetime of the start of the stationary period (same as in stap)
end datetime of the end of the stationary period (same as in stap)
include logical if stationary period was modelled (same as in stap)
Nussbaumer, Raphaël, Mathieu Gravey, Martins Briedis, Felix Liechti, and Daniel Sheldon. 2023. Reconstructing bird trajectories from pressure and wind data using a highly optimized hidden Markov model. Methods in Ecology and Evolution, 14, 1118–1129 doi:10.1111/2041-210X.14082.
Other graph:
graph_add_wind(),
graph_create(),
graph_marginal(),
graph_most_likely(),
graph_set_movement(),
print.graph()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) # Create graph graph <- graph_create(tag, quiet = TRUE) # Define movement model graph <- graph_set_movement(graph) # Compute simulations path_simulation <- graph_simulation(graph, quiet = TRUE) plot_path(path_simulation, plot_leaflet = FALSE)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) # Create graph graph <- graph_create(tag, quiet = TRUE) # Define movement model graph <- graph_set_movement(graph) # Compute simulations path_simulation <- graph_simulation(graph, quiet = TRUE) plot_path(path_simulation, plot_leaflet = FALSE)
Loads one or more objects from an interim .RData file created during the GeoPressure analysis.
This is a convenience function to quickly restore saved objects (e.g., tag, graph,
path_most_likely) for a given tag id or directly from a file path.
load_interim( x, var = NULL, var_optional = NULL, envir = parent.frame(), verbose = FALSE )load_interim( x, var = NULL, var_optional = NULL, envir = parent.frame(), verbose = FALSE )
x |
A character string of length 1. If |
var |
Optional name (or names) of objects that must exist in the file. If |
var_optional |
Character vector of object names that may or may not exist in the file. Any of these that are present will be loaded; missing ones are silently ignored. |
envir |
the environment where the data should be loaded. |
verbose |
should item names be printed during loading? |
If no selection is requested (var and var_optional both NULL), invisibly returns
the character vector of object names loaded (as in base::load()). Otherwise, if a single
object name is requested, invisibly returns that object; if multiple names are requested,
invisibly returns a named list of those objects.
load_interim("18LX", var = c("tag", "graph"))load_interim("18LX", var = c("tag", "graph"))
This function creates a water mask for maps with geolight_map already run.
The mask is based on coastline data from Natural Earth and is stored as
map$mask_water as a boolean matrix where TRUE indicates water and
FALSE indicates land.
A pixel is marked as land if any land exists within it (using the conservative
touches=TRUE approach in rasterization), which is important for detecting small
islands; the mask then flags the remaining pixels as water.
map_add_mask_water(map, ne_scale = "medium", land_threshold = 0)map_add_mask_water(map, ne_scale = "medium", land_threshold = 0)
map |
a GeoPressureR |
ne_scale |
Natural Earth resolution passed to
|
land_threshold |
Numeric threshold used to classify pixels as water from
the rasterized land fraction. Pixels with land fraction at or below
|
The coastline data is rasterized to match the map's grid (defined by extent and
scale from the map). land_threshold controls how much land can be present
in a pixel before it is treated as land in map$mask_water. For "large"/10
resolution, rnaturalearthhires is used by rnaturalearth when available.
A map object with mask_water added as a logical matrix.
Other map:
map_create(),
print.map(),
rast.map()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 4, known = data.frame( stap_id = 1, known_lon = 17.05, known_lat = 48.9 ) ) |> twilight_create() |> twilight_label_read() |> geolight_map(quiet = TRUE) # Create water mask tag$map_light <- map_add_mask_water(tag$map_light) # View the mask image(tag$map_light$mask_water) })withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 4, known = data.frame( stap_id = 1, known_lon = 17.05, known_lat = 48.9 ) ) |> twilight_create() |> twilight_label_read() |> geolight_map(quiet = TRUE) # Create water mask tag$map_light <- map_add_mask_water(tag$map_light) # View the mask image(tag$map_light$mask_water) })
map objectThis function creates a GeoPressureR map object from a spatio-temporal dataset.
The data needs to be discretized according to scale, extent (space) and stap (time).
This function is used by geopressure_map and graph_marginal.
map_create(data, extent, scale, stap, id = NA, type = "unknown")map_create(data, extent, scale, stap, id = NA, type = "unknown")
data |
list of matrices of the same size, one for each stationary period. |
extent |
geographical extent of the map on which the likelihood and graph model will be
computed. Vector of length 4 |
scale |
number of pixels per 1° latitude-longitude. For instance, |
stap |
a data.frame of stationary periods. |
id |
tag identifier. |
type |
map type used for default palettes in plots. One of:
|
A GeoPressure map object
Other map:
map_add_mask_water(),
print.map(),
rast.map()
data <- lapply(1:10, \(x) matrix(runif(5000), nrow = 50, ncol = 100)) scale <- 10 extent <- c(0, 10, 0, 5) seq(as.Date("2023-01-01"), as.Date("2023-01-10"), by = "day") stap <- data.frame( stap_id = 1:10, start = seq(as.POSIXct("2023-01-01", tz = "UTC"), as.POSIXct("2023-01-10 UTC", tz = "UTC"), by = "day" ), include = TRUE ) stap$end <- stap$start + sample(1:10) * 10000 # Create the map map <- map_create( data = data, extent = extent, scale = scale, stap = stap, id = "18LX", type = "pressure" ) print(map) plot(map)data <- lapply(1:10, \(x) matrix(runif(5000), nrow = 50, ncol = 100)) scale <- 10 extent <- c(0, 10, 0, 5) seq(as.Date("2023-01-01"), as.Date("2023-01-10"), by = "day") stap <- data.frame( stap_id = 1:10, start = seq(as.POSIXct("2023-01-01", tz = "UTC"), as.POSIXct("2023-01-10 UTC", tz = "UTC"), by = "day" ), include = TRUE ) stap$end <- stap$start + sample(1:10) * 10000 # Create the map map <- map_create( data = data, extent = extent, scale = scale, stap = stap, id = "18LX", type = "pressure" ) print(map) plot(map)
extent and scale
Take the two parameters defining the spatial grid of a map in GeoPressureR (extent and scale)
and constructs various possible spatial variable of interest for the spatial grid (e.g., grid
dimension, latitude and longitude...)
This function is used in multiple functions of GeoPressureR to allow to only store extent and
scale in tag and graph while having access to all spatial variables anywhere anytime.
map_expand(extent, scale)map_expand(extent, scale)
extent |
geographical extent of the map on which the likelihood and graph model will be
computed. Vector of length 4 |
scale |
number of pixels per 1° latitude-longitude. For instance, |
A list containing:
extent same as input
scale same as input
lat vector of latitude
lon vector of longitude
dim vector of length 2 of the dimension of the map (number of pixel in lat and lon)
str(map_expand(extent = c(0, 10, 0, 5), scale = 1)) str(map_expand(extent = c(-16, 23, 0, 50), scale = 10))str(map_expand(extent = c(0, 10, 0, 5), scale = 1)) str(map_expand(extent = c(-16, 23, 0, 50), scale = 10))
param listCreate the list of parameter for GeoPressureR tag and graph objects.
param list are mostly used to archived the actual value of parameters used to create a tag
and/or a graph, thus allowing for examination of parameters post-creation. This function should
therefore not be used to set/define parameters ahead of computation. In reality, there are very
few external case of use for this function.
param_create(id, default = FALSE, ...)param_create(id, default = FALSE, ...)
id |
Unique identifier of a tag. |
default |
logical to initiate param with default value of the package. |
... |
arguments passed to other methods. |
A GeoPressureR param list
Other param:
print.param()
param <- param_create("18LX", default = TRUE) print(param)param <- param_create("18LX", default = TRUE) print(param)
path from a graph
Retrieve the edges in a graph corresponding to the flight transition defined by a path. These
edges can be useful to extract flight information specific to a path.
path2edge(path, tag_graph)path2edge(path, tag_graph)
path |
a GeoPressureR |
tag_graph |
either a |
Data.frame of the edge containing:
s: index in 3D (lat-lon-stap) of the origin (source).
t: index in 3D (lat-lon-stap) of the destination (target).
lat_s: latitude of the origin (source).
lat_t: latitude of the destination (target).
lon_s: longitude of the origin (source).
lon_t: longitude of the destination (target).
stap_s: stationary period of the origin (source).
stap_t: stationary period of the destination (target).
distance: Distance (in km) of the flight.
start: end of the flight.
end: start of the flight.
duration: duration of the flight.
n: number of flight.
bearing: Angle of the flight in degree (0° = North, 90° = East).
gs: groundspeed vector expressed as a complex number. You can compute the groundspeed value
(km/h) with abs(gs), the W-E and S-N component of the flight with Re(gs) and Im(gs), and
the angle/direction with Arg(gs). If graph provided.
ws: if computed with graph_add_wind(), same value as gs. Airspeed is computed with
as = gs - ws in complex number to keep the vectorial additive properties. If graph provided.
Other path:
path2elevation(),
path2twilight(),
plot_path(),
tag2path()
edge <- path2edge(path, tag)edge <- path2edge(path, tag)
This function is a wrapper of the GeoPressureAPI elevationPath entry point. It queries the ground
elevation from SRTM (SRTM90_V4) along a polyline
specify by path.
Because the position are often defined on a relative coarse scale (e.g., 0.25° ~ 29km),
you can request the elevation at a specify resolution defined by scale and return pre-defined
percentile of the elevation at this resolution.
The returned data.frame provide the ground elevation along the path with a resolution defined by
sampling_scale.
path2elevation( path, scale = 4, sampling_scale = scale, percentile = c(10, 50, 90), debug = FALSE )path2elevation( path, scale = 4, sampling_scale = scale, percentile = c(10, 50, 90), debug = FALSE )
path |
a GeoPressureR |
scale |
spatial resolution of the SRTM to use to query the elevation. |
sampling_scale |
spatial resolution of the point along the polyline on which the SRTM is
estimated. Same unit as |
percentile |
percentile of the ground elevation distribution found within each grid cell
of the SRTM at the resolution defined by |
debug |
logical to display additional information to debug a request |
A data.frame containing
stap_id numeric value corresponding to the ratio of distance between position of known stap
lon
lat
distance distance in km along the path starting at the first stap_id
Other path:
path2edge(),
path2twilight(),
plot_path(),
tag2path()
# Create a path path <- data.frame( lon = c(8.47, 9.41, 9.01, -0.91, 14.24, 27.30, 34.39, 30.00), lat = c(48.89, 44.78, 40.07, 37.68, 17.33, 7.32, 8.09, -23.13), start = as.POSIXct( c( "2017-05-01 00:42", "2017-05-03 01:22", "2017-05-03 22:47", "2017-05-06 03:32", "2017-05-07 01:12", "2017-05-07 22:32", "2017-05-09 21:52", "2017-05-10 21:12" ), tz = "UTC" ), end = as.POSIXct( c( "2017-05-02 22:12", "2017-05-03 20:12", "2017-05-06 02:47", "2017-05-06 23:22", "2017-05-07 17:42", "2017-05-09 20:27", "2017-05-10 19:57", "2017-05-11 21:17" ), tz = "UTC" ), stap_id = seq(1, 8) ) plot_path(path) elevation <- path2elevation(path) plot(elevation$distance, elevation$X50, type = "l", ylab = "Elevation (m)", xlab = "Distance from start (km)" ) lines(elevation$distance, elevation$X10, lty = 5) lines(elevation$distance, elevation$X90, lty = 5) id <- elevation$stap_id %% 1 == 0 points(elevation$distance[id], elevation$X90[id], col = "red")# Create a path path <- data.frame( lon = c(8.47, 9.41, 9.01, -0.91, 14.24, 27.30, 34.39, 30.00), lat = c(48.89, 44.78, 40.07, 37.68, 17.33, 7.32, 8.09, -23.13), start = as.POSIXct( c( "2017-05-01 00:42", "2017-05-03 01:22", "2017-05-03 22:47", "2017-05-06 03:32", "2017-05-07 01:12", "2017-05-07 22:32", "2017-05-09 21:52", "2017-05-10 21:12" ), tz = "UTC" ), end = as.POSIXct( c( "2017-05-02 22:12", "2017-05-03 20:12", "2017-05-06 02:47", "2017-05-06 23:22", "2017-05-07 17:42", "2017-05-09 20:27", "2017-05-10 19:57", "2017-05-11 21:17" ), tz = "UTC" ), stap_id = seq(1, 8) ) plot_path(path) elevation <- path2elevation(path) plot(elevation$distance, elevation$X50, type = "l", ylab = "Elevation (m)", xlab = "Distance from start (km)" ) lines(elevation$distance, elevation$X10, lty = 5) lines(elevation$distance, elevation$X90, lty = 5) id <- elevation$stap_id %% 1 == 0 points(elevation$distance[id], elevation$X90[id], col = "red")
path (positions and dates)This function computes the theoretical twilight (i.e., datetime of sunrise and sunset) at given locations and for specific date.
We use the suntools package for this.
By default (solar_dep=0), the computation returns sunrise and sunset. But, it is also possible
to compute different twilights by setting depression angle value greater than 0 (6° for civil,
12° for nautical and 18° for astronomical). The corresponding solar elevation threshold is
-solar_dep, and the equivalent solar zenith angle is 90 + solar_dep.
path2twilight(path, date = NULL, solar_dep = 0, return_long = TRUE)path2twilight(path, date = NULL, solar_dep = 0, return_long = TRUE)
path |
a GeoPressureR |
date |
a vector of POSIXt datetime for which sunrise and sunset are computed. Be default,
uses the range of |
solar_dep |
a numerical value representing the solar depression angle used to compute
sunrise and sunset. The corresponding solar elevation threshold is |
return_long |
logical defining the format of the data.frame returned. If |
if return_long == TRUE, a twilight data.frame (same as twilight_create()) with
columns:
date same as input date
twilight date-time of twilight
rise logical indicating sunrise (TRUE) or sunset (FALSE).
stap_id same as path$stap_id
lat same as path$lat
lon same as path$lon
if return_long == FALSE, a data.frame with the same size of date with columns:
date same as input date
sunrise date-time of sunrise
sunset date-time of sunset
stap_id same as path$stap_id
lat same as path$lat
lon same as path$lon
Other path:
path2edge(),
path2elevation(),
plot_path(),
tag2path()
path <- data.frame( stap_id = c(1, 2, 3, 4, 5), j = c(1, 1, 1, 1, 1), ind = c(1652L, 1603L, 1505L, 1609L, 1463L), lat = c(48.9, 47.5, 45.5, 41.5, 37.5), lon = c(17.05, 16.5, 14.5, 16.5, 13.5), start = as.POSIXct( c(1501113450, 1501888650, 1501987950, 1502075550, 1502151150), tzone = "UTC" ), end = as.POSIXct(c(1501876050, 1501961250, 1502046750, 1502133150, 1502323050), tzone = "UTC"), include = c(TRUE, TRUE, TRUE, TRUE, TRUE), known = c(TRUE, FALSE, FALSE, FALSE, FALSE), interp = c(FALSE, FALSE, FALSE, FALSE, FALSE) ) twl <- path2twilight(path)path <- data.frame( stap_id = c(1, 2, 3, 4, 5), j = c(1, 1, 1, 1, 1), ind = c(1652L, 1603L, 1505L, 1609L, 1463L), lat = c(48.9, 47.5, 45.5, 41.5, 37.5), lon = c(17.05, 16.5, 14.5, 16.5, 13.5), start = as.POSIXct( c(1501113450, 1501888650, 1501987950, 1502075550, 1502151150), tzone = "UTC" ), end = as.POSIXct(c(1501876050, 1501961250, 1502046750, 1502133150, 1502323050), tzone = "UTC"), include = c(TRUE, TRUE, TRUE, TRUE, TRUE), known = c(TRUE, FALSE, FALSE, FALSE, FALSE), interp = c(FALSE, FALSE, FALSE, FALSE, FALSE) ) twl <- path2twilight(path)
graph
This function display a plot of pressure time series recorded by a tag
plot_graph_movement(graph, speed = seq(0, 120), plot_plotly = FALSE)plot_graph_movement(graph, speed = seq(0, 120), plot_plotly = FALSE)
graph |
a GeoPressureR |
speed |
Vector of speed value (km/h) used on the x-axis. |
plot_plotly |
logical to use |
a plot or ggplotly object.
Other movement:
bird_create(),
graph_set_movement(),
speed2prob(),
tag_download_wind()
movement_gamma <- list( type = "gs", method = "gamma", shape = 7, scale = 7, low_speed_fix = 15, zero_speed_ratio = 1 ) plot_graph_movement(movement_gamma) movement_logis <- list( type = "gs", method = "logis", scale = 7, location = 40, low_speed_fix = 15, zero_speed_ratio = 1 ) plot_graph_movement(movement_logis) bird <- bird_create("Example bird", mass = 0.1, wing_span = 0.4, wing_aspect = 7) movement_power <- list( type = "as", method = "power", bird = bird, power2prob = \(power) (1 / power)^3, low_speed_fix = 15, zero_speed_ratio = 1 ) plot_graph_movement(movement_power)movement_gamma <- list( type = "gs", method = "gamma", shape = 7, scale = 7, low_speed_fix = 15, zero_speed_ratio = 1 ) plot_graph_movement(movement_gamma) movement_logis <- list( type = "gs", method = "logis", scale = 7, location = 40, low_speed_fix = 15, zero_speed_ratio = 1 ) plot_graph_movement(movement_logis) bird <- bird_create("Example bird", mass = 0.1, wing_span = 0.4, wing_aspect = 7) movement_power <- list( type = "as", method = "power", bird = bird, power2prob = \(power) (1 / power)^3, low_speed_fix = 15, zero_speed_ratio = 1 ) plot_graph_movement(movement_power)
path
This function plots a path data.frame. This function is used in plot.map().
plot_path( path, plot_leaflet = TRUE, map = NULL, provider = NULL, provider_options = leaflet::providerTileOptions(), pad = 3, polyline = NULL, circle = NULL, group = NULL )plot_path( path, plot_leaflet = TRUE, map = NULL, provider = NULL, provider_options = leaflet::providerTileOptions(), pad = 3, polyline = NULL, circle = NULL, group = NULL )
path |
a GeoPressureR |
plot_leaflet |
logical defining if the plot is an interactive |
map |
optional |
provider |
optional tile provider name (see |
provider_options |
tile options. See leaflet::addProviderTiles() and leaflet::providerTileOptions(). |
pad |
padding of the map in degree lat-lon (only for |
polyline |
list of parameters passed to |
circle |
list of parameters passed to |
group |
optional Leaflet overlay group name. When supplied, all
trajectories in |
A leaflet map when plot_leaflet = TRUE, otherwise a ggplot2 object.
Interactive maps always offer Esri basemaps (gray canvas, imagery and topographic). CARTO, Mapbox and MapTiler basemaps are added to the layer control only when their API key is stored in your system keyring. Get a key from each provider:
CARTO: "Get your API key" on CARTO Basemaps.
Mapbox: Access tokens page of your account (see Mapbox documentation).
MapTiler: API keys page of your MapTiler Cloud account (see MapTiler documentation).
Then store each key once:
keyring::key_set_with_value("CARTO_API_KEY", password = "<your CARTO API key>")
keyring::key_set_with_value("MAPBOX_ACCESS_TOKEN", password = "<your Mapbox token>")
keyring::key_set_with_value("MAPTILER_API_KEY", password = "<your MapTiler API key>")
Mapbox access tokens are visible in the browser when a map is rendered. Use a public, read-only token rather than a secret token.
Other path:
path2edge(),
path2elevation(),
path2twilight(),
tag2path()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) path <- data.frame( stap_id = 1:4, lon = c(17.05, 16.2, NA, 15.4), lat = c(48.9, 47.8, NA, 46.5), known_lon = c(17.05, NA, NA, NA), known_lat = c(48.9, NA, NA, NA), start = as.POSIXct( c("2018-01-01", "2018-01-03", "2018-01-05", "2018-01-07"), tz = "UTC" ), end = as.POSIXct( c("2018-01-02", "2018-01-04", "2018-01-06", "2018-01-08"), tz = "UTC" ) ) plot_path(path) plot_path(path, plot_leaflet = FALSE)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) path <- data.frame( stap_id = 1:4, lon = c(17.05, 16.2, NA, 15.4), lat = c(48.9, 47.8, NA, 46.5), known_lon = c(17.05, NA, NA, NA), known_lat = c(48.9, NA, NA, NA), start = as.POSIXct( c("2018-01-01", "2018-01-03", "2018-01-05", "2018-01-07"), tz = "UTC" ), end = as.POSIXct( c("2018-01-02", "2018-01-04", "2018-01-06", "2018-01-08"), tz = "UTC" ) ) plot_path(path) plot_path(path, plot_leaflet = FALSE)
pressurepath
Display a pressurepath data.frame as a time series or histogram
plot_pressurepath( pressurepath, type = "timeseries", sd = attr(pressurepath, "sd"), warning_std_thr = 3, plot_plotly = TRUE )plot_pressurepath( pressurepath, type = "timeseries", sd = attr(pressurepath, "sd"), warning_std_thr = 3, plot_plotly = TRUE )
pressurepath |
a GeoPressureR |
type |
|
sd |
standard deviation of the pressure error. Numeric of length 1 or number of stationary periods. |
warning_std_thr |
Threshold of outlier, coefficient of the z-score |
plot_plotly |
logical to use |
a plot or ggplotly object.
Other pressurepath:
geopressure_timeseries(),
pressurepath_create(),
pressurepath_variable_available()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) path <- data.frame( stap_id = tag$stap$stap_id, lat = c(48.5, 32.5, 30.5, 49.5, 41.6), lon = c(17.5, 13.5, 16.5, 21.5, 12.7) ) pressurepath <- pressurepath_create(tag, path = path, quiet = TRUE) plot_pressurepath(pressurepath) plot_pressurepath(pressurepath, type = "histogram") plot_pressurepath(pressurepath, type = "altitude")withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) path <- data.frame( stap_id = tag$stap$stap_id, lat = c(48.5, 32.5, 30.5, 49.5, 41.6), lon = c(17.5, 13.5, 16.5, 21.5, 12.7) ) pressurepath <- pressurepath_create(tag, path = path, quiet = TRUE) plot_pressurepath(pressurepath) plot_pressurepath(pressurepath, type = "histogram") plot_pressurepath(pressurepath, type = "altitude")
tag
This function display a plot of acceleration time series recorded by a tag
plot_tag_acceleration( tag, variable = "activity", plot_plotly = TRUE, label_auto = TRUE, min_duration = 30 )plot_tag_acceleration( tag, variable = "activity", plot_plotly = TRUE, label_auto = TRUE, min_duration = 30 )
tag |
a GeoPressureR |
variable |
type of acceleration variable to plot |
plot_plotly |
logical to use |
label_auto |
logical to compute and plot the flight label using |
min_duration |
Minimal duration (in minutes) to consider a high activity as migratory flight. |
a plot or ggplotly object.
Other plot_tag:
plot_tag_actogram(),
plot_tag_light(),
plot_tag_pressure(),
plot_tag_temperature(),
plot_tag_twilight()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) }) plot_tag_acceleration(tag)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) }) plot_tag_acceleration(tag)
tag
This function display a plot of the acceleration time series recorded by a tag
plot_tag_actogram( tag, twl_offset = NULL, plot_plotly = TRUE, flip_axes = FALSE, double_plot = FALSE )plot_tag_actogram( tag, twl_offset = NULL, plot_plotly = TRUE, flip_axes = FALSE, double_plot = FALSE )
tag |
a GeoPressureR |
twl_offset |
Shift of the middle of the night compared to 00:00 UTC (in hours). If not provided, it uses the middle of all nights. |
plot_plotly |
logical to use |
flip_axes |
logical to place time on the x-axis and dates on the y-axis. Dates increase downward in the flipped display. |
double_plot |
logical to display a 48-hour window. The second 24-hour half contains the following day's observations. |
a ggplot or ggplotly object.
Other plot_tag:
plot_tag_acceleration(),
plot_tag_light(),
plot_tag_pressure(),
plot_tag_temperature(),
plot_tag_twilight()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) plot_tag_actogram(tag, plot_plotly = TRUE) })withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) plot_tag_actogram(tag, plot_plotly = TRUE) })
tag
This function display a plot of light time series recorded by a tag
plot_tag_light(tag, transform_light = TRUE, plot_plotly = TRUE)plot_tag_light(tag, transform_light = TRUE, plot_plotly = TRUE)
tag |
a GeoPressureR |
transform_light |
logical to display a log transformation of light |
plot_plotly |
logical to use |
a plot or ggplotly object.
Other plot_tag:
plot_tag_acceleration(),
plot_tag_actogram(),
plot_tag_pressure(),
plot_tag_temperature(),
plot_tag_twilight()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) }) plot_tag_light(tag)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) }) plot_tag_light(tag)
tag
This function display a plot of pressure time series recorded by a tag
plot_tag_pressure(tag, plot_plotly = TRUE, warning_pressure_diff = 3)plot_tag_pressure(tag, plot_plotly = TRUE, warning_pressure_diff = 3)
tag |
a GeoPressureR |
plot_plotly |
logical to use |
warning_pressure_diff |
Threshold of pressure hourly difference marking as warning (hPa). |
a plot or ggplotly object.
Other plot_tag:
plot_tag_acceleration(),
plot_tag_actogram(),
plot_tag_light(),
plot_tag_temperature(),
plot_tag_twilight()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) }) plot_tag_pressure(tag, plot_plotly = FALSE) withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_label(tag, quiet = TRUE) }) plot_tag_pressure(tag)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) }) plot_tag_pressure(tag, plot_plotly = FALSE) withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_label(tag, quiet = TRUE) }) plot_tag_pressure(tag)
tag
This function display a plot of temperature time series recorded by a tag
plot_tag_temperature(tag, variable = "external", plot_plotly = TRUE)plot_tag_temperature(tag, variable = "external", plot_plotly = TRUE)
tag |
a GeoPressureR |
variable |
temperature variable to plot |
plot_plotly |
logical to use |
a plot or ggplotly object.
Other plot_tag:
plot_tag_acceleration(),
plot_tag_actogram(),
plot_tag_light(),
plot_tag_pressure(),
plot_tag_twilight()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) }) plot_tag_temperature(tag)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) }) plot_tag_temperature(tag)
tag
This function display a plot of twilight time series recorded by a tag
plot_tag_twilight( tag, twilight_line = NULL, transform_light = TRUE, twl_offset = NULL, plot_plotly = TRUE, flip_axes = FALSE, double_plot = FALSE )plot_tag_twilight( tag, twilight_line = NULL, transform_light = TRUE, twl_offset = NULL, plot_plotly = TRUE, flip_axes = FALSE, double_plot = FALSE )
tag |
a GeoPressureR |
twilight_line |
a twilight data.frame typically created with |
transform_light |
logical to use a log transformation of light |
twl_offset |
Shift of the middle of the night compared to 00:00 UTC (in hours). If not provided, it uses the middle of all nights. |
plot_plotly |
logical to use |
flip_axes |
logical to place time on the x-axis and dates on the y-axis. Dates increase downward in the flipped display. |
double_plot |
logical to display a 48-hour window. The second 24-hour half contains the following day's observations. |
a ggplot or ggplotly object.
Other plot_tag:
plot_tag_acceleration(),
plot_tag_actogram(),
plot_tag_light(),
plot_tag_pressure(),
plot_tag_temperature()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) plot_tag_twilight(tag, plot_plotly = TRUE) tag <- tag_label(tag, quiet = TRUE) plot_tag_twilight(tag) })withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) plot_tag_twilight(tag, plot_plotly = TRUE) tag <- tag_label(tag, quiet = TRUE) plot_tag_twilight(tag) })
This function plots the stacked calibration histogram and fitted density, with calibration
stationary periods labeled as known or fitted anchors. Refined fitted anchors remain labeled as
fitted. If a path is provided, it instead plots the solar zenith angle histogram derived from
tag$twilight and the path, with the calibration density overlaid.
plot_twl_calib(x, path = NULL, warning_ci = 0.95, plot_plotly = TRUE, ...) plot_twl_calib_path(tag, path, warning_ci = 0.9973, plot_plotly = TRUE)plot_twl_calib(x, path = NULL, warning_ci = 0.95, plot_plotly = TRUE, ...) plot_twl_calib_path(tag, path, warning_ci = 0.9973, plot_plotly = TRUE)
x |
a GeoPressureR |
path |
a GeoPressureR |
warning_ci |
Width of the symmetric confidence interval used to flag staps with twilights
outside the calibrated range (e.g., |
plot_plotly |
logical to use |
... |
unused |
tag |
a GeoPressureR |
a ggplot or ggplotly object
Other geolight:
geolight_fit_location(),
geolight_map(),
geolight_solar(),
twilight_create(),
twilight_label_read(),
twilight_label_write()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 5, known = data.frame( stap_id = 1, known_lon = 17.05, known_lat = 48.9 ) ) |> twilight_create() |> twilight_label_read() |> geolight_map_calibrate() }) # Histogram + kernel density plot_twl_calib(tag) # With fitted location duration of 5 days minimum tag <- geolight_map_calibrate(tag, fitted_location_duration = 5) # Path-based diagnostic (uses tag$twilight) path <- tag$stap[, c("stap_id", "start", "end")] path$lon <- ifelse(is.na(tag$stap$known_lon), 0, tag$stap$known_lon) path$lat <- ifelse(is.na(tag$stap$known_lat), 0, tag$stap$known_lat) plot_twl_calib(tag, path = path, plot_plotly = FALSE)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 5, known = data.frame( stap_id = 1, known_lon = 17.05, known_lat = 48.9 ) ) |> twilight_create() |> twilight_label_read() |> geolight_map_calibrate() }) # Histogram + kernel density plot_twl_calib(tag) # With fitted location duration of 5 days minimum tag <- geolight_map_calibrate(tag, fitted_location_duration = 5) # Path-based diagnostic (uses tag$twilight) path <- tag$stap[, c("stap_id", "start", "end")] path$lon <- ifelse(is.na(tag$stap$known_lon), 0, tag$stap$known_lon) path$lat <- ifelse(is.na(tag$stap$known_lat), 0, tag$stap$known_lat) plot_twl_calib(tag, path = path, plot_plotly = FALSE)
map objectThis function plots a GeoPressureR map object.
You can plot on top of the map a path, this uses the plot_path() function.
Our maps are defined in lat-lon (i.e., EPSG:4326), but the display of maps on web map are
nearly always in web mercator (i.e.,
EPSG:3857). We therefore need to reproject our map for display.
However, we don't really want to interpolate the map as each pixel might be important to
visualize. We therefore re-project with a near-neighbour interpolation (method = "near"
in terra::project()). Yet to avoid having pixel misplaced, we generally need to use a
projection with a finer resolution. The argument fac_res_proj controls the relative change of
resolution between the original map to the projected map.
## S3 method for class 'map' plot( x, path = NULL, thr_likelihood = 1, plot_leaflet = TRUE, provider = NULL, provider_options = leaflet::providerTileOptions(), palette = NULL, opacity = 0.8, legend = FALSE, fac_res_proj = 4, ... )## S3 method for class 'map' plot( x, path = NULL, thr_likelihood = 1, plot_leaflet = TRUE, provider = NULL, provider_options = leaflet::providerTileOptions(), palette = NULL, opacity = 0.8, legend = FALSE, fac_res_proj = 4, ... )
x |
a GeoPressureR |
path |
a GeoPressureR |
thr_likelihood |
Threshold to display likelihood values. |
plot_leaflet |
logical to use an interactive |
provider |
optional tile provider name (see |
provider_options |
tile options. See leaflet::addProviderTiles() and leaflet::providerTileOptions(). |
palette |
color palette name or vector of colors. |
opacity |
opacity of the raster layer in leaflet. |
legend |
logical to display the legend. |
fac_res_proj |
Factor of the resolution of the reprojection (see details above). A value of
|
... |
additional parameters passed to |
a plot or leaflet object.
Interactive maps always offer Esri basemaps (gray canvas, imagery and topographic). CARTO, Mapbox and MapTiler basemaps are added to the layer control only when their API key is stored in your system keyring. Get a key from each provider:
CARTO: "Get your API key" on CARTO Basemaps.
Mapbox: Access tokens page of your account (see Mapbox documentation).
MapTiler: API keys page of your MapTiler Cloud account (see MapTiler documentation).
Then store each key once:
keyring::key_set_with_value("CARTO_API_KEY", password = "<your CARTO API key>")
keyring::key_set_with_value("MAPBOX_ACCESS_TOKEN", password = "<your Mapbox token>")
keyring::key_set_with_value("MAPTILER_API_KEY", password = "<your MapTiler API key>")
Mapbox access tokens are visible in the browser when a map is rendered. Use a public, read-only token rather than a secret token.
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 4 ) |> geopressure_map(quiet = TRUE) }) plot(tag$map_pressure) plot(tag$map_pressure, plot_leaflet = FALSE) # `thr_likelihood` can be used to visualize its effect in `graph_create` plot(tag$map_pressure, thr_likelihood = 0.9, palette = "viridis", opacity = 1, provider = "Esri.WorldGrayCanvas" )withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 4 ) |> geopressure_map(quiet = TRUE) }) plot(tag$map_pressure) plot(tag$map_pressure, plot_leaflet = FALSE) # `thr_likelihood` can be used to visualize its effect in `graph_create` plot(tag$map_pressure, thr_likelihood = 0.9, palette = "viridis", opacity = 1, provider = "Esri.WorldGrayCanvas" )
tag objectThis function plots a GeoPressureR tag object as a time series or a map.
By default, type is determined in the following order of preference according to availability:
c("map_pressure", "map_light"), "map_pressure", "map_light", "pressure".
plot.tag() calls different plotting functions depending on type.
"pressure": plot_tag_pressure()
"light": plot_tag_light()
"acceleration": plot_tag_acceleration()
"temperature": plot_tag_temperature()
"twilight": plot_tag_twilight()
"actogram": plot_tag_actogram()
"map_*" : plot.map() with tag$map_* as first argument.
Refers to these functions for additional parameters and more flexibility in the plotting.
## S3 method for class 'tag' plot(x, type = NULL, ...)## S3 method for class 'tag' plot(x, type = NULL, ...)
x |
a GeoPressureR |
type |
type of the plot to display. One of |
... |
additional parameters for |
a plot, ggplotly or leaflet object.
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() }) # By default, plot will display the time series of pressure plot(tag) # Change the `type` to display other sensor plot(tag, type = "acceleration") plot(tag, type = "light") plot(tag, type = "temperature") plot(tag, type = "twilight") plot(tag, type = "actogram") # After you compute any likelihood map, the default will # become this map (i.e., `type = "map"`) tag <- tag_set_map(tag, extent = c(-16, 23, 0, 50), scale = 4, known = data.frame( stap_id = 1, known_lon = 17.05, known_lat = 48.9 ) ) |> geopressure_map(quiet = TRUE) plot(tag) # The likelihood map of light can be display with tag <- geolight_map(tag, quiet = TRUE) plot(tag, type = "map_light") # When both pressure and light likelihood are present, # the default is to display their products, equivalent # to choose `type = c("map_pressure", "map_light")` plot(tag)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() }) # By default, plot will display the time series of pressure plot(tag) # Change the `type` to display other sensor plot(tag, type = "acceleration") plot(tag, type = "light") plot(tag, type = "temperature") plot(tag, type = "twilight") plot(tag, type = "actogram") # After you compute any likelihood map, the default will # become this map (i.e., `type = "map"`) tag <- tag_set_map(tag, extent = c(-16, 23, 0, 50), scale = 4, known = data.frame( stap_id = 1, known_lon = 17.05, known_lat = 48.9 ) ) |> geopressure_map(quiet = TRUE) plot(tag) # The likelihood map of light can be display with tag <- geolight_map(tag, quiet = TRUE) plot(tag, type = "map_light") # When both pressure and light likelihood are present, # the default is to display their products, equivalent # to choose `type = c("map_pressure", "map_light")` plot(tag)
pressurepath_create() combines a tag pressure series with a path and retrieves matching ERA5
variables. Positions during flights are linearly interpolated between stationary periods.
pressurepath_create_arco() and pressurepath_create_api() are shortcuts that force the
corresponding source.
pressurepath_create( tag, path = tag2path(tag), variable = c("altitude", "surface_pressure"), solar_dep = 0, era5_dataset = "both", preprocess = FALSE, workers = "auto", quiet = FALSE, debug = FALSE, source = c("auto", "arco", "api") ) pressurepath_create_api( tag, path = tag2path(tag), variable = c("altitude", "surface_pressure"), solar_dep = 0, era5_dataset = "both", preprocess = FALSE, workers = "auto", quiet = FALSE, debug = FALSE ) pressurepath_create_arco( tag, path = tag2path(tag), variable = c("altitude", "surface_pressure"), solar_dep = 0, era5_dataset = "both", preprocess = FALSE, quiet = FALSE, debug = FALSE )pressurepath_create( tag, path = tag2path(tag), variable = c("altitude", "surface_pressure"), solar_dep = 0, era5_dataset = "both", preprocess = FALSE, workers = "auto", quiet = FALSE, debug = FALSE, source = c("auto", "arco", "api") ) pressurepath_create_api( tag, path = tag2path(tag), variable = c("altitude", "surface_pressure"), solar_dep = 0, era5_dataset = "both", preprocess = FALSE, workers = "auto", quiet = FALSE, debug = FALSE ) pressurepath_create_arco( tag, path = tag2path(tag), variable = c("altitude", "surface_pressure"), solar_dep = 0, era5_dataset = "both", preprocess = FALSE, quiet = FALSE, debug = FALSE )
tag |
A GeoPressureR |
path |
A GeoPressureR |
variable |
ERA5 variables to retrieve, named as in the
ERA5 catalogue,
plus the derived |
solar_dep |
Solar depression angle used to compute sunrise and sunset, or |
era5_dataset |
ERA5 product: |
preprocess |
Whether to preprocess pressure with |
workers |
Number of parallel GeoPressureAPI requests, or |
quiet |
Logical to suppress progress messages. |
debug |
Logical to display request details. |
source |
Data source: |
A pressurepath data.frame containing tag pressure, coordinates, requested ERA5
variables, normalised surface pressure, and optional sunrise and sunset times.
source = "arco" reads ECMWF's Analysis-Ready Cloud-Optimised (ARCO) archive directly. It
requires an ECMWF API key and the optional Rarr and ecmwfr packages. variable uses the
same names as the hosted API, but the archive carries fewer of them: 20 for
era5_dataset = "single-levels", 16 for "land", and the 8 they share for "both", plus the
derived "altitude". Use pressurepath_variable_available() to list them.
source = "api" uses the hosted GeoPressureAPI. It needs no ECMWF key or Rarr installation
and reaches the full Earth Engine band set: 292 variables for era5_dataset = "single-levels"
and "both", 70 for "land".
The default, source = "auto", uses ARCO when a key stored by ecmwfr::wf_set_key() is
available and GeoPressureAPI otherwise. Use pressurepath_create_arco() or
pressurepath_create_api() to select a backend explicitly.
Measurements are retained only when path contains the surrounding stationary periods.
Coordinates during flights are interpolated linearly, while ERA5 values are sampled at the
nearest grid cell and hour. era5_dataset = "single-levels" uses 0.25 degree global ERA5,
"land" uses 0.1 degree ERA5-Land, and "both" selects ERA5-Land over land and global ERA5
over water.
Surface pressure is returned in hPa and normalised to the mean tag pressure within each
stationary-period and elevation-label group. Observations labelled "discard" are excluded
from those means. If solar_dep is not NULL, local sunrise and sunset are added.
When altitude is produced, GeoPressureR uses the same barometric relation as GeoPressureAPI:
Here, is tag pressure, while , ,
and
are ERA5 surface pressure, 2 m temperature, and model-surface elevation. Model-surface elevation
is obtained from ERA5 surface geopotential divided by standard gravity. The constants are the
standard temperature lapse rate K/m, universal gas constant
J/(mol K), standard gravity m/s², and molar mass of dry air
kg/mol. Pressure is converted to Pa internally and altitude is returned in
metres above mean sea level.
era5_dataset
Use era5_dataset = "single-levels" whenever altitude is computed.
ERA5-Land's surface_pressure is not the exact hydrostatic image of the orography ERA5-Land
publishes as geopotential — the two disagree by up to ~10 hPa in steep terrain. The
term therefore fails to cancel from the relation above and the whole discrepancy
lands in the retrieved altitude. Measured against 41,653 hourly station-pressure observations
from 271 NOAA ISD stations (2–3576 m, Alps, July 2020), compared with surveyed station
elevation:
era5_dataset |
bias | MAE | RMSE |
"single-levels" |
−0.6 m | 9.0 m | 27.4 m |
"land" / "both" |
+2.5 m | 55.3 m | 76.9 m |
ERA5-Land replays the land component of ERA5 and assimilates no atmospheric observations of its
own, so it carries no independent information about absolute altitude. Substituting the
orography implied by its own surface pressure removes the error exactly and reproduces
"single-levels" to 0.1 m.
"land" and "both" remain the defaults for backward compatibility. They are appropriate for
retrieving other variables at 0.1 degree resolution, and for geopressure_map(), whose
pressure mismatch is differential and unaffected.
With era5_dataset = "single-levels" the altitude error separates into two parts that behave
very differently. A static per-site offset (median 3.7 m, p90 15 m) reflects station metadata
and sub-grid terrain and does not vary in time, while the temporal scatter (median SD 3.1 m,
p90 7.7 m) is the actual reanalysis error. Expect roughly 3 m for relative altitude changes
at a fixed location and 10 m mean absolute error for absolute altitude, degrading to tens
of metres in steep terrain — where it is a fixed offset rather than noise. Precision is nearly
independent of flight altitude: de-biased RMSE stays 2–7 m up to 1000 m above the model surface
and about 12 m at 1000–3000 m above it.
total_precipitation, surface_solar_radiation_downwards and
surface_thermal_radiation_downwards do not mean the same thing across backends when
era5_dataset = "land". GeoPressureAPI serves Earth Engine's ERA5-Land collection, where these
bands are overwritten by their *_hourly counterparts and are therefore hourly increments.
ARCO serves ECMWF's own ERA5-Land fields, which accumulate from 00 UTC. For
era5_dataset = "single-levels" both are hourly and agree. Take the difference between
consecutive hours if you need increments from ARCO over land.
ARCO access and CDS downloads use the same ECMWF Personal Access Token. Create an ECMWF account, copy the token from your Climate Data Store profile, accept the dataset licence terms, and store the token once in your system keyring:
ecmwfr::wf_set_key("your-personal-access-token")
Do not put the token in a script or commit it to version control. GeoPressureR retrieves the
stored token with ecmwfr::wf_get_key() for all ECMWF-backed functions, including
geopressure_timeseries(), pressurepath_create(), and tag_download_wind().
Other pressurepath:
geopressure_timeseries(),
plot_pressurepath(),
pressurepath_variable_available()
pressurepath <- pressurepath_create(tag, path)pressurepath <- pressurepath_create(tag, path)
The variables available to pressurepath_create() depend on both the backend and the ERA5
product, and the sets genuinely differ. GeoPressureAPI serves whatever bands the underlying
Earth Engine collection carries: 292 for ERA5 single levels against 70 for ERA5-Land, with only
44 in common. era5_dataset = "both" mosaics ERA5-Land on top of ERA5 but returns ERA5's band
namespace, so its set equals "single-levels" and ERA5-Land-only bands are dropped. The ARCO
backend reads ECMWF's zarr stores directly and currently maps only surface pressure and 2 m
temperature, so it can return "surface_pressure" and the derived "altitude".
pressurepath_variable_available( source = c("api", "arco"), era5_dataset = c("single-levels", "land", "both") )pressurepath_variable_available( source = c("api", "arco"), era5_dataset = c("single-levels", "land", "both") )
source |
Backend: |
era5_dataset |
ERA5 product: |
Requesting a variable the chosen product does not have used to fail silently: GeoPressureAPI
returned 200 success with every array empty — not just the missing one — which arrived as a
pressurepath whose ERA5 columns were all NA. pressurepath_create() now validates the
request up front with this list.
A character vector of variable names accepted by variable, including "altitude".
Other pressurepath:
geopressure_timeseries(),
plot_pressurepath(),
pressurepath_create()
length(pressurepath_variable_available("api", "single-levels")) length(pressurepath_variable_available("api", "land")) pressurepath_variable_available("arco", "land")length(pressurepath_variable_available("api", "single-levels")) length(pressurepath_variable_available("api", "land")) pressurepath_variable_available("arco", "land")
bird objectThis function displays the information of a bird object.
## S3 method for class 'bird' print(x, ...)## S3 method for class 'bird' print(x, ...)
x |
a GeoPressureR |
... |
arguments passed to other methods |
bird is returned invisibly and unchanged
Other bird:
bird_create()
# Using AVONET dataset bird_create("Acrocephalus arundinaceus")# Using AVONET dataset bird_create("Acrocephalus arundinaceus")
graph objectThis function displays the information of a graph object.
## S3 method for class 'graph' print(x, ...)## S3 method for class 'graph' print(x, ...)
x |
a GeoPressureR |
... |
arguments passed to other methods |
graph is returned invisibly and unchanged
Other graph:
graph_add_wind(),
graph_create(),
graph_marginal(),
graph_most_likely(),
graph_set_movement(),
graph_simulation()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) graph <- graph_create(tag, quiet = TRUE) print(graph)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() |> twilight_label_read() |> tag_set_map( extent = c(-16, 23, 0, 50), known = data.frame(stap_id = 1, known_lon = 17.05, known_lat = 48.9) ) |> geopressure_map(quiet = TRUE) |> geolight_map(quiet = TRUE) }) graph <- graph_create(tag, quiet = TRUE) print(graph)
map objectThis function displays the information of a map object.
## S3 method for class 'map' print(x, ...)## S3 method for class 'map' print(x, ...)
x |
a GeoPressureR |
... |
arguments passed to other methods |
map is returned invisibly and unchanged
Other map:
map_add_mask_water(),
map_create(),
rast.map()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 4 ) |> geopressure_map(quiet = TRUE) }) print(tag$map_pressure)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 4 ) |> geopressure_map(quiet = TRUE) }) print(tag$map_pressure)
param listThis function displays the information of a param list.
## S3 method for class 'param' print(x, ...)## S3 method for class 'param' print(x, ...)
x |
a GeoPressureR |
... |
arguments passed to other methods |
param is returned invisibly and unchanged
Other param:
param_create()
# Display the default parameters used in the package. param <- param_create("18LX", default = TRUE) print(param)# Display the default parameters used in the package. param <- param_create("18LX", default = TRUE) print(param)
tag objectThis function displays the information of a tag object.
## S3 method for class 'tag' print(x, ...)## S3 method for class 'tag' print(x, ...)
x |
a GeoPressureR |
... |
further arguments passed to or from other methods. |
tag is returned invisibly and unchanged
Other tag:
read_stap(),
tag_create(),
tag_set_map(),
tag_stap_daily()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) }) print(tag)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) }) print(tag)
map
This function convert a GeoPressureR map object into a terra::SpatRaster with the data of
each stationary periods stored in a different layer.
rast.map(x, names = glue::glue("#{map$stap$stap_id}"), crs = "epsg:4326", ...)rast.map(x, names = glue::glue("#{map$stap$stap_id}"), crs = "epsg:4326", ...)
x |
a GeoPressureR |
names |
names of the SpatRaster layers created. See |
crs |
character. Description of the Coordinate Reference System (map projection) in |
... |
additional parameters for |
A terra::SpatRaster object.
Other map:
map_add_mask_water(),
map_create(),
print.map()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 4 ) |> geopressure_map(quiet = TRUE) }) rast.map(tag$map_pressure)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 4 ) |> geopressure_map(quiet = TRUE) }) rast.map(tag$map_pressure)
Reads a CSV file defining coarse stationary periods (stap0) or validates a data.frame,
including date parsing, ordering, and overlap checks.
read_stap(x, required_cols = c("start", "end"))read_stap(x, required_cols = c("start", "end"))
x |
a |
required_cols |
character vector of required columns (default: |
A data.frame containing at least the required columns, sorted by start.
Other tag:
print.tag(),
tag_create(),
tag_set_map(),
tag_stap_daily()
# From a data.frame stap_df <- data.frame( start = as.POSIXct(c("2020-01-01", "2020-01-03"), tz = "UTC"), end = as.POSIXct(c("2020-01-02", "2020-01-04"), tz = "UTC") ) read_stap(stap_df) # From a CSV path # read_stap("./data/stap-label/18LX.csv")# From a data.frame stap_df <- data.frame( start = as.POSIXct(c("2020-01-01", "2020-01-03"), tz = "UTC"), end = as.POSIXct(c("2020-01-02", "2020-01-04"), tz = "UTC") ) read_stap(stap_df) # From a CSV path # read_stap("./data/stap-label/18LX.csv")
This function convert a speed vector represented in complex number into a bearing angle (0°=N ; 90°=E...). This conversion is needed because trigonometric angle are different than bearing.
speed2bearing( speed, speed_ref = complex(real = 0, imaginary = 1), positive = TRUE )speed2bearing( speed, speed_ref = complex(real = 0, imaginary = 1), positive = TRUE )
speed |
speed as complex value |
speed_ref |
reference vector of the angle. Default is the North in order to return bearing.
Use |
positive |
logical to ensure the bearing is positive between 0-360 degree. |
bearing angle in degree
speed2bearing(complex(real = 10, imaginary = 5))speed2bearing(complex(real = 10, imaginary = 5))
Converts a speed (airspeed or ground speed) to a probability based on the movement model.
speed2prob(speed, movement)speed2prob(speed, movement)
speed |
airspeed or ground speed in km/h |
movement |
a list of the movement model parameter defined with |
Probability values corresponding to the speed provided.
Other movement:
bird_create(),
graph_set_movement(),
plot_graph_movement(),
tag_download_wind()
speed <- seq(1, 120) low_speed_fix <- 20 # minimum speed allowed prob <- speed2prob( speed, list( method = "gamma", shape = 7, scale = 7, low_speed_fix = low_speed_fix, zero_speed_ratio = 0 ) ) plot(speed, prob, type = "l", xlab = "Groundspeed [km/h]", ylab = "Probability" ) abline(v = low_speed_fix) # Using airspeed bird <- bird_create("Acrocephalus arundinaceus") prob <- speed2prob( speed, list( method = "power", bird = bird, power2prob = \(power) (1 / power)^3, low_speed_fix = low_speed_fix, zero_speed_ratio = 0 ) ) plot(speed, prob, type = "l", xlab = "Airspeed [km/h]", ylab = "Probability") abline(v = low_speed_fix)speed <- seq(1, 120) low_speed_fix <- 20 # minimum speed allowed prob <- speed2prob( speed, list( method = "gamma", shape = 7, scale = 7, low_speed_fix = low_speed_fix, zero_speed_ratio = 0 ) ) plot(speed, prob, type = "l", xlab = "Groundspeed [km/h]", ylab = "Probability" ) abline(v = low_speed_fix) # Using airspeed bird <- bird_create("Acrocephalus arundinaceus") prob <- speed2prob( speed, list( method = "power", bird = bird, power2prob = \(power) (1 / power)^3, low_speed_fix = low_speed_fix, zero_speed_ratio = 0 ) ) plot(speed, prob, type = "l", xlab = "Airspeed [km/h]", ylab = "Probability") abline(v = low_speed_fix)
This function returns the duration between stap$start and stap$end.
The function can be used with any data.frame containing start and end as POSIXct (e.g.,
flight or path).
stap2duration(stap_path, units = "days", return_numeric = TRUE)stap2duration(stap_path, units = "days", return_numeric = TRUE)
stap_path |
A |
units |
character string. Units in which the results are desired. Can be abbreviated.
See |
return_numeric |
logical to return the duration as a numeric rather than with a duration format. |
Vector of duration
# Create fake stap stap <- data.frame( start = seq(as.POSIXct("1990-01-01"), as.POSIXct("1991-01-01"), length.out = 13) ) stap$end <- stap$start + 60 * 60 * 24 * 30 stap$stap_id <- seq_len(nrow(stap)) stap2duration(stap) stap2duration(stap, units = "mins", return_numeric = FALSE)# Create fake stap stap <- data.frame( start = seq(as.POSIXct("1990-01-01"), as.POSIXct("1991-01-01"), length.out = 13) ) stap$end <- stap$start + 60 * 60 * 24 * 30 stap$stap_id <- seq_len(nrow(stap)) stap2duration(stap) stap2duration(stap, units = "mins", return_numeric = FALSE)
Convert a stationary period data.frame stap into a flight data.frame or list. Flight are
computed as the difference between the end of a stationary period to the start of the next one.
Because the pressure/acceleration is labelled for "in flight", the bird was already in flight
before the first label and after the last label. We account for this by adding to all flights
duration half the temporal resolution of the sensor.
You can compute the flight between specific stationary periods using include_stap_id. In this
case, the flight duration is computed as the sum of individual flights in between.
You can return the flight as a data.frame or as a list if you want to retrieve the information
of all individual flight between the include_stap_id.
stap2flight( stap, include_stap_id = NULL, format = "df", units = "hours", return_numeric = TRUE )stap2flight( stap, include_stap_id = NULL, format = "df", units = "hours", return_numeric = TRUE )
stap |
a stationary period data.frame (see |
include_stap_id |
vector of the stationary period |
format |
character to return a list |
units |
character string. Units in which the results are desired. Can be abbreviated.
See |
return_numeric |
logical to return the duration as a numeric rather than with a duration format. |
A list or a data.frame (see description) containing
start: Start time of the (first) flight
end: End time of the (last) flight
stap_id_s: Source stap_id (i.e, start)
stap_id_t: Target stap_id (i.e, end)
duration: (Sum of the) duration of flight(s)
(n: Number of flights)
The value in brackets are only for the data.frame
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) # By default, return a data.frame of all individual flights knitr::kable(stap2flight(tag$stap)) # Compute the total flight between stap 1,3 and 5. Sum flight duration in between. knitr::kable(stap2flight(tag$stap, include_stap_id = c(1, 3, 5))) # Can also return as a list of data.frame to access individual flights information. knitr::kable(stap2flight(tag$stap, include_stap_id = c(1, 3, 5), format = "list", units = "secs" ))withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) # By default, return a data.frame of all individual flights knitr::kable(stap2flight(tag$stap)) # Compute the total flight between stap 1,3 and 5. Sum flight duration in between. knitr::kable(stap2flight(tag$stap, include_stap_id = c(1, 3, 5))) # Can also return as a list of data.frame to access individual flights information. knitr::kable(stap2flight(tag$stap, include_stap_id = c(1, 3, 5), format = "list", units = "secs" ))
tag
This function check the condition of a tag object.
tag_assert(tag, condition = "tag", type = "abort")tag_assert(tag, condition = "tag", type = "abort")
tag |
a GeoPressureR |
condition |
condition to assert |
type |
Message type to display. One of |
logical indicating the tag object has the relevant element
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) tag_assert(tag) tag_assert(tag, "stap") tag_assert(tag, "setmap", type = "warn") tag_assert(tag, "map_pressure", type = "inform") tag_assert(tag, "setmap", type = "logical")withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) tag_assert(tag) tag_assert(tag, "stap") tag_assert(tag, "setmap", type = "warn") tag_assert(tag, "map_pressure", type = "inform") tag_assert(tag, "setmap", type = "logical")
tag objectRead sensor measurements into a GeoPressureR tag object. Optionally correct timestamps
for clock offset and drift, then crop to the recording period of interest.
tag_create( id, manufacturer = NULL, crop_start = NULL, crop_end = NULL, directory = glue::glue("./data/raw-tag/{id}"), pressure_file = NULL, light_file = NULL, acceleration_file = NULL, temperature_external_file = NULL, temperature_internal_file = NULL, magnetic_file = NULL, assert_pressure = TRUE, quiet = FALSE, time_shift = 0, time_drift = 0, time_reference = NULL )tag_create( id, manufacturer = NULL, crop_start = NULL, crop_end = NULL, directory = glue::glue("./data/raw-tag/{id}"), pressure_file = NULL, light_file = NULL, acceleration_file = NULL, temperature_external_file = NULL, temperature_internal_file = NULL, magnetic_file = NULL, assert_pressure = TRUE, quiet = FALSE, time_shift = 0, time_drift = 0, time_reference = NULL )
id |
Unique tag identifier. |
manufacturer |
Data format: |
crop_start |
Inclusive start of the corrected recording period, as POSIXct or character
in UTC. |
crop_end |
Exclusive end of the corrected recording period, as POSIXct or character in UTC.
|
directory |
Directory containing the original sensor files. |
pressure_file |
Pressure input; tabular values must be in hPa. See Sensor files and Tabular input for input formats. |
light_file |
Optional light input. |
acceleration_file |
Optional acceleration input. |
temperature_external_file |
Optional external or air-temperature input. |
temperature_internal_file |
Optional internal or body-temperature input. |
magnetic_file |
Optional magnetic and acceleration input with axis columns. |
assert_pressure |
Logical; require pressure data in the returned tag. |
quiet |
Logical; hide progress messages and sampling-interval warnings. |
time_shift |
Constant correction in hours. A numeric value for all sensors or a named list
for individual sensors ( |
time_drift |
Linear correction in hours per year (365.25 days). A numeric value for all
sensors or a named list for individual sensors. Default is zero; |
time_reference |
Original recorded timestamp at which drift correction is zero, as POSIXct
or character in UTC. |
A GeoPressureR tag containing param (see param_create()) and the available sensor
tables. Each sensor table has a UTC POSIXct date column and the following measurement columns:
pressure: value in hPa.
light, temperature_external, temperature_internal: value.
acceleration: value and optionally mean_acceleration_z. For SOI, value is the sum of
successive z-axis acceleration differences over 32 measurements at 10 Hz (jiggle);
mean_acceleration_z is their mean z-axis acceleration.
magnetic: magnetic_x, magnetic_y, magnetic_z, acceleration_x, acceleration_y,
acceleration_z.
Data are read -> corrected -> cropped. Keep the original files and specify clock
corrections in tag_create(). All sensor timestamps are rounded to the nearest millisecond
after correction and before cropping, including when no correction is supplied. A warning
identifies sensors where rounding makes distinct timestamps identical; all measurements are kept.
Pressure is required by default; use assert_pressure = FALSE
for tags without pressure data.
By default, files are read from ./data/raw-tag/{id} and the manufacturer is detected from
the directory where possible. Set manufacturer explicitly when needed, including for PresTag.
Sensor file arguments accept a file path or filename pattern, such as "*.pressure".
Supported formats are:
SOI ("soi"): pressure *.pressure, light *.glf, acceleration *.acceleration,
external temperature *.temperature or *.airtemperature, internal temperature
*.bodytemperature, and magnetic data *.magnetic.
Migratetech ("migratetech"): pressure and acceleration *.deg, light *.lux.
BAS ("bas"): light *.lig only; use assert_pressure = FALSE.
Lund CAnMove ("lund"): pressure *_press.xlsx, light and acceleration *_acc.xlsx.
PresTag ("prestag"): pressure *.txt.
Manufacturer readers detect available sensor files when their arguments are NULL.
For SOI, use NA to skip a sensor.
With manufacturer = "tabular", each sensor argument accepts a data.frame, tibble, or CSV path.
Tables need a UTC POSIXct date column and a value column; pressure values must be in hPa.
Magnetic tables instead use the axis columns listed under Value below.
CSV files use datetime instead of date, with UTC timestamps such as
"2025-01-01T00:00:00"; fractional seconds are supported. CSV files named pressure.csv,
light.csv, etc. can be detected automatically from directory. Omit optional tabular sensors
with NULL. An in-memory pressure_file also selects tabular input automatically.
time_shift adds a constant offset in hours.
time_drift adds a linear correction in hours per year (365.25 days).
time_reference is the original recorded time at which drift correction is zero. By default,
it is the earliest measurement across all sensors, before shifts or cropping.
Positive corrections add time; negative corrections subtract time. Each correction accepts
one value for all sensors or a named list, such as list(pressure = -12 / 60, light = 0).
Sensors omitted from a list receive zero; entries for absent sensors are ignored. All sensors
share the reference, regardless of recording duration. Drift uses the original timestamps,
before adding the shift, and extends linearly before an explicit reference.
Correction settings and the reference used for drift are recorded in tag$param$tag_create.
When changing corrections, rerun the analysis from the original data and regenerate labels
that rely on exact timestamps, including TRAINSET labels.
Cropping uses corrected UTC timestamps: crop_start is inclusive and crop_end is exclusive.
Leave either boundary as NULL to keep all data on that side.
Other tag:
print.tag(),
read_stap(),
tag_set_map(),
tag_stap_daily()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { # Read available sensors. tag <- tag_create("18LX", quiet = TRUE) # Crop to the period of interest. tag <- tag_create("18LX", crop_start = "2017-08-01", crop_end = "2017-08-05", quiet = TRUE ) # Select files explicitly when several match the same pattern. tag <- tag_create("CB621", pressure_file = "CB621_BAR.deg", light_file = "CB621.lux", quiet = TRUE ) # Correct selected sensors using a shared recorded reference. tag <- tag_create("18LX", time_shift = list(light = 2), time_drift = list(pressure = -12 / 60), time_reference = "2017-06-20", quiet = TRUE ) }) # Read an in-memory table and apply the same correction to all sensors. pressure <- data.frame( date = as.POSIXct("2025-01-01", tz = "UTC") + (0:48) * 1800, value = rep(1000, 49) ) tag <- tag_create("example", pressure_file = pressure, time_shift = 2, time_drift = -12 / 60, quiet = TRUE )withr::with_dir(system.file("extdata", package = "GeoPressureR"), { # Read available sensors. tag <- tag_create("18LX", quiet = TRUE) # Crop to the period of interest. tag <- tag_create("18LX", crop_start = "2017-08-01", crop_end = "2017-08-05", quiet = TRUE ) # Select files explicitly when several match the same pattern. tag <- tag_create("CB621", pressure_file = "CB621_BAR.deg", light_file = "CB621.lux", quiet = TRUE ) # Correct selected sensors using a shared recorded reference. tag <- tag_create("18LX", time_shift = list(light = 2), time_drift = list(pressure = -12 / 60), time_reference = "2017-06-20", quiet = TRUE ) }) # Read an in-memory table and apply the same correction to all sensors. pressure <- data.frame( date = as.POSIXct("2025-01-01", tz = "UTC") + (0:48) * 1800, value = rep(1000, 49) ) tag <- tag_create("example", pressure_file = pressure, time_shift = 2, time_drift = -12 / 60, quiet = TRUE )
This function downloads data associated to each flight from the ERA5 hourly pressure levels (doi:10.24381/cds.bd0915c6)
with the Climate Data Store (CDS) and through the ecmwfr R package.
Any variable available from the ERA5 pressure level can be downloaded.
The flights are determined from the stationary periods classified tag$stap. It requests a
single file for each flight using the exact time (hourly basis) and pressure (altitude). To make
the download more efficient, wf_request_batch()
is used to download files in parallel. CDS queue limits vary with the current system workload.
If CDS reports that queued requests are temporarily limited, reduce workers and try again.
More information in the GeoPressureManual.
tag_download_wind( tag, extent = tag$param$tag_set_map$extent, include_stap_id = NULL, variable = c("u_component_of_wind", "v_component_of_wind"), file = function(stap_id, tag_id) { glue::glue("./data/wind/{tag_id}/{tag_id}_{stap_id}.nc") }, overwrite = FALSE, workers = 19, cds_token = lifecycle::deprecated(), ... )tag_download_wind( tag, extent = tag$param$tag_set_map$extent, include_stap_id = NULL, variable = c("u_component_of_wind", "v_component_of_wind"), file = function(stap_id, tag_id) { glue::glue("./data/wind/{tag_id}/{tag_id}_{stap_id}.nc") }, overwrite = FALSE, workers = 19, cds_token = lifecycle::deprecated(), ... )
tag |
a GeoPressureR |
extent |
geographical extent of the map on which the likelihood will be computed.
Vector of length 4 |
include_stap_id |
stationary period identifiers of the start of the flight to download. Default is to download all flights. |
variable |
list of variables to download from the ERA5 pressure level :
|
file |
absolute or relative path of the ERA5 wind data file to be downloaded. Function taking as arguments (1) the stationary period identifier and (2) the tag_id. |
overwrite |
logical. If |
workers |
maximum number of simultaneous requests submitted to CDS. Defaults to |
cds_token |
|
... |
Arguments passed on to
|
The path of the downloaded (requested file) or the an R6 object with download/transfer information
ARCO access and CDS downloads use the same ECMWF Personal Access Token. Create an ECMWF account, copy the token from your Climate Data Store profile, accept the dataset licence terms, and store the token once in your system keyring:
ecmwfr::wf_set_key("your-personal-access-token")
Do not put the token in a script or commit it to version control. GeoPressureR retrieves the
stored token with ecmwfr::wf_get_key() for all ECMWF-backed functions, including
geopressure_timeseries(), pressurepath_create(), and tag_download_wind().
wf_request_batch() ,
GeoPressureManual
Other movement:
bird_create(),
graph_set_movement(),
plot_graph_movement(),
speed2prob()
tag_download_wind(tag)tag_download_wind(tag)
tag objectThis function performs the following operations:
Read label file with tag_label_read() and assign the label to a new column in each sensor
data.frame
Compute the stationary period tag$stap from the label and assign the corresponding stap_id
on all sensors data.frame with tag_label_stap()
If the label file does not exist, the function will suggest to create it with
tag_label_write() and use tag_label_auto() if acceleration data exists.
tag_label( tag, file = glue::glue("./data/tag-label/{tag$param$id}-labeled.csv"), quiet = FALSE, warning_flight_duration = lifecycle::deprecated(), warning_stap_duration = lifecycle::deprecated(), ... )tag_label( tag, file = glue::glue("./data/tag-label/{tag$param$id}-labeled.csv"), quiet = FALSE, warning_flight_duration = lifecycle::deprecated(), warning_stap_duration = lifecycle::deprecated(), ... )
tag |
a GeoPressure |
file |
Absolute or relative path of the label file. |
quiet |
logical to display message. |
warning_flight_duration |
lifecycle::deprecated() |
warning_stap_duration |
lifecycle::deprecated() |
... |
lifecycle::deprecated() |
Same tag list with
(1) a stap data.frame describing the STAtionary Period:
stap_id unique identifier in increasing order 1,...,n
start start date of each stationary period
end end date of each stationary period
(2) an additional label and stap_id column on the sensor data.frame:
date datetime of measurement as POSIXt
value sensor measurement
label indicates the observation to be discarded ("discard" and "flight") as well as
grouped by elevation layer (elev_*)
stap_id stationary period of the measurement matching the tag$stap.
Other tag_label:
tag_label_auto(),
tag_label_read(),
tag_label_stap(),
tag_label_write()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) print(tag) tag <- tag_label(tag) print(tag) # The labelled `tag` contains additional column on the sensor data.frame str(tag) })withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) print(tag) tag <- tag_label(tag) print(tag) # The labelled `tag` contains additional column on the sensor data.frame str(tag) })
tag
This function uses acceleration data to classify migratory flights. The function uses a
k=2 mean clustering (kmeans()) to identify high activity periods. Periods of high activity
lasting more than min_duration are then considered to be migratory flight.
Additionally, we perform a post-processing step to improve the classification of low-activity period happening during a migration flight (e.g. gliding phase):
Mid-activity surrounded by flights. The kmeans classification classify high-activity all
values above 50% of the distance between the two clusters. Here, we classify as mid-activity
non-flight activity data which value are greater than thr_reclassify of the distance between
the two kmeans clusters. Any periods of mid-activity surrounded by flight are also considered
as flights.
To avoid stap lasting only a few datapoints, we also classify any datapoint
which is surrounded by a flight before and after, within a window of +/- post_proc_window
points. As a result, no stap will be shorter than (2 * post_proc_window + 1) * dt.
This function is inspired by the function classify_flap from the
PAMlr package.
tag_label_auto( tag, min_duration = 30, thr_reclassify = 0.1, post_proc_window = 2 )tag_label_auto( tag, min_duration = 30, thr_reclassify = 0.1, post_proc_window = 2 )
tag |
a GeoPressure |
min_duration |
Minimal duration (in minutes) to consider a high activity as migratory flight. |
thr_reclassify |
Post-processing threshold of activity considered for re-classification.
Typically between |
post_proc_window |
Post-processing windows considered for re-classification. Typically |
Same data logger list than input tag, but with the column label filled with
"flight" in the acceleration data.frame when a sustained high-activity period is detected.
Other tag_label:
tag_label(),
tag_label_read(),
tag_label_stap(),
tag_label_write()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) tag <- tag_label_auto(tag, min_duration = 15) str(tag$acceleration) })withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) tag <- tag_label_auto(tag, min_duration = 15) str(tag$acceleration) })
This function reads an exported csv file from TRAINSET and
updates the data logger dataset tag.
tag_label_read( tag, file = glue::glue("./data/tag-label/{tag$param$id}-labeled.csv") )tag_label_read( tag, file = glue::glue("./data/tag-label/{tag$param$id}-labeled.csv") )
tag |
a GeoPressure |
file |
Absolute or relative path of the label file. |
Same data logger list as input, updated with the labels tag$pressure$label and
optionally tag$acceleration$label.
Other tag_label:
tag_label(),
tag_label_auto(),
tag_label_stap(),
tag_label_write()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) tag <- tag_label_read(tag) str(tag) })withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) tag <- tag_label_read(tag) str(tag) })
This function computes the stationary periods from the pressure and/or acceleration label data.
In most case, this function should be run directly after tag_label_read() in order to update
tag to correspond to the new label file.
A stationary period is a period during which the bird is considered static relative to the
spatial resolution of interest (~10-50km). They are defined by being separated by a flight of any
duration (label "flight"). The stap_id is an integer value for stationary periods and decimal
value for flight. The stap_id is added as a new column to each sensor data.
If an acceleration data.frame is present and contains a column label, the stationary period
will be computed from it, otherwise, it uses the pressure data.frame.
tag_label_stap( tag, quiet = FALSE, warning_flight_duration = lifecycle::deprecated(), warning_stap_duration = lifecycle::deprecated() )tag_label_stap( tag, quiet = FALSE, warning_flight_duration = lifecycle::deprecated(), warning_stap_duration = lifecycle::deprecated() )
tag |
a GeoPressure |
quiet |
logical to display warning message. |
warning_flight_duration |
lifecycle::deprecated() |
warning_stap_duration |
lifecycle::deprecated() |
tag is return with (1) a new data.frame of stationary periods tag$stap and (2) a new
column stap_id for each sensor data.
Other tag_label:
tag_label(),
tag_label_auto(),
tag_label_read(),
tag_label_write()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label_read() tag <- tag_label_stap(tag) str(tag) str(tag$stap) })withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label_read() tag <- tag_label_stap(tag) str(tag) str(tag$stap) })
This function writes the csv file of labelled activity and pressure which can be read with TRAINSET. If no label data exist, it will first initialize the label data.
Optionally, it can also export a reference dataset for pressure tag$pressure$ref as another
series to be visualized on TRAINSET, but without impacting the labelling process.
tag_label_write( tag, file = glue::glue("./data/tag-label/{tag$param$id}.csv"), quiet = FALSE )tag_label_write( tag, file = glue::glue("./data/tag-label/{tag$param$id}.csv"), quiet = FALSE )
tag |
a GeoPressure |
file |
Absolute or relative path of the label file to be saved. |
quiet |
logical to display message. |
The file pathname is return invisibly
Other tag_label:
tag_label(),
tag_label_auto(),
tag_label_read(),
tag_label_stap()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) # Writing unlabelled tag will initialize the labelling for trainset tag_label_write(tag) # Writing unlabelled tag will initialize the labelling for trainset tag <- tag_label_auto(tag) tag_label_write(tag) # Writing labelled tag will use the existing labels tag <- tag_label(tag) tag_label_write(tag) })withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) # Writing unlabelled tag will initialize the labelling for trainset tag_label_write(tag) # Writing unlabelled tag will initialize the labelling for trainset tag <- tag_label_auto(tag) tag_label_write(tag) # Writing labelled tag will use the existing labels tag <- tag_label(tag) tag_label_write(tag) })
map of a tag objectThis function adds to tag the parameters defining the 3D grid of the map. The spatial
parameters (extent and scale) define the geographical dimensions of the map, and the
temporal dimension is defined based on the stationary periods built using the labels.
include_stap_id and include_min_duration can be used to limit which stationary periods are
computed and modelled in the analysis. By default, all stationary periods are included.
In addition, tag offers the possibility to define known locations (e.g., equipment or
retrieval site). These can only be defined at the level of a stationary period (i.e., assuming
constant position during the whole stationary period) but you can define as many known stationary
periods as you wish. Because the index of the last stationary period is generally unknown, you
can use negative indexing in known, i.e., known$stap_id = -1 will be converted to
nrow(tag$stap).
By default, no likelihood map will be computed for these stationary periods and the trajectory
model will be more constrained, saving significant computational time. You can change this
using the compute_known parameter in geopressure_map().
tag_set_map( tag, extent, scale = 10, known = data.frame(stap_id = integer(), known_lat = double(), known_lon = double()), include_stap_id = NULL, include_min_duration = 0 )tag_set_map( tag, extent, scale = 10, known = data.frame(stap_id = integer(), known_lat = double(), known_lon = double()), include_stap_id = NULL, include_min_duration = 0 )
tag |
a GeoPressureR |
extent |
geographical extent of the map on which the likelihood and graph model will be
computed. Vector of length 4 |
scale |
number of pixels per 1° latitude-longitude. For instance, |
known |
data.frame containing the known positions of the bird (e.g., equipment or retrieval
site) with columns |
include_stap_id |
vector of |
include_min_duration |
minimum duration threshold of stationary periods to include (in hours). |
A GeoPressureR tag object with:
stap: Data.frame of all stationary periods with three new columns: known_lat and
known_lon define the known position during these stationary periods, and include defines
whether the likelihood map of this stationary period should be computed and later used in the
graph.
extent same as input parameter extent
scale same as input parameter scale
Other tag:
print.tag(),
read_stap(),
tag_create(),
tag_stap_daily()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) # Default tag tag_default <- tag_set_map(tag, c(-16, 23, 0, 50)) print(tag_default) # Customized tag, with coarse grid scale, known position for the first stationary # period and considering only the stationary periods lasting more than 20hours. tag_custom <- tag_set_map(tag, extent = c(-16, 23, 0, 50), scale = 1, include_min_duration = 20, known = data.frame( stap_id = 1, known_lon = 17.05, known_lat = 48.9 ) ) print(tag_custom)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) # Default tag tag_default <- tag_set_map(tag, c(-16, 23, 0, 50)) print(tag_default) # Customized tag, with coarse grid scale, known position for the first stationary # period and considering only the stationary periods lasting more than 20hours. tag_custom <- tag_set_map(tag, extent = c(-16, 23, 0, 50), scale = 1, include_min_duration = 20, known = data.frame( stap_id = 1, known_lon = 17.05, known_lat = 48.9 ) ) print(tag_custom)
Construct stationary periods from labelled sunrise and sunset times. Each boundary is the
midpoint of an assumed movement period: night midpoints when movement occurs at night, or day
midpoints when movement occurs during the day. The resulting stap intervals therefore cover
the periods between successive movements. If a stap_long is provided (as a data.frame or a CSV
path), its intervals are kept as-is and the remaining gaps are filled using twilight midpoints.
tag_stap_daily( tag, stap_long = NULL, movement_period = "night", max_twl_gap = 23.5, quiet = FALSE, twl_grouping = lifecycle::deprecated(), stap0 = lifecycle::deprecated() )tag_stap_daily( tag, stap_long = NULL, movement_period = "night", max_twl_gap = 23.5, quiet = FALSE, twl_grouping = lifecycle::deprecated(), stap0 = lifecycle::deprecated() )
tag |
a GeoPressureR |
stap_long |
optional long stationary periods, supplied as a |
movement_period |
When the bird is assumed to be moving: |
max_twl_gap |
maximum allowed gap between consecutive twilights (in hours) before erroring, indicating missing twilights. |
quiet |
logical to hide messages. |
twl_grouping |
|
stap0 |
Updated tag with a twilight-based stap and optional stap0. The stap includes a
logical column stap0 set to TRUE when intervals come from the provided stap0 input.
Other tag:
print.tag(),
read_stap(),
tag_create(),
tag_set_map()
# Create and label the sunrise and sunset times used to define periods. withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> twilight_create() |> twilight_label_read() # Assume the bird moves at night. Preserve the long stationary periods # stored in data/stap-label/18LX.csv, while filling the remaining time # with daily periods bounded by night midpoints. tag <- tag_stap_daily( tag, stap_long = tag$param$id, movement_period = "night" ) }) head(tag$stap)# Create and label the sunrise and sunset times used to define periods. withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> twilight_create() |> twilight_label_read() # Assume the bird moves at night. Preserve the long stationary periods # stored in data/stap-label/18LX.csv, while filling the remaining time # with daily periods bounded by night midpoints. tag <- tag_stap_daily( tag, stap_long = tag$param$id, movement_period = "night" ) }) head(tag$stap)
path from the likelihood maps of a tag
Find the position of the highest value in a map, typically most probable value in a likelihood map.
Note that this path is the most likely, considering only the observation model and ignoring the
movement model. Prefer to use graph_most_likely() for the most realistic path accounting for
flight duration.
interp can be used to interpolate unrealistic position from short stationary periods based on
the position of the longer ones. In order to preserve a reference to the grid, the interpolation
is only performed at the centre of the grid cell (defined by the likelihood map). Note also
that it is not possible to interpolate the first and last stationary period.
tag2path(tag, likelihood = NULL, interp = FALSE, use_known = TRUE)tag2path(tag, likelihood = NULL, interp = FALSE, use_known = TRUE)
tag |
a GeoPressureR |
likelihood |
Field of the |
interp |
the position of the stationary period shorter than |
use_known |
If |
A path data.frame
stap_id stationary period
ind indices of the coordinate in the 2D grid. Useful to retrieve map or graph information.
lat Latitude,
lon longitude
Other path:
path2edge(),
path2elevation(),
path2twilight(),
plot_path()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 2 ) |> geopressure_map(quiet = TRUE) }) # Extract a path from pressure map path <- tag2path(tag) plot_path(path) # Short stationary periods (e.g. 1 day) can be unreliably # estimated, so interpolating them is often better path <- tag2path(tag, interp = 1) plot_path(path)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> tag_set_map( extent = c(-16, 23, 0, 50), scale = 2 ) |> geopressure_map(quiet = TRUE) }) # Extract a path from pressure map path <- tag2path(tag) plot_path(path) # Short stationary periods (e.g. 1 day) can be unreliably # estimated, so interpolating them is often better path <- tag2path(tag, interp = 1) plot_path(path)
GeoPressure Trainset is a shiny app designed to help you manually label pressure and acceleration data for training machine learning models. This interactive app allows you to visualize time series data, select data points or regions, and assign behavioral labels (e.g., "flight", "discard", or custom elevation labels) to create training datasets.
trainset(x, launch_browser = TRUE, run_bg = TRUE, debug = FALSE)trainset(x, launch_browser = TRUE, run_bg = TRUE, debug = FALSE)
x |
One of:
|
launch_browser |
If true (by default), the app runs in your browser, otherwise it runs on Rstudio. |
run_bg |
If true, the app runs in a background R session using the |
debug |
If |
The app features:
Interactive plotly visualization of pressure and acceleration time series
Point and region selection for efficient labeling
Support for stationary periods (STAP) navigation
Custom label creation (elevation labels)
Export functionality to save labeled data as CSV files
Learn more about data labeling workflows in the GeoPressureManual or explore the GeoPressureR documentation.
A GeoPressureR tag object (with pressure and optionally acceleration data
and an id in tag$param$id). If run_bg = TRUE, a background process object
is returned invisibly, with the tag attached as an attribute attr(p, "tag").
The labeled data can be exported directly from the app interface.
tag_label_read(), tag_label_write(), GeoPressureManual
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) trainset(tag, run_bg = FALSE, launch_browser = FALSE)withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) trainset(tag, run_bg = FALSE, launch_browser = FALSE)
Format time series data frame into a matrix
ts2mat( ts, sensor = "time series", twl_offset = 0, value = "value", twl_time_tolerance = 180 )ts2mat( ts, sensor = "time series", twl_offset = 0, value = "value", twl_time_tolerance = 180 )
ts |
data.frame of a |
sensor |
sensor name used in messages. |
twl_offset |
Shift of the middle of the night compared to 00:00 UTC (in hours). If not provided, it uses the middle of all nights. |
value |
column name to extract |
twl_time_tolerance |
Maximum allowed time difference in seconds between observations and the regular grid. Observations beyond this threshold will be set to NA. Default is 180 seconds (3 minutes). Half the sampling interval is always allowed, so that drift-corrected timestamps sliding against the grid are kept. |
A data.frame with columns date and value.
mat <- ts2mat(tag$pressure)mat <- ts2mat(tag$pressure)
This function estimates twilight (i.e., datetime of sunrise and sunset) by searching for the
first and last light of the day which is defined by the light exceeds or falls below the light
threshold twl_thr.
twilight_create( tag, twl_thr = NULL, twl_offset = NULL, transform_light = TRUE, twl_time_tolerance = 180 )twilight_create( tag, twl_thr = NULL, twl_offset = NULL, transform_light = TRUE, twl_time_tolerance = 180 )
tag |
a GeoPressureR |
twl_thr |
Light threshold that defines twilight. By default ( |
twl_offset |
Shift of the middle of the night compared to 00:00 UTC (in hours). If not provided, it uses the middle of all nights. |
transform_light |
logical to use a log transformation of light |
twl_time_tolerance |
Maximum allowed time difference in seconds between observations and the regular grid. Observations beyond this threshold will be set to NA. Default is 180 seconds (3 minutes). Half the sampling interval is always allowed, so that drift-corrected timestamps sliding against the grid are kept. |
a tag list containing a new data.frame twilight with columns:
twilight (date-time of twilight)
rise (logical) indicating sunrise (TRUE) or sunset (FALSE).
stap_id if stap_id is present in light.
GeoPressureManual , TwGeos::findTwilights()
Other geolight:
geolight_fit_location(),
geolight_map(),
geolight_solar(),
plot_twl_calib(),
twilight_label_read(),
twilight_label_write()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) # Create twilight data.frame tag <- twilight_create(tag) str(tag$twilight) plot(tag, type = "twilight")withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) }) # Create twilight data.frame tag <- twilight_create(tag) str(tag$twilight) plot(tag, type = "twilight")
This function read an exported csv file from TRAINSET https://trainset.raphaelnussbaumer.com/
and update the twilight data tag$twilight.
twilight_label_read( tag, file = glue::glue("./data/twilight-label/{tag$param$id}-labeled.csv") )twilight_label_read( tag, file = glue::glue("./data/twilight-label/{tag$param$id}-labeled.csv") )
tag |
a GeoPressureR |
file |
csv file of the labels to be read. |
Same tag object, updated with the labels tag$twilight$label.
Other geolight:
geolight_fit_location(),
geolight_map(),
geolight_solar(),
plot_twl_calib(),
twilight_create(),
twilight_label_write()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() tag_labelled <- twilight_label_read(tag) }) plot(tag, type = "twilight") |> plotly::layout(title = list(text = "Before label")) str(tag_labelled$twilight) plot(tag_labelled, type = "twilight") |> plotly::layout(title = list(text = "After label"))withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() tag_labelled <- twilight_label_read(tag) }) plot(tag, type = "twilight") |> plotly::layout(title = list(text = "Before label")) str(tag_labelled$twilight) plot(tag_labelled, type = "twilight") |> plotly::layout(title = list(text = "After label"))
This function writes the csv file of the labelled twilight which can be read with TRAINSET https://trainset.raphaelnussbaumer.com/.
twilight_label_write( tag, file = glue::glue("./data/twilight-label/{tag$param$id}.csv"), quiet = FALSE )twilight_label_write( tag, file = glue::glue("./data/twilight-label/{tag$param$id}.csv"), quiet = FALSE )
tag |
a GeoPressureR |
file |
Name of the twilight label file to be saved. |
quiet |
logical to hide messages |
None
Other geolight:
geolight_fit_location(),
geolight_map(),
geolight_solar(),
plot_twl_calib(),
twilight_create(),
twilight_label_read()
withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() label_file <- twilight_label_write(tag) str(utils::read.csv(label_file)) })withr::with_dir(system.file("extdata", package = "GeoPressureR"), { tag <- tag_create("18LX", quiet = TRUE) |> tag_label(quiet = TRUE) |> twilight_create() label_file <- twilight_label_write(tag) str(utils::read.csv(label_file)) })
Wind support, or wind profit, is the projection of the wind vector onto the
groundspeed vector ,
with being the dot product.
A positive value indicates that wind was blowing in the direction of movement, while a negative one indicates a head wind.
windspeed and groundspeed should be expressed as complex value where the real part
corresponds to the east-west component and imaginary part to the north-south component.
Alternatively to wind support, you can compute the drift (or crosswind component) value with
drift = TRUE,
with being the cross product.
A positive value of drift indicates that the wind is pushing the bird to the right of its intended path, while a negative indicates that the wind is pushing the bird to the left.
You can use abs() (or Mod()) to compute the norm (or absolute value) of the speed vector and
speed_to_bearing() to compute the bearing/orientation of the speed vector. The latter
computes the trigonometric angle of the speed vector with Arg() and convert this angle to a
bearing (North = 0° instead of 90°).
windsupport(windspeed, groundspeed, drift = FALSE)windsupport(windspeed, groundspeed, drift = FALSE)
windspeed |
windspeed as complex value |
groundspeed |
groundspeed as complex value |
drift |
return drift instead of windsupport |
wind support as scalar value (same unit as gs and ws)
windsupport(windspeed = 5 + 2i, groundspeed = 10 + 0i)windsupport(windspeed = 5 + 2i, groundspeed = 10 + 0i)