The microxanox
package may be updated / changed, so
please take care to work with a specific version. This reproduction
guide requires at least version 0.9.2 and the loaded version is:
## [1] '0.9.3'
TO become convenient with the package’s power and its function’s
please first consult the original
user guide of the microxanox
package developed by Owen L. Petchey and Rainer M. Krug to
understand the workflow of setting up different simulation and analyse,
visualize and interpret their results. This reproduction guide
particularly serves the purpose to explain the workflow necessary to set
up the symmetric model and perform symmetric simulations, as well as
asymmetric manipulations of the latter.
Compared to the version 0.9.1 of the microxanox
package
we added functionality for:
To initialize a symmetric strain parameter set
new_strain_parameter
with values argument ==
symmetric
needs to be called. Number of strains stays one,
meaning no investigations in trait variation.
# number of strains per group
num_strains <- 1
# initial abundance of strain is set to 10^5 per default
num_CB_strains <- num_strains
num_SB_strains <- num_strains
num_PB_strains <- num_strains
# values == "symmetric" initiates symmetric strain parameter
sp <- new_strain_parameter(
n_CB = num_CB_strains,
values_CB = "symmetric",
n_PB = num_SB_strains,
values_PB = "symmetric",
n_SB = num_PB_strains,
values_SB = "symmetric",
values_other = "symmetric",
values_initial_state = "symmetric"
)
The simulation framework is initialized by calling
sym_new_strain_parameter
. The extent and pattern of
environmental change is implemented in the log10a_series
and asym_factor
argument (i.e. symmetric means 1) and its
speed with the sim_sample_interval
. The
sim_duration
is then calculated from number of steps times
wait time per step. Here, it is important to set the
dynamic model
to
symmetric_bush_plus_dynamic_model
, as well as using
event_definintion_symmetric
for the
event_definition
argument.
# Simulation dimensions
wait_time <- 100 ## time spent at each step, sim_sample_interval
event_interval <- 10 ## interval of event occurence during simulation
# Environmental properties
asym_factor <- 1 ## defines asymmetry in the system, 1 means symmetric
start_aO <- -2 ## start of oxygen diffusivity vector
start_aS <- 0 ## start of sulfur diffusivity vector
steps <- 1e3 ## number of steps with duration of one wait_time
log10a_series <- seq(start_aO, start_aS, length = steps)
parameter <- new_runsim_parameter(
dynamic_model = symmetric_bushplus_dynamic_model, ## sym!
event_definition = event_definition_symmetric, ## sym!
event_interval = event_interval,
noise_sigma = 0,
minimum_abundances = c(1, 0 , 1), ## PB stays 0
strain_parameter = sp,
log10a_series = log10a_series,
asym_factor = 1 ## 1 -> symmetric!
)
names(parameter$minimum_abundances) <- c("CB", "PB", "SB") ## rename subvector of paramter list
# rm(sp)
parameter$sim_duration <- wait_time * length(parameter$log10a_series)
parameter$sim_sample_interval <- wait_time ## to avoid having negative ODE results
Running a single simulation is done with with
run_simlation_symmetric
. In contrast,
run_temporal_ssfind
is used to find stable states across a
gradient of the given diffusivity pattern in log10a_series.
However, first it is important to understand how to control the environmental pattern of change to be able to produce the desired simulations.
log10a_series
and using
set_diffusivities
to control the pattern of changeTo observe regime shifts in both direction, we have to change the
log10a_series of both oxygen and sulfide diffusivity. This is done by
first changing the sequence log10a_series
, which directly
defines the oxygen diffusivity vector
(i.e. log10aO_series
), followed by updating the new series
in the object parameter
.
# define series
log10a_series <- c(seq(start_aO, start_aS, length = steps),
rep(start_aS, times = 10),
seq(start_aS, start_aO, length = steps),
rep(start_aO, times = 10),
seq(start_aO, start_aS, length = steps),
rep(start_aS, times = 10))
# redefine in parameter
parameter$log10a_series <- log10a_series
To now apply the changes done in log10a_series, onto
10aO_series
and the inverse log10aS_series
in
parameter
we need the helper function
set_diffusivities
. This function sets the
log10aO_series
and log10aS_series
(inversed)
in the parameter object. It is absolutely necessary to use this function
WHENEVER the diffusivity pattern of change is modified! The diffusivity
pattern of change is always modified by changing
parameter$log10a_series
.
Let’s visualize the diffusivity pattern we have created to ensure it our simulation will go as expected. We see that the pattern is inverted as desired.
run_simulation_symmetric
: Dynamics according to given
vector iNext, we will run a symmetric simulation driven by the vector we just
defined. For more realistic simulations we can increase the
parameter$sim_duration
, but doing so can lead to simulation
taking enormous amounts of time, if the used computer has low
parallelized computation power. Thus, we will leave it short (and not in
stable state) for presentation purposes.
The simulation is run by calling the function
run_simulation_symmetric
and assigning its result to a
variable.
run_simulation_symmetric
with
plot_dynamics_symmetric
We implemented a convenience function
plot_dynamics_symmetric
to quickly visualize the result
from run_simulation_symmetric
. By putting the argument
plot_a
to TRUE
we can additionally visualize
the pattern of diffusivity already shown above.
run_temporal_ssfind_symmetric
: Dynamics in both
direction of given vector with the temporal methodThe function run_temporal_ssfind_symmetric
performs
simulations forth and back of the provided environmental driver pattern.
It is suited to find the optimal value for wait_time, to eventually make
the system display stable states. Here, we leave the wait_time short
again to keep the simulation fast computing-wise.
First, we need to change the diffusivities again to only go in one direction, as the temporal method itself runs two simulations, one in either direction of environmental change.
parameter$log10a_series <- seq(start_aO, start_aS, length = steps)
parameter <- set_diffusivities(parameter)
Again, we check whether the diffusivity pattern behaves as expected:
We are now ready to do the the experiment with the temporal method by
using run_temporal_ssfind_symmetric
:
result_temporal <- run_temporal_ssfind_symmetric(parameter)
saveRDS(result_temporal, file = mdat("result_temporal.RDS"))
To visualize the temporal dynamics resulting from the input
diffusivity pattern we use the convenience function
plot_temporal_ss
that has been updated from the
microxanox
version 0.9.1 to be compatible with symmetric
results.
To run asymmetric experiments we first have to change to the parameter configuration to be asymmetric. We do this by either changing trait values, background conditions or the diffusivity pattern. Here, we look at examples trait and diffusivity asymmetry.
An example for asymmetric trait values would be to change the tolerance of sulfur-reducing bacteria. (i.e. changing the half-inhibition constant). Here, we decrease the tolerance from 100 to 30 μM,
Next, we simulate the dynamics using the temporal method:
We can also modify the diffusivity pattern to be asymmetric. To
change the diffusivity pattern we use the asym_factor
argument of the helper function set_diffusivities
; you can
explore the relationship between the asym_factor
and the
asymmetric diffusivity pattern. It is also important to remember to make
trait values symmetric again. Here, we choose the
asym_factor
to be e.g. 0.6, a value of 1 would mean a
symmetric pattern.
# trait symmetry by assigning tolerance of CB
parameter$strain_parameter$SB$h_O_SB <- parameter$strain_parameter$CB$h_SR_CB
# change the pattern
parameter <- set_diffusivities(param = parameter,
asym_factor = 0.6) ## here we set the factor of 0.5
ui <- fluidPage(
sliderInput(
"variable",
"Asymmetry Factor:",
min = 0,
max = 2,
value = 1,
step = 0.1,
ticks = seq(0, 2, by = 0.1)
),
plotOutput("plot")
)
server <- function(input, output) {
output$plot <- renderPlot({
# extract the factor and update the parameter set
asym_factor <- input$variable
parameter <- set_diffusivities(parameter, asym_factor)
# define a time vector
time <- seq(0, 1, length = length(parameter$log10a_series))
# define a data frame suited for plotting
plt.df <- data.frame(value = c(parameter$log10aO_series, parameter$log10aS_series),
key = rep(c("Oxygen diffusivity", "Sulfur diffusivity"), each = length(parameter$log10a_series)),
time = rep(time, times = 2))
# create plot
ggplot(data = plt.df) +
geom_path(aes(x = time, y = value, color = key)) +
scale_color_manual(values = c("#e85050", "#5da1df")) +
# geom_hline(aes(yintercept = axis, color = "sym axis"), linetype = "dashed") +
labs(x = "Time", y = "Value", color = "") +
theme_bw()
})
}
Let’s run the dynamics resulting from the diffusivity pattern with asymmetry factor 0.6.
The function get_symmetry_measurements
returns various
metrics used to quantify the (a)symmetry.
## anox_TP anox_TPafter state_anox_TP state_anox_TPafter ox_TP
## CB_1 -0.8294314 -0.8227425 1.969485e+01 4.014967e+09 -1.197324
## SB_1 -0.8294314 -0.8227425 3.942534e+09 7.766993e-08 -1.197324
## SR -0.8294314 -0.8227425 3.188228e+01 8.487129e+00 -1.197324
## O -0.8294314 -0.8227425 3.171898e+01 8.440474e+01 -1.197324
## P -0.8294314 -0.8227425 5.568052e-01 3.833119e-01 -1.197324
## ox_TPafter state_ox_TP state_ox_TPafter hyst_area hyst_range
## CB_1 -1.204013 3.947989e+09 2.251713e-08 1.468910e+09 0.367893
## SB_1 -1.204013 5.130508e+01 4.020459e+09 1.469960e+09 0.367893
## SR -1.204013 3.023815e+01 9.222883e+01 1.730512e+01 0.367893
## O -1.204013 3.030103e+01 6.348001e+00 1.599961e+01 0.367893
## P -1.204013 5.437381e-01 3.701584e-01 2.514698e-03 0.367893
## abs_shift_recovery abs_shift_catastrophy
## CB_1 4.014967e+09 3.947989e+09
## SB_1 4.020459e+09 3.942534e+09
## SR 6.199068e+01 2.339515e+01
## O 5.268577e+01 2.395303e+01
## P 1.734933e-01 1.735796e-01
The (a)symmetry measures obtained from
get_symmetry_measurements
can be directly visualized using
plot_symmetry_measures
. This convenience function serves
for graphical orientation of the measurements. As a first argument it
takes the results data frame and as the second one we need to define the
species to plot, which is either a bacteria or a chemical.
## Warning in geom_segment(data = slice(plot_df, c(1, 2)), mapping = aes(x = aO[1], : All aesthetics have length 1, but the data has 2 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
## a single row.
## Warning in geom_segment(data = slice(plot_df, c(3, 4)), mapping = aes(x = aO[1], : All aesthetics have length 1, but the data has 2 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
## a single row.
To visualize the asymmetry between amelioration and degradation
trajectories is it recommend to use the function
plot_tajectory_asymmetry
, as it better organizes contrasts
the visual difference between these trajectory dynamics. As arguments it
takes the typ
of trajectory to plot (“bacteria” or
“substrate”) and the direction of the trajectory
(“recovery” or “collapse”)
up <- plot_trajectory_symmetry(result_stressor.asym_0.6, typ = "substrate", trajectory = "recovery")
down <- plot_trajectory_symmetry(result_stressor.asym_0.6, typ = "substrate", trajectory = "collapse")
wrap_plots(up, down) + plot_layout(guides = "collect") & theme(plot.title = element_blank())
To plot upwards and downwards shifts in one panel with the function
plot_tajectory_symmetry_compact
. It is the straightforward
that the argument trajectory
cannot be specified here.
Contact
Thank you for reading this user guide. If there are still remaining questions or you find bugs of any kind I would be pleased if you reached out!
log10a_series
and using set_diffusivities
to
control the pattern of changerun_simulation_symmetric
:
Dynamics according to given vector irun_simulation_symmetric
with
plot_dynamics_symmetric
run_temporal_ssfind_symmetric
:
Dynamics in both direction of given vector with the temporal
method