SimpleOM <- OM('Example OM',
nYear=30,
pYear=20,
nSim=48)3 Build a Simple OM
This chapter describes the contents of OM objects by going through the process of manually constructing an operating model (OM).
It uses an expert judgement-based approach, where the OM parameters are entered manually, with parameter uncertainties specified as distributions which are sampled when the OM is used to simulate and project a fishery.
3.1 Initialize OM
The OM() function is used to create a new Operating Model object (see ?OM). The contents of the OM can be specified with arguments to the OM function:
or by using functions matching the names of the slots in the object.
For example, here we’ll change the number of independent stochastic simulations in our OM from the default nSim=48 to a small number so that the code runs very quickly:
nSim(SimpleOM)[1] 48
nSim(SimpleOM) <- 5
nSim(SimpleOM)[1] 5
Similarly, the number of historical years and projection years can be changed:
nYear(SimpleOM) <- 20
pYear(SimpleOM) <- 103.2 Years and Seasons
CurrentYear is the last historical year before the projections begin, and is automatically set to the current calendar year:
CurrentYear(SimpleOM)[1] 2025
This can be over-written using either the CurrentYear argument in OM() or by assigning a new value to the SimpleOM object with CurrentYear():
CurrentYear(SimpleOM) <- 2020The Years function can be used to return the values of the historical or projection years:
Years(SimpleOM, 'H') [1] 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015
[16] 2016 2017 2018 2019 2020
Years(SimpleOM, 'P') [1] 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030
Unless specified otherwise, operating models are constructed using annual time steps. Seasonality can be added to the model by assigning a value to the Seasons slot of the OM object:
Seasons(SimpleOM) <- 4 # 4-quarters
Years(SimpleOM, 'H') |> head(8)[1] 2001.000 2001.247 2001.496 2001.748 2002.000 2002.247 2002.496 2002.748
As shown above, Seasons changes the values of the historical and projection years into decimal years corresponding with the specified number of seasons within a year.
Almost all of the openMSE objects have been developed using the R S4 system.
S4 objects contain slots, named components of the object that can be accessed using the @ operator (this is analogous to using the $ symbol to access contents of S3 objects), for example:
slotNames(SimpleOM) [1] "Name" "Agency" "Author" "Email" "Region"
[6] "Latitude" "Longitude" "Sponsor" "nSim" "nYear"
[11] "pYear" "CurrentYear" "Stock" "Fleet" "Obs"
[16] "Imp" "Data" "DataLag" "CatchFrac" "Allocation"
[21] "EFactor" "Complexes" "SexPars" "Relations" "Interval"
[26] "nReps" "pStar" "maxF" "Seed" "Seasons"
[31] "Years" "Control" "Misc" "Log" "Source"
SimpleOM@nSim[1] 5
The @ symbol can be used to assign new values to slots, for example:
SimpleOM@nSim <- 5While earlier versions of openMSE advocated using the @ symbol to access slots and assign new values, this practice is not recommended for openMSE 2.0. Instead, users are encouraged to use the accessor and assignment functions that have been developed for each object class.
This is especially important when assigning new values, where the assignment functions may have side effects that will be missed if the @ symbol is used.
For example, consider the Seasons assignment function:
`Seasons<-`function(x, value) {
CheckClass(x)
x@Seasons <- value
x@Years <- CalcYears(x@nYear, x@pYear, x@CurrentYear, x@Seasons)
x
}
<bytecode: 0x000001a2f9335a80>
<environment: namespace:MSEtool>
Note that in addition to assigning the new value to the Seasons slot, the Seasons assignment function also recalculates the values for the Years slot, a step that would have been missed if the new value was assigned directly using the @ symbol and would likely lead to unexpected errors.
If required, the lubridate package can be used to convert decimal years into dates (and back again):
SimpleOM |>
Years() |>
lubridate::date_decimal() |>
lubridate::as_date() |>
head()[1] "2001-01-01" "2001-04-01" "2001-07-01" "2001-09-30" "2002-01-01"
[6] "2002-04-01"
The Seasons value in the OM defines the number of historical and projection time steps, as well as the structure of the age classes for all stocks in the OM.
The accounting in openMSE always starts at the beginning of the first historical year (i.e., Years(SimpleOM)[1]) and moves sequentially through the annual or seasonal time steps in Years(SimpleOM).
All stocks must have the same time units as the OM. See the Ages section below for more details.
Additionally, because it is used to set up the time and age structure of the model, the Seasons value should not be changed once an operating model is constructed.
3.3 Specify a Stock Object
OM objects can contain one or more Stock objects.
A Stock object contains the information related the biological characteristics of a stock, including growth and maturity schedules, natural mortality rates, stock-recruitment relationship, and other information relating to spatial distribution and movement patterns (see ?Stock for more details).
Here we create an example Stock object using the expert judgment approach described above. The stock is loosely based on albacore Thunnus alalunga and should only be considered an example for demonstration purposes.
SimpleStock <- Stock('Example Stock',
CommonName = 'Albacore',
Species = "Thunnus alalunga")In addition to Name, CommonName, and Species that were specified in the call to the Stock() function, Stock objects contain several other sub-objects that need to be populated:
AgesLengthWeightNaturalMortalityMaturityFecunditySRRSpatialDepletion
The sub-objects in italics are optional, see the sections below for details. The other sub-objects must be populated to complete the Stock object.
Help documentation can be accessed for all openMSE objects and functions, e.g.,
?OM
?Stock
?Ages
?Length
# etcStrictly speaking, the Length object is also optional if no other objects are a function of length (e.g., Weight, Maturity, Fecundity and Selectivity etc in the Fleet object.
See Chapter 7 for an example of an OM that does not use Length.
3.3.1 Ages
An Ages object contains information relating to the age structure of the stock.
Ages(SimpleStock) <- Ages(MaxAge=4*20, Units='quarter')
Ages(SimpleStock)
── An `?MSEtool::Ages()` Object ──
── `MinAge`
0
── `MaxAge`
80
── `Units`
"quarter"
── `Classes` (Year)
0, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75,
4, 4.25, …, 19.75, and 20
── `PlusGroup`
TRUE
Note that MaxAge is set in time units of quarter. It is important that the time units in the Ages object matches the number of seasons in the OM.
Also note that, following the convention in Years(OM) the age classes are always in units of year:
AgeClasses(SimpleStock) [1] 0.00 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00 2.25 2.50 2.75
[13] 3.00 3.25 3.50 3.75 4.00 4.25 4.50 4.75 5.00 5.25 5.50 5.75
[25] 6.00 6.25 6.50 6.75 7.00 7.25 7.50 7.75 8.00 8.25 8.50 8.75
[37] 9.00 9.25 9.50 9.75 10.00 10.25 10.50 10.75 11.00 11.25 11.50 11.75
[49] 12.00 12.25 12.50 12.75 13.00 13.25 13.50 13.75 14.00 14.25 14.50 14.75
[61] 15.00 15.25 15.50 15.75 16.00 16.25 16.50 16.75 17.00 17.25 17.50 17.75
[73] 18.00 18.25 18.50 18.75 19.00 19.25 19.50 19.75 20.00
To keep things simple, we’ll change our OM back to annual time-steps and re-recreate the Ages object accordingly:
Seasons(SimpleOM) <- 1 # annual
Ages(SimpleStock) <- Ages(MaxAge=20)3.3.2 Length
Most sub-objects in Stock and Fleet objects are structured and populated in a similar manner to Length objects.
This section describes populating Length objects in detail. Other sub-objects are described in less detail, and readers should refer back to this section for the specific details.
The Length object describes the mean length-at-age schedule and how length-at-age is distributed around the mean.
The main pieces of information in the Length object are stored in slots named:
-
MeanAtAge: the mean length-at-age schedule -
ASK: the age-size key used to convert at-length schedules to at-age (and vice versa)
MeanAtAge can be specified in two ways:
- A growth model and a list of the respective parameter values
- Directly as an array specifying the mean length-at-age for each simulation and year.
