Code
# install.packages("pacman")
library("pacman")
p_install_gh("benmarwick/wordcountaddin")
words <- wordcountaddin::word_count("index.qmd")Patterns and Trends in Environmental Data FS26, Research Project G1
# install.packages("pacman")
library("pacman")
p_install_gh("benmarwick/wordcountaddin")
words <- wordcountaddin::word_count("index.qmd")Number of words: 1,597
Number of characters (incl. spaces & references, but excl. code): 21,184
Annually, humpback whales (Megaptera novaeangliae) migrate between high-latitude feeding grounds and low-latitude breeding grounds. These extensive movements have important implications for understanding population connectivity and stock structure, yet remain poorly understood. This study replicates the approach of Andrews-Goff et al. (2023b) to identify migration routes, seasonal patterns, and behavioral states from satellite tag-derived movement trajectories using the R Studio packages amt and tmap. Individuals migrated between Australia and Antarctica. A predictable annual migration cycle between feeding and breeding habitats was observed. Future studies should integrate environmental and biological variables to improve behavioral interpretability.
Migration in humpback whales (Megaptera novaeangliae) is thought to be initiated by environmental cues such as oceanic productivity, sea-surface temperature, El Niño events, and upwelling indices, as well as internal mechanisms including memory of oceanic conditions and established migratory routes (Ingman et al., 2021; Millien et al., 2025; Pelayo-González et al., 2022). Despite ocean currents, weather, and bathymetry, humpback whales maintain highly directional movement over long distances with remarkable precision (Horton et al., 2011).
For long-term monitoring and humpback whale management following near-extinction from commercial whaling, the International Whaling Comission (IWC) assigned six Southern Ocean breeding areas and seven Southern Hemisphere breeding stocks (A – G; Donovan (1991); IWC (1982)). While some breeding stocks show strong site fidelity, others exhibit spatial overlap, suggesting interchange within Southern Ocean feeding areas (Amaral et al., 2016). Two breeding stocks (D and E1), with an estimated population of 17’810 individuals, occur in Area V (Andrews-Goff et al., 2023b; Hedley et al., 2011). However, connectivity between feeding aggregations and breeding stocks in area V remains poorly understood (Amaral et al., 2016).
Satellite telemetry enables movement analysis across broad spatial and temporal scales in remote marine environments (Andrews-Goff et al., 2023b; Dingle, 2014; Mate et al., 2007). It has been used to identify habitat use (Reisinger et al., 2021), seasonal migration patterns (Andrews-Goff et al., 2023b), and behavioral states (Garrigue et al., 2015). To investigate the migration patterns of breeding stock E1, Andrews-Goff et al. (2023b) tracked 50 eastern Australian humpback whales using satellite telemetry. This study replicates their approach to determine migration routes, seasonal patterns, and behavioral states from satellite tag-derived movement trajectories. Accordingly, the study focuses on the following research questions:
Between 2008 and 2010, Andrews-Goff et al. (2023b) deployed 50 satellite tags on E1 humpback whales. Tags transmitted at variable intervals to extend battery life and operational lifespan. Only tracks with more than five locations were analyzed; consequently, two individuals with insufficient data were excluded, leaving 48 individuals for analysis. For data collection details, see Andrews-Goff et al. (2023b).
For this replication study, two CSV datasets were downloaded from Movebank (Andrews-Goff et al., 2023a; Movebank, 2026). In addition, a shapefile of global Exclusive Economic Zones (EEZ) was used to determine tag deployment locations (Flanders Marine Institute, 2023). Table 1 summarizes the attributes used in the analysis.
library(tibble)
library(knitr) # for tables
metadata_tbl <- tribble(
~'Column label', ~'Description', ~'Unit',
"event_id",
"A unique event ID is assigned to every time-location record.",
"-",
"timestamp",
"Time of satellite tag transmission. Format: yyyy-MM-dd HH:mm:ss",
"UTC",
"location_long",
"Geographic longitude of the location estimated by the sensor.",
"Decimal degrees (WGS84)",
"location_lat",
"Geographic latitude of the location estimated by the sensor.",
"Decimal degrees (WGS84)",
"individual_id",
"Unique animal identifier.",
"-",
"deploy_on_date",
"Timestamp when tag deployment started. Format: yyyy-MM-dd",
"UTC",
"deploy_off_date",
"Timestamp when tag deployment ended. Format: yyyy-MM-dd HH:mm:ss",
"UTC",
"deploy_on_latitude",
"Geographic latitude of the deployment location.",
"Decimal degrees (WGS84)",
"deploy_on_longitude",
"Geographic longitude of the deployment location.",
"Decimal degrees (WGS84)",
"duty_cycle",
"Frequency of satellite tag transmissions and periods when the transmitter is active or inactive.",
"-",
"tag_manufacturername",
"Company which produced the tag.",
"-",
"tag_model",
"Model of the tag.",
"-",
"SOVEREIGN1",
"State that claims jurisdiction over the maritime zone",
"-"
)
kable(metadata_tbl)| Column label | Description | Unit |
|---|---|---|
| event_id | A unique event ID is assigned to every time-location record. | - |
| timestamp | Time of satellite tag transmission. Format: yyyy-MM-dd HH:mm:ss | UTC |
| location_long | Geographic longitude of the location estimated by the sensor. | Decimal degrees (WGS84) |
| location_lat | Geographic latitude of the location estimated by the sensor. | Decimal degrees (WGS84) |
| individual_id | Unique animal identifier. | - |
| deploy_on_date | Timestamp when tag deployment started. Format: yyyy-MM-dd | UTC |
| deploy_off_date | Timestamp when tag deployment ended. Format: yyyy-MM-dd HH:mm:ss | UTC |
| deploy_on_latitude | Geographic latitude of the deployment location. | Decimal degrees (WGS84) |
| deploy_on_longitude | Geographic longitude of the deployment location. | Decimal degrees (WGS84) |
| duty_cycle | Frequency of satellite tag transmissions and periods when the transmitter is active or inactive. | - |
| tag_manufacturername | Company which produced the tag. | - |
| tag_model | Model of the tag. | - |
| SOVEREIGN1 | State that claims jurisdiction over the maritime zone | - |
The data analysis was performed using RStudio (R Core Team, 2025). The pre-processed datasets provided by Andrews-Goff et al. (2023b) were joined, cleaned, and tidied prior to analysis (Preprocessing).
To identify movement patterns and behavioral states from satellite-derived trajectories, step length (sl_; meters), time difference (dt; seconds), turning angle (ta_; degrees), and burst (burst_) were calculated using the amt package functions make_track, track_resample, filter_min_n_burst, and steps_by_burst (Signer et al., 2019). Trajectories were interpolated with track_resample() to regular 30-minute intervals (± 15 min) to account for varying sampling frequencies. Travel speed [m/s] was calculated from step length and time difference. Subsequently, movement behavior was classified based on travel speed (Table 2).
behavior_tbl <- tribble(
~'Movement behavior', ~'Speed',
"Feeding and Breeding",
"0.26 - 0.56 m/s [@zerbini_migration_2020; @garrigue_satellite_2015]",
"Resting",
"0.56–1.00 m/s [@jenner_description_2011]",
"Travelling",
"> 1.00 m/s [@chittleborough_aerial_1953; @braithwaite_optimal_2015]"
)
kable(behavior_tbl)| Movement behavior | Speed |
|---|---|
| Feeding and Breeding | 0.26 - 0.56 m/s (Garrigue et al., 2015; Zerbini et al., 2020) |
| Resting | 0.56–1.00 m/s (Jenner & Jenner, 2011) |
| Travelling | > 1.00 m/s (Braithwaite et al., 2015; Chittleborough, 1953) |
Maps were created using the tmap package (Tennekes, 2018). Spatial data (data set and World data set from tmap) were projected using a Lambert azimuthal equal-area (LAEA) projection centered at 60°S and 135°E (WGS84; PROJ string: +proj=laea +lat_0=-60 +lon_0=135 +datum=WGS84) to preserve relative sizes of landmasses (Snyder, 1994).
AI tools were used to assist with data analysis and for language refinement. OpenAI (2026) was particularly helpful in visualizing the geocentered data in LAEA projection and using the amt package. Nevertheless, the conceptual development remains the sole work of the authors.
Humpback whales migrated along Australia’s east coast and across the East Antarctic sector of the Southern Ocean, primarily within IWC Management Area V, with one individual migrating westward into area IV (Figure 1).
# install.packages("amt")
# install libraries
library(tidyverse)
library(sf)
library(tmap)
library(ggplot2)
library(amt) # Manage and analyze animal movement data
library(purrr)
# Import dataset
# ID as factor
tracks <- read_delim("my_tracks.csv") |>
mutate(individual_id = as.factor(individual_id),
deploy_on_date = as.POSIXct(deploy_on_date))
# Check data set
#str(tracks)
# Dataframe as sf
tracks_sf <- st_as_sf(tracks, coords = c("location_long", "location_lat"), crs = 4326)
# Set crs to Lambert azimuthal equal-area (LAEA) for the packages tmap and amt. LAEA accounts for the distortion in higher latitudes.
crs_laea <- "+proj=laea +lat_0=-60 +lon_0=135 +datum=WGS84"
# Preprocessing for package amt
# Due to the calculation of the tracking distance (Table 1) at the beginning
# It only need ID, locations and timestamp for package amt
tracks_amt <- tracks |>
select(
individual_id,
x = location_long,
y = location_lat,
t = timestamp
) |>
mutate(t = as.POSIXct(t, tz = "UTC"))
# Dataframe as sf
tracks_amt_sf<- st_as_sf(
tracks_amt,
coords = c("x", "y"),
crs = 4326
)
# Project the crs into metrics (LAEA)
tracks_amt_laea <- st_transform(tracks_amt_sf, crs = crs_laea)
# Extract coordinates
# Remove geometry for amt
tracks_amt_laea <- tracks_amt_laea |>
mutate(
x = st_coordinates(geometry)[, 1],
y = st_coordinates(geometry)[, 2]
) |>
st_drop_geometry()
# As list for calculate speed for all individuals
tracks_amt_list <- split(tracks_amt_laea, tracks_amt_laea$individual_id)# Shift map world and tracks to LAEA
tracks_sf_laea <- st_transform(tracks_sf, crs = crs_laea)
World_laea<- st_transform(World, crs_laea)
# Create bounding box from tracks
bbox_laea <- st_bbox(tracks_sf_laea)
# Expand the box a bit
expand_x <- 1000000 # 1000 km to the left and right
expand_y <- 450000 # 450 km up and down
bbox_big <- bbox_laea
bbox_big["xmin"] <- bbox_big["xmin"] - expand_x
bbox_big["xmax"] <- bbox_big["xmax"] + expand_x
bbox_big["ymin"] <- bbox_big["ymin"] - expand_y
bbox_big["ymax"] <- bbox_big["ymax"] + expand_y
# Labels
label_fun <- function(vals) {
sapply(vals, function(x) {
if (x >= -180 && x <= 180) {
if (x > 0) paste0(x, "°E")
else paste0(abs(x), "°")
} else {
if (x < 0) paste0(abs(x), "°S")
else paste0(x, "°")
}
})
}
# Creating the IWC Management Areas
iwc_lons <- c(-170, -60, 0, 70, 130)
# Create IWC-lines with a function
make_lon_line <- function(lon) {
lats <- seq(-90, -40, by = 1)
coords <- cbind(
rep(lon, length(lats)),
lats)
st_linestring(coords)
}
iwc_lines <- st_sfc(
lapply(iwc_lons, make_lon_line),
crs = 4326
)
iwc_lines_laea <- st_transform(iwc_lines, crs_laea)
# Add IWC labels
iwc_labels <- data.frame(
lon = c(110, 140, -160),
lat = -55,
label = c("IV", "V", "I")
) |>
st_as_sf(coords = c("lon", "lat"), crs = 4326)
# Now transform the IWC lines into the correct crs
iwc_labels_laea <- st_transform(iwc_labels, crs_laea)
# Map
tm_shape(World_laea, bbox = bbox_big) +
tm_polygons(fill = "grey70", col = "grey70") +
# add the IWC Management Areas
tm_shape(iwc_lines_laea) +
tm_lines(lwd = 1, col = "black") +
tm_shape(iwc_labels_laea) +
tm_text("label", size = 1.5, col = "black") +
# add the tracks
tm_shape(tracks_sf_laea) +
tm_dots(fill ="individual_id", size = 0.05) +
# add coordinate system
tm_graticules(x = seq(-180, 180, by = 20),
y = seq(-80, 40, by = 10),
col = "grey40",
lwd = 0.2,
labels.show = TRUE,
labels.col = "grey20",
labels.size = 0.7) +
tm_layout(bg.color = "white",
legend.show = FALSE)Humpback whales were equipped with tags either in Australia or Antarctica (Table 3). The number of locations recorded per individual varies between 5 and 1,409 (mean = 277), totaling 13,311 locations. Tracking distance ranges from 68.5 to 8,645.2 km.
# Calculate tracking duration, deploy location and tracking distance
# Tracking duration
tracks_sf <- tracks_sf |>
mutate(tracking_duration = as.numeric(difftime(deploy_off_date, deploy_on_date, units = "days")),
tracking_duration_rounded = round(tracking_duration, digits = 0))
# deploy location
# load EEZ boundaries into R
eez <- read_sf("World_EEZ_v12_20231025/eez_v12.shp")
# Filter Australia's EEZ
aus_eez <- eez |>
filter(SOVEREIGN1 == "Australia")
tracks_sf <- st_join(tracks_sf, aus_eez[, "SOVEREIGN1"])
tracks_sf <- tracks_sf |>
mutate(
SOVEREIGN1 = case_when(
SOVEREIGN1 == "Australia" ~ "Australia",
TRUE ~ "Antarctica"
)
) |>
rename(deploy_location = SOVEREIGN1)
# Tracking distance
tracking_distance <- map_dfr(
tracks_amt_list,
function(df) {
tr <- make_track(
tbl = df,
x,
y,
t
)
tr <- steps(tr)
tibble(
tracking_distance_km = sum(tr$sl_/1000, na.rm = TRUE)
)
},
.id = "individual_id"
)
# Left join tracks and tracking distance
tracks_sf <- left_join(tracks_sf, tracking_distance, by = "individual_id")
# create a table with tracking duration, deploy on year, deploy off year, deploy location, tracking distance and number of locations
tracks_summary <- tracks_sf |>
group_by(individual_id) |>
summarise(
"Deploy on" = min(format(deploy_on_date, "%m-%Y")),
"Deploy off" = max(format(deploy_off_date, "%m-%Y")),
"Tracking duration (days)" =first(tracking_duration_rounded),
"Number of locations" = n(),
"Estimated tracking distance (km)" = first(round(tracking_distance_km, digits = 2)),
"Deploy location" = first(deploy_location)
) |>
rename(ID = individual_id)
tracks_summary <- tracks_summary |>
st_drop_geometry()
kable(tracks_summary)| ID | Deploy on | Deploy off | Tracking duration (days) | Number of locations | Estimated tracking distance (km) | Deploy location |
|---|---|---|---|---|---|---|
| 53348 | 02-2010 | 03-2010 | 32 | 118 | 1113.52 | Antarctica |
| 53376 | 02-2010 | 02-2010 | 3 | 48 | 222.26 | Antarctica |
| 53383 | 02-2010 | 02-2010 | 4 | 7 | 244.74 | Antarctica |
| 64235 | 10-2010 | 11-2010 | 47 | 185 | 4418.25 | Australia |
| 64238 | 10-2010 | 10-2010 | 15 | 47 | 763.39 | Australia |
| 88717 | 10-2008 | 11-2008 | 30 | 117 | 1704.83 | Australia |
| 88718 | 10-2008 | 01-2009 | 92 | 748 | 5089.81 | Australia |
| 88723 | 10-2008 | 01-2009 | 82 | 504 | 5368.66 | Australia |
| 88725 | 10-2008 | 01-2009 | 81 | 601 | 4314.83 | Australia |
| 88728 | 11-2008 | 02-2009 | 93 | 908 | 5559.93 | Australia |
| 88729 | 10-2008 | 02-2009 | 98 | 868 | 6362.89 | Australia |
| 88730 | 06-2009 | 08-2009 | 45 | 127 | 2301.04 | Australia |
| 88732 | 10-2008 | 11-2008 | 35 | 187 | 2298.65 | Australia |
| 88733 | 10-2008 | 12-2008 | 42 | 278 | 3925.43 | Australia |
| 88734 | 06-2009 | 07-2009 | 26 | 96 | 1369.38 | Australia |
| 88735 | 10-2008 | 12-2008 | 39 | 194 | 1006.65 | Australia |
| 88736 | 06-2009 | 07-2009 | 15 | 56 | 1007.42 | Australia |
| 88737 | 06-2009 | 07-2009 | 21 | 89 | 1406.47 | Australia |
| 88738 | 10-2008 | 12-2008 | 58 | 469 | 4104.53 | Australia |
| 88741 | 11-2008 | 04-2009 | 155 | 1409 | 8645.19 | Australia |
| 88742 | 06-2009 | 07-2009 | 21 | 68 | 1008.38 | Australia |
| 88743 | 10-2008 | 11-2008 | 13 | 92 | 527.71 | Australia |
| 88744 | 10-2008 | 10-2008 | 3 | 17 | 107.82 | Australia |
| 88745 | 10-2008 | 11-2008 | 19 | 58 | 1324.82 | Australia |
| 88746 | 10-2008 | 11-2008 | 20 | 117 | 1684.83 | Australia |
| 88747 | 06-2009 | 07-2009 | 14 | 55 | 883.83 | Australia |
| 88748 | 06-2009 | 07-2009 | 35 | 108 | 2214.49 | Australia |
| 88750 | 06-2009 | 07-2009 | 27 | 23 | 1234.34 | Australia |
| 88751 | 06-2009 | 07-2009 | 22 | 77 | 1327.95 | Australia |
| 88753 | 06-2009 | 07-2009 | 27 | 99 | 1063.49 | Australia |
| 88754 | 06-2009 | 08-2009 | 59 | 176 | 3092.28 | Australia |
| 88755 | 06-2009 | 08-2009 | 40 | 38 | 1669.81 | Australia |
| 88756 | 06-2009 | 07-2009 | 26 | 55 | 1318.23 | Australia |
| 96385 | 02-2010 | 03-2010 | 14 | 188 | 385.59 | Antarctica |
| 96386 | 03-2010 | 05-2010 | 92 | 1099 | 3825.78 | Antarctica |
| 96390 | 03-2010 | 03-2010 | 21 | 337 | 699.33 | Antarctica |
| 96395 | 03-2010 | 03-2010 | 5 | 82 | 221.20 | Antarctica |
| 96398 | 03-2010 | 04-2010 | 46 | 621 | 1824.68 | Antarctica |
| 96401 | 03-2010 | 03-2010 | 4 | 69 | 68.41 | Antarctica |
| 96403 | 02-2010 | 03-2010 | 22 | 256 | 1685.00 | Antarctica |
| 96404 | 03-2010 | 03-2010 | 1 | 28 | 68.54 | Antarctica |
| 96412 | 03-2010 | 03-2010 | 15 | 234 | 666.29 | Antarctica |
| 98100 | 10-2010 | 07-2011 | 287 | 344 | 6946.53 | Australia |
| 98109 | 02-2010 | 04-2010 | 66 | 5 | 447.48 | Antarctica |
| 98114 | 10-2010 | 12-2010 | 57 | 358 | 4584.19 | Australia |
| 98129 | 10-2010 | 01-2011 | 106 | 862 | 6627.31 | Australia |
| 98138 | 02-2010 | 04-2010 | 41 | 471 | 1374.15 | Antarctica |
| 98139 | 10-2010 | 11-2010 | 41 | 318 | 2671.39 | Australia |
The tags collected data between 24th October 2008 and 27th July 2011 (Figure 2). Tag transmission duration ranged from 1 to 286 days (mean = 78.8 days), with continuous or intermittent transmissions (eg. ID 98100).
ggplot(tracks_sf, aes(timestamp, individual_id)) +
geom_point() +
scale_x_date(
date_breaks = "3 months",
date_labels = "%b\n%Y"
) +
labs(
x = "Date",
y = "ID"
) +
theme(theme(
axis.text.y = element_text(size = 6)
)) +
theme_bw()The number of humpback whale localizations varies by month and year (Table 4). Data are missing for May 2009, September 2009 to January 2010, and June to September 2010. In total, 4,235 locations were recorded in 2008, 3,399 in 2009, 5,332 in 2010, and 344 in 2011. Over the four-year period, locations ranged from 119 (August) to 2,881 (November).
# Calculate month, year and coordinates
tracks_sf <- tracks_sf |>
mutate(
year = year(timestamp),
month_abbr = month(timestamp, label = TRUE),
month_num = month(timestamp), # for tmap
x = st_coordinates(geometry)[, "X"],
y = st_coordinates(geometry)[, "Y"]
)
# Create a table with year, month, number of locations and number of individuals and mean latitude
tracks_monthly <- tracks_sf |>
group_by(year, month_abbr) |>
summarise(
"Number of locations" = n(),
"Number of individuals" = n_distinct(individual_id),
Mean_lat = mean(y, na.rm = TRUE)
) |>
mutate(
"Mean latitude (WGS 84)" = ifelse(
Mean_lat < 0,
paste0(round(abs(Mean_lat), 1), "°S"),
paste0(round(Mean_lat, 1), "°N")
)
) |>
select( -Mean_lat) |>
st_drop_geometry() |>
rename(
Year = year,
Month = month_abbr)
kable(tracks_monthly)| Year | Month | Number of locations | Number of individuals | Mean latitude (WGS 84) |
|---|---|---|---|---|
| 2008 | Oct | 394 | 12 | 38.5°S |
| 2008 | Nov | 1992 | 14 | 44.4°S |
| 2008 | Dec | 1849 | 9 | 59.4°S |
| 2009 | Jan | 1587 | 6 | 63.8°S |
| 2009 | Feb | 393 | 3 | 64.9°S |
| 2009 | Mar | 342 | 1 | 65.4°S |
| 2009 | Apr | 10 | 1 | 65.6°S |
| 2009 | Jun | 265 | 13 | 27.1°S |
| 2009 | Jul | 683 | 13 | 22.2°S |
| 2009 | Aug | 119 | 3 | 27.6°S |
| 2010 | Feb | 346 | 6 | 66.5°S |
| 2010 | Mar | 2134 | 11 | 66.3°S |
| 2010 | Apr | 727 | 4 | 64.4°S |
| 2010 | May | 356 | 1 | 64°S |
| 2010 | Oct | 516 | 6 | 31.8°S |
| 2010 | Nov | 889 | 5 | 45.2°S |
| 2010 | Dec | 364 | 3 | 55.3°S |
| 2011 | Jan | 286 | 1 | 64.7°S |
| 2011 | Jul | 59 | 1 | 27.6°S |
Sampling intervals vary widely, ranging from 1 minute to approximately 212 days (median interval = 2.4 hours; mean = 7.0 hours). Most observed sampling interval is 5 minutes (n = 226; Figure 3).
# Function make_track. Creates a track (basic building block of the amt package)
tracks_maketrack <- map(
tracks_amt_list,
function(df) {
make_track(
tbl = df,
x,
y,
t,
individual_id
)
}
)
# Inspect the sampling rate with function summarize_sampling_rate
sampling_rate <- map_dfr(
tracks_maketrack,
~ summarize_sampling_rate(.x, time_unit = "min")
)
# calculate mean sampling rate
# min = 1 min, median = 146 min (2.4h), mean = 418 min (6.96 hours), max = 305347 min (212 days)
sampling_rate_summary <- sampling_rate |>
summarise(
min = min(min),
q1 = mean(q1),
median = mean(median),
mean = mean(mean),
q3 = mean(q3),
max = max(max)
)
# Time intervals
time_interval <- map_dfr(
tracks_maketrack,
\(trk) tibble(
dt_min = as.numeric(diff(trk$t_), units = "mins"),
track_id = trk$individual_id[1]
)
)
# summary time intervals per individual
time_interval_id <- time_interval |>
group_by(track_id) |>
summarise(min = min(dt_min),
mean = mean(dt_min),
max = max(dt_min)
)
# Absolute frequency
time_interval_n <- count(time_interval, dt_min, sort = TRUE)
# 10 most frequent time intervals
time_interval_top10 <- time_interval_n|>
arrange(desc(n)) |>
slice_head(n = 20)
time_interval_n %>%
filter(n >= 30) %>%
ggplot(aes(dt_min, n)) +
geom_col() +
labs(
x = "Time intervals between consecutive locations (min)",
y = "Frequency (n)") +
scale_x_continuous(breaks = seq(10, max(time_interval$dt_min, na.rm = TRUE), by = 10)) +
theme_classic() Humpback whales reach their northern limit on average between July and August and their southern limit between February and April (Table 4, Figure 4).
# Shift tracks to LAEA
tracks_sf_laea <- st_transform(tracks_sf, crs = crs_laea)
# map
tm_shape(World_laea, bbox = bbox_big) +
tm_polygons(fill = "grey70", border.col = "grey70") +
# add the tracks
tm_shape(tracks_sf_laea) +
tm_dots(fill = "month_num",
size = 0.05,
fill.scale = tm_scale_continuous(values = "kovesi.cyclic_bu_mg_yl_gn_bu"),
fill.legend = tm_legend(title = "Month", frame = FALSE)
) +
tm_facets(by = "year", ncol = 2, nrow = 2) +
# add coordinate system
tm_graticules(x = seq(-180, 180, by = 20),
y = seq(-80, 40, by = 10),
col = "grey40",
lwd = 0.2,
labels.show = TRUE,
labels.col = "grey20",
labels.size = 0.7,
labels.format = list(fun = label_fun)) +
tm_layout(bg.color = "white")Between Antarctica and Australia, humpback whales primarily exhibited travelling behavior, with concentrated use observed around Antarctica (Figure 5). Along the eastern Australian coast, travelling also predominanted, with several localized breeding and resting sites also identified.
# choosing interval of 30 min, and tolerance of 15 min
tracks_amt_calc <- map(
tracks_amt_list,
function(df) {
tr <- make_track(
tbl = df,
x,
y,
t
)
tr <- track_resample(
tr,
rate = minutes(30),
tolerance = minutes(15)
)
# to identify turning angles, we need at least 3 consecutive locations within a continuous segment
tr <- filter_min_n_burst(
tr,
min_n = 3
)
tr <- steps_by_burst(tr)
tr <- mutate(
tr,
speed_ms = sl_ / as.numeric(dt_, units = "secs")
)
tr
}
)
# as dataframe
# sl_ = step length (in CRS units [m]); ta_ = turning angles (in degrees), dt_ = time difference, burst_ = burst, speed [m/s]
tracks_amt_calc_df <- bind_rows(tracks_amt_calc)
# # check steps visually
# plot(tracks_amt_calc_df$sl_, tracks_amt_calc_df$ta_)
#
# hist(tracks_amt_calc_df$sl_)
# hist(tracks_amt_calc_df$ta_)
# Classify speed into travelling, resting and feeding-breeding
tracks_amt_calc_df <- tracks_amt_calc_df |>
mutate(Behavior = case_when(
speed_ms >= 1 ~ "Travelling",
speed_ms >= 0.56 & speed_ms < 1 ~ "Resting",
speed_ms >= 0 & speed_ms < 0.56 ~ "Feeding_breeding"))
# convert to sf object for tmap in LAEA
tracks_amt_calc_sf <- st_as_sf(
tracks_amt_calc_df,
coords = c("x2_", "y2_"),
crs = crs_laea
)
# colours for map
my_cols <- c(
"Feeding_breeding" = "#33FF33",
"Resting" = "#0066FF",
"Travelling" = "#FF33FF"
)
# map
tm_shape(World_laea, bbox = bbox_big) +
tm_polygons(fill = "grey70", border.col = "grey70") +
# add the tracks
tm_shape(tracks_amt_calc_sf) +
tm_dots(fill = "Behavior",
size = 0.2,
fill.scale = tm_scale_categorical(values = my_cols),
fill.legend = tm_legend(title = "Behavior", frame = FALSE)
) +
tm_graticules(x = seq(-180, 180, by = 20),
y = seq(-80, 40, by = 10),
col = "grey40",
lwd = 0.2,
labels.show = TRUE,
labels.col = "grey20",
labels.size = 0.7,
labels.format = list(fun = label_fun)) +
tm_layout(bg.color = "white")Satellite tag-derived trajectories identified migratory pathways and habitat use of breeding stock E1 humpback whales. Individuals migrated between Australia and Antarctica, primarily within IWC management area V (Figure 1), consistent with Andrews-Goff et al. (2023b). Some followed direct routes, while others travelled via New Zealand, suggesting potential supplementary feeding habitat during migration (Seyboth et al., 2023).
Notably, one individual migrated into the IWC management area IV, potentially reflecting prey availability, redistribution, or environmental change (Dedden & Rogers, 2022; King et al., 2021), highlighting variability in migratory pathways. Most individuals utilised Antarctic feeding grounds within IWC management area V, likely reflecting aggregation in productive feeding areas (Titova et al., 2020). Drivers of this variability remain uncertain, and further research combining satellite telemetry, prey distribution data, and environmental parameters is required.
Six individuals migrated between 5,000 – 8,646 km (Table 3), likely representing one-way movements between feeding and breeding grounds (Hoyt, 2023). The maximum distance (8,645.2 km) is comparable to humpback whale migrations between Antarctica and Central America or Colombia (Rasmussen et al., 2007; Stone et al., 1990). Although broadly comparable to Andrews-Goff et al. (2023b), minor deviations may reflect differences in methodological workflows and analytical procedures. However, most individuals exhibited shorter tracking distances, which may be a result of satellite tag signal loss, a common limitation in long-term marine mammal telemetry studies resulting from technical failure, tag detachment, or environmental conditions (Hays et al., 2007).
Seasonal patterns were assessed using timing and latitudinal extent of satellite trajectories (Figure 2; Figure 3). Monthly distribution is summarised in Table 4. A predictable annual migration cycle between feeding and breeding habitats was observed (Figure 4), consistent with breeding stocks E1, B, and G (Millien et al., 2025; Russell et al., 2022; Van Opzeeland et al., 2013). However, variable transmission durations and irregular location intervals resulted in incomplete migration trajectories, a common limitation in satellite telemetry studies (Mul et al., 2019). Behavioral classification was sensitive to temporal resolution. As migration timing of humpback whales can vary according to age, sex, reproductive state, and environmental conditions (Craig et al., 2003), integrating movement data with biological and environmental variables could improve understanding of seasonal migration patterns.
Behavioral states were inferred from swimming speed and spatial context, identifying travelling, feeding/breeding, and potential resting behavior (Figure 5). High swimming speeds of breeding stock E1 were primarily documented between Australia, Antarctica and New Zealand, consistent with migratory behavior of humpback whales moving between high-latitude feeding grounds and low-latitude breeding grounds (Evans, 1987). In contrast, lower movement rates and increased spatial occupancy within Antarctic waters (60-70°S) suggest feeding-related behavior rather than directed migration alone. Oceanographic features such as shelf edges and frontal systems may support feeding behavior through increased productivity (Friedlaender et al., 2006; Stevick et al., 2002). Within feeding grounds, movements likely reflect prey-driven foraging behavior and reduced predation risk (Amaral et al., 2016).
Moderate swimming speeds combined with prolonged spatial occupancy of Tasmanian waters may indicate resting behavior prior to or following migration (Figure 5), although additional behavioral data would be required to confirm this hypothesis. Furthermore, as seen in Figure 4, some humpback whales traveled as far North as 20°S, reaching waters associated with breeding and calving activities. Despite this, relatively few breeding behavioral states were identified north of 30°S, potentially reflecting limitations associated with the selected sampling interval and tolerance level during the behavioral state classification.
Future studies should consider interpolating satellite-tag derived localisation points at shorter temporal intervals, as higher temporal resolutions may improve the detection of short-duration behavioral states and allow for smoother transitions between behavioral states. Integrating movement trajectories with environmental and biological variables would further improve behavioral interpretability.