Global Location Sensors (GLS) are widely used to track animal movements over long periods. However, processing GLS data has traditionally been a manual, time-consuming process requiring:
glscalibrator automates this entire workflow, allowing you to process entire datasets with a single command.
# Install from GitHub
# install.packages("devtools")
devtools::install_github("fabbiologia/glscalibrator")
# Load the package
library(glscalibrator)For this vignette we’ll rely on the bundled example data that ships with the package, but the same structure applies to your own deployments. The examples live in:
system.file("extdata", package = "glscalibrator")The main function calibrate_gls_batch() handles everything:
results <- calibrate_gls_batch(
data_dir = system.file("extdata", package = "glscalibrator"),
output_dir = "data/processed/calibration",
colony_lat = 27.85178, # Your colony latitude
colony_lon = -115.17390, # Your colony longitude
light_threshold = 2, # Light threshold in lux
verbose = TRUE
)# Summary statistics for all birds
print(results$summary)
# Processing log (successes and failures)
print(results$processing_log)
# Access individual bird positions
bird_data <- results$results$BW154_05Jul24_225805
head(bird_data)After running calibrate_gls_batch(), you’ll have:
GLSmergedata.csv - Combined data for all birds in standard formatall_birds_calibrated.csv - All positions with metadatacalibration_summary.csv - Summary statistics[bird_id]_calibrated.csv - Individual bird positions[bird_id]_GLSmergedata.csv - Individual bird in standard formatall_tracks_combined.png - Map with all bird tracks[bird_id]_track.png - Individual bird track map[bird_id]_calibration.png - Calibration diagnosticsLight-based geolocation is unreliable near equinoxes. You can exclude these periods:
# Define equinox exclusion windows
equinoxes <- list(
c("2024-08-24", "2024-10-23"), # Autumn
c("2024-02-19", "2024-04-19"), # Spring
c("2023-08-24", "2023-10-23") # Previous year
)
results <- calibrate_gls_batch(
data_dir = "data/raw/birds",
output_dir = "data/processed/calibration",
colony_lat = 27.85,
colony_lon = -115.17,
exclude_equinoxes = equinoxes
)results <- calibrate_gls_batch(
data_dir = "data/raw/birds",
output_dir = "data/processed/calibration",
colony_lat = 27.85,
colony_lon = -115.17,
light_threshold = 3, # Higher threshold
min_positions = 20, # Require more positions
create_plots = FALSE # Skip plot generation
)
# metadata table is also exported for programmatic access
glscalibrator_example_metadataIf you need more control, you can use the individual functions:
light_data <- read_lux_file(gls_example("W086"))
head(light_data)calib_period <- auto_detect_calibration(
light_data,
colony_lat = 27.85178,
colony_lon = -115.17390,
threshold = 2
)
print(calib_period)
# $start
# [1] "2024-07-05 22:58:05 UTC"
# $end
# [1] "2024-07-07 22:58:05 UTC"
# $twilights
# [1] 5twilights <- detect_twilights(light_data, threshold = 2)
head(twilights)twilights_clean <- filter_twilights(
twilights,
light_data = light_data,
threshold = 2,
strict = TRUE
)calib_result <- estimate_sun_elevation(
twilight = twilights_clean$Twilight,
rise = twilights_clean$Rise,
lon = -115.17390,
lat = 27.85178
)
zenith <- calib_result["z1"]
print(paste("Zenith angle:", round(zenith, 2), "degrees"))# Example calibration_summary.csv structure:
# bird_id zenith sun_elevation n_twilights_calib n_positions hemisphere_check
# BW154_05Jul24_225805 98.74 -8.74 5 143 CORRECT (Western)
# BW157_05Jul24_231215 98.39 -8.39 5 274 CORRECT (Western)Key columns: - zenith: Calculated sun elevation angle for this device - n_twilights_calib: Twilights used for calibration - n_positions: Final number of position estimates - hemisphere_check: Quality control (should match your study area)
# Example [bird_id]_calibrated.csv structure:
# bird_id datetime date Longitude Latitude zenith method
# BW154 2024-07-08 05:30:00 2024-07-08 -115.2 27.9 98.74 threshold_crossing_internal_gammaThe package performs automatic quality checks:
# Check calibration diagnostics
# Look at [bird_id]_calibration.png files
# Check hemisphere in summary
summary <- read.csv("data/processed/calibration/data/calibration_summary.csv")
table(summary$hemisphere_check)
# Review failed birds
failed <- results$processing_log[
sapply(results$processing_log, function(x) x$status == "FAILED")
]
print(failed)