simulate_logbook()
generates the kind of logbook an analyst receives from a mixed
demersal-pelagic fishery, together with the truth that is never in a
real logbook: where and with which tactic each trip fished, which vessel
type made it, and how the stocks really changed. This guide walks
through the simulator layer by layer, explains the settings that matter
for targeting, and shows the basic mechanics: what the principal
components (PCs) and clusters of the catch composition pick up when we
know the truth.
The standardisation of three species from this logbook is shown in Standardising a realistic logbook: two worked examples.
| Layer | What it does | Main settings |
|---|---|---|
| Environment | shelf-to-slope depth, reef patches in sediment, SST gradient | grid, shelf_depth,
reef_share, reef_scale,
sst_range |
| Species | demersal: depth x substrate; pelagic: SST, depth and season | species (one row per species) |
| Tactics | gear catchability of each species | tactics (tactic x species) |
| Fleet | vessel types, home tactics and loyalty, entry and exit | vessel_types, home, loyalty,
entry_share, exit_share |
| Behaviour | trips go where expected value is high | price_periods, preference,
closure |
| Dynamics | Schaefer production, movement, monthly removals | r, B0, B_start,
dispersal |
| Reporting | trip records, two-set trips, coarse positions, rounding, under-reporting, synonyms | logbook |
All settings are in one list. Change any element and pass the list to
simulate_logbook(); species,
tactics, price, trips,
closure, vessel_types, home and
loyalty are replaced as a whole, the others are merged with
the defaults.
## [1] "n_years" "start_year" "grid"
## [4] "shelf_depth" "shelf_power" "depth_sd"
## [7] "depth_scale" "reef_share" "reef_scale"
## [10] "sst_range" "sst_sd" "sst_scale"
## [13] "species" "tactics" "q"
## [16] "price_periods" "price" "vessel_types"
## [19] "home" "loyalty" "vessel_cv"
## [22] "entry_share" "creep" "exit_share"
## [25] "trips" "trips_cv" "effort_season_amp"
## [28] "hours_mean" "hours_cv" "preference"
## [31] "closure" "tweedie_power" "tweedie_phi"
## [34] "logbook"
knitr::kable(s$species[, c("species", "group", "habitat", "depth_mu", "reef",
"sediment", "sst_mu", "season_amp", "price")],
row.names = FALSE)| species | group | habitat | depth_mu | reef | sediment | sst_mu | season_amp | price |
|---|---|---|---|---|---|---|---|---|
| Dentex dentex | demersal | shallow reef | 60 | 1.00 | 0.02 | NA | 0.0 | 12 |
| Pagellus erythrinus | demersal | shallow sediment | 50 | 0.05 | 1.00 | NA | 0.0 | 8 |
| Pagellus bogaraveo | demersal | deep reef | 350 | 1.00 | 0.02 | NA | 0.0 | 15 |
| Merluccius merluccius | demersal | deep sediment | 400 | 0.05 | 1.00 | NA | 0.0 | 5 |
| Conger conger | demersal | reef, all depths | 150 | 1.00 | 0.30 | NA | 0.0 | 3 |
| Phycis blennoides | demersal | deep, mixed | 500 | 0.50 | 1.00 | NA | 0.0 | 2 |
| Thunnus alalunga | pelagic | offshore | 700 | 1.00 | 1.00 | 18 | 0.7 | 6 |
| Coryphaena hippurus | pelagic | warm, offshore | 300 | 1.00 | 1.00 | 21 | 0.9 | 7 |
| Seriola dumerili | pelagic | coastal, reef-associated | 100 | 1.00 | 0.30 | 20 | 0.4 | 9 |
| Scomber colias | pelagic | coastal | 60 | 1.00 | 1.00 | 18 | 0.3 | 2 |
Depth increases offshore (to the right) with random bumps; reef patches are the highest values of a smooth random field; sea temperature increases from north (top, cool) to south (bottom, warm), as in the Southern Hemisphere.
Reef patches. reef_share is the share
of cells that are reef and reef_scale the size (correlation
length, in cells) of the patches.
reef_share or reef_scale: fewer or
smaller, scattered patches. When patches are smaller than the reporting
blocks (logbook$obs_res, 5 x 5 cells), reef and sediment
trips share the same reported position, so a spatial term cannot
separate them and only the catch composition can.The default (reef_scale = 2.5) deliberately makes
patches about the size of a reporting block or smaller.
reef_maps <- do.call(rbind, lapply(c(1, 2.5, 6), function(sc) {
e <- simulate_logbook(modifyList(s, list(reef_scale = sc, n_years = 4)),
seed = 1, plots = FALSE)$env
data.frame(e, reef_scale = paste("reef_scale =", sc))
}))
ggplot(reef_maps, aes(x = x, y = y, fill = substrate)) +
geom_raster() + facet_wrap(~reef_scale) + coord_equal() +
geom_vline(xintercept = seq(0.5, 40.5, by = 5), colour = "white", linewidth = 0.2) +
geom_hline(yintercept = seq(0.5, 40.5, by = 5), colour = "white", linewidth = 0.2) +
scale_fill_manual(values = c(reef = "#7570b3", sediment = "#e6ab02")) +
labs(x = NULL, y = NULL, fill = NULL, subtitle = "white grid: 5 x 5 reporting blocks") +
theme_bw()Demersal densities are the product of a depth preference (lognormal,
depth_mu, depth_cv) and a substrate affinity
(reef, sediment), so shallow reef, deep reef,
shallow sediment and deep sediment arise as continuous gradients rather
than sharp classes. Pelagic species follow sea temperature
(sst_mu, sst_sd) and depth, and their
availability changes over the year (season_amp,
season_peak): dolphinfish and albacore are summer-autumn
migrants.
A tactic is a gear used in a particular way. Its catchability of each
species (tactics) is the gear selectivity; where the gear
is used decides which species are available. The reef handline catches
reef species, the bottom longline sediment species, and pelagic trolling
the pelagic species, with some overlap (conger is caught by both bottom
gears; amberjack by reef handline and trolling).
q <- as.data.frame(as.table(s$tactics))
names(q) <- c("tactic", "species", "catchability")
ggplot(q, aes(x = species, y = tactic, fill = catchability)) +
geom_tile(colour = "white") +
geom_text(aes(label = catchability), size = 2.8) +
scale_fill_viridis_c(option = "rocket", direction = -1, trans = "sqrt") +
labs(x = NULL, y = NULL) + theme_bw() +
theme(axis.text.x = element_text(angle = 30, hjust = 1, size = 7))Three vessel types (vessel_types) fish with different
flexibility:
Each month, a share loyalty of a specialist’s trips
(default 0.8) is restricted to its home tactics; the remaining trips,
and all trips of mixed vessels, choose among all tactics by expected
value. Specialists therefore mostly stick to their gear but follow good
opportunities, e.g. demersal boats trolling for dolphinfish in a good
summer.
## $demersal
## [1] "Reef" "Sediment"
##
## $pelagic
## [1] "Pelagic"
##
## $mixed
## [1] "Reef" "Sediment" "Pelagic"
## demersal pelagic mixed
## 0.8 0.8 0.0
## tactic
## type Pelagic Reef Sediment
## demersal 0.09 0.51 0.41
## mixed 0.47 0.30 0.23
## pelagic 0.89 0.06 0.05
## demersal mixed pelagic
## 0.7966311 0.0000000 0.8069538
Why it matters for standardisation: a specialist’s targeting barely changes, so a vessel effect absorbs it. Mixed vessels (and the non-loyal trips of specialists) switch tactics within the same vessel as prices change, which is the targeting that the catch composition has to capture.
loyalty = 1: specialists never leave their home
tactics.loyalty = 0 for all types: every vessel behaves as a
mixed vessel, the strongest targeting shifts.preference: how strongly trips concentrate on the most
valuable cells and tactics (higher = more decisive skippers).Prices change in three periods: demersal species are expensive in
2000-2007, pelagic species boom in 2008-2015, then prices are neutral.
From 2016 the bottom longline is banned deeper than 300 m and effort is
cut by 20%. Some vessels enter later (and are more efficient,
creep), others leave.
The result is that nominal CPUE (orange) departs from the true biomass (black) in different ways for each species:
The logbook records trips, not sets. A share
logbook$two_sets of trips (default 0.3) makes a second set,
and with probability logbook$switch_tactic (default 0.7)
the second set uses another tactic. The catches of both sets are summed
into one record at the position of the first set, so these trips mix two
catch compositions, as in many real logbooks.
## [1] 0.1783129
## demersal mixed pelagic
## 0.216 0.207 0.038
Pelagic specialists make mixed trips only on their non-loyal trips. Further reporting settings:
| Setting | Default | Effect |
|---|---|---|
obs_res |
5 | positions reported as centres of 5 x 5 blocks |
missing_position |
0.02 | share of trips without position |
round_to |
0.5 | catches rounded to 0.5 kg |
underreport |
small catches (< 2 kg) of cheap species (price <= 3) | dropped with probability 0.5 |
synonyms, synonym_rate |
blackspot seabream | 10% recorded under its common name |
## trip year month vessel hours lon lat species kg
## 1 1 2000 1 V04 7.3 3.85 36.85 Dentex dentex 256.5
## 2 1 2000 1 V04 7.3 3.85 36.85 Scomber colias 23.5
## 3 1 2000 1 V04 7.3 3.85 36.85 Seriola dumerili 14.0
## 4 2 2000 1 V12 9.7 3.85 36.85 Conger conger 83.5
## 5 2 2000 1 V12 9.7 3.85 36.85 Merluccius merluccius 24.5
## 6 2 2000 1 V12 9.7 3.85 36.85 Scomber colias 3.5
## 7 2 2000 1 V12 9.7 3.85 36.85 Seriola dumerili 9.5
## 8 3 2000 1 V10 7.8 4.85 39.35 Pagellus bogaraveo 30.5
We now take the logbook through the first steps of the toolbox and compare the targeting covariates with the truth.
x <- cpue_data(sim$logbook, year = "year", species = "species", catch = "kg",
effort = "hours", id = "trip", vessel = "vessel",
lon = "lon", lat = "lat", covariates = "month",
synonyms = c("Blackspot seabream" = "Pagellus bogaraveo"))
x <- subset(x, !is.na(lon), note = "positions reported")
x <- select_species(x, threshold = 0.95)
x <- add_targeting(x)
x$targeting$pca## <cpue_pca> 19218 operations, 10 species, transform: fourth_root
## PC eigenvalue share cumulative
## 1 2.192 0.219 0.219
## 2 1.707 0.171 0.390
## 3 1.340 0.134 0.524
## 4 1.108 0.111 0.635
## 5 1.056 0.106 0.740
## 6 0.792 0.079 0.820
## 7 0.569 0.057 0.876
## 8 0.530 0.053 0.929
## Optimal Coordinates: 3 non-trivial PC(s); 4 clusters by the npc + 1 rule
Attach the truth of each trip (never available in real data):
truth <- sim$trips[match(x$data$trip, sim$trips$trip), ]
x$data$true_tactic <- truth$tactic
x$data$habitat <- ifelse(truth$tactic == "Pelagic", "pelagic", truth$habitat)
x$data$depth <- truth$depth
x$data$mixed <- ifelse(!is.na(truth$tactic2) & truth$tactic2 != truth$tactic,
"two tactics", "one tactic")
x$data$X <- truth$X
x$data$Y <- truth$YRead the axes from the species arrows (loadings). In this fishery the first PC typically separates pelagic from demersal trips, and the next PCs reef from sediment and shallow from deep: the PCA recovers tactic and habitat from the catch alone, without being told either. Which PC carries which contrast can change between runs and settings, so always check the loadings.
demersal_trips <- x$data$true_tactic != "Pelagic"
ggplot(x$data[demersal_trips, ], aes(x = depth, y = PC2, colour = true_tactic)) +
geom_point(alpha = 0.3, size = 0.7) + scale_x_log10() +
labs(x = "Depth of the first set (m, log scale)", colour = "True tactic",
title = "Demersal trips: PC2 against depth") + theme_bw()If depth is carried by another PC in your run, replace
PC2 by that PC.
Averaged by the true cell, the PC scores map the habitat at a finer scale than the reported positions; the reported 5 x 5 blocks blur it.
cell_pc <- aggregate(cbind(PC1, PC2) ~ X + Y, data = x$data, FUN = mean)
pm <- rbind(data.frame(X = cell_pc$X, Y = cell_pc$Y, score = cell_pc$PC1, pc = "PC1"),
data.frame(X = cell_pc$X, Y = cell_pc$Y, score = cell_pc$PC2, pc = "PC2"))
ggplot(pm, aes(x = X, y = Y, fill = score)) +
geom_raster() + facet_wrap(~pc) + coord_equal() +
scale_fill_gradient2(low = "#2166ac", mid = "grey95", high = "#b2182b") +
labs(x = "x (offshore ->)", y = "y", fill = "Mean score",
title = "Mean PC score by true cell") + theme_bw()Trips that combine two tactics have intermediate compositions. PCs place them continuously; clusters have to assign each to one tactic.
## FT operations share dominant Scomber colias Seriola dumerili
## 1 1 9936 0.517 Scomber colias 38.3 11.6
## 2 2 3620 0.188 Thunnus alalunga 2.2 1.9
## 3 3 2849 0.148 Pagellus bogaraveo 1.6 1.6
## 4 4 2813 0.146 Merluccius merluccius 2.4 1.6
## Conger conger Thunnus alalunga Coryphaena hippurus Pagellus erythrinus
## 1 10.8 0.7 8.8 15.4
## 2 1.1 79.6 10.1 2.2
## 3 3.2 0.7 2.0 9.0
## 4 2.4 1.0 1.1 2.6
## Pagellus bogaraveo Merluccius merluccius Phycis blennoides Dentex dentex
## 1 0.5 0.5 0.2 13.1
## 2 0.6 0.7 0.4 1.2
## 3 75.5 1.6 0.7 4.0
## 4 2.1 73.2 10.9 2.7
## tactic
## cluster Pelagic Reef Sediment
## 1 0.43 0.33 0.24
## 2 0.96 0.02 0.02
## 3 0.05 0.85 0.10
## 4 0.07 0.16 0.78
## habitat
## cluster deep reef deep sediment pelagic shallow reef shallow sediment
## 1 0.04 0.01 0.43 0.22 0.30
## 2 0.01 0.01 0.96 0.01 0.01
## 3 0.83 0.03 0.05 0.03 0.06
## 4 0.10 0.75 0.07 0.04 0.04
Clusters describe the catch composition, which reflects both the gear and where it was used, so they rarely match tactics one to one: mixed trips, gear overlap and neighbouring habitats blur the link.
The clusters and PCs change in steps at the price changes (2008, 2016) and the closure (2016), as the true tactic shares do.
groups <- split(sim$settings$species$species, sim$settings$species$group)
type <- tapply(sim$trips$vessel_type, sprintf("V%02d", sim$trips$vessel),
function(z) z[1])
plot_vessel_profile(x, groups = groups, by = type)Specialists sit at the ends (almost all demersal or almost all
pelagic catch), mixed vessels in between. With loyalty 0.8 the
specialists are clear but not pure, so rules on the catch of the target
species (select_vessels()) recover them only
approximately.
reef_scale = 1 against
6, and compare Base+S with DPC+S
in the standardisation: the gap shrinks as patches grow larger than the
reporting blocks.loyalty = c(demersal = 1, pelagic = 1, mixed = 0) (strict
specialists) or all zero (every vessel mixed).logbook = list(two_sets = 0) (one set per trip) or
switch_tactic = 1; see how the clusters separate and how
the PC biplot changes.obs_res = 1 (exact
positions) against 10 (very coarse).B_start or
r so that species trends diverge, and check whether the PCs
start absorbing them (compare n_pc).Winker, H., Kerwath, S.E. and Attwood, C.G. (2014) Proof of concept for a novel procedure to standardize multispecies catch and effort data. Fisheries Research 155: 149-159.
Thorson, J.T., Fonner, R., Haltuch, M.A., Ono, K. and Winker, H. (2017) Accounting for spatiotemporal variation and fisher targeting when estimating abundance from multispecies fishery data. Canadian Journal of Fisheries and Aquatic Sciences 74: 1794-1807.