中文 | Español | English | português | Turkish

knitr::opts_chunk$set(echo = FALSE)
library(ecoevoapps)
library(tidyverse)
library(patchwork)
library(knitr)
library(kableExtra)

Mutualismo é um tipo de interação interespecífica na qual as espécies envolvidas provém uma a outra um efeito líquido benéfico. Mutualismos podem se manifestar de diversas formas, incluindo interações entre plantas e polinizadores, dispersão de propágulos por animais e defesa contra predadores. Por exemplo, as vespas do figo polinizam as flores da figueira em troca de um local seguro para se alimentar e ovipor (Cook & Rasplus 2003). Outro exemplo clássico é o mutualismo entre formigas e acácias, no qual as formigas se alimentam e nidificam dentro de estruturas criadas pelas acácias, mas protegem a planta de herbívoros (Janzen 1966). Uma visão mais detalhada sobre mutualismo pode ser encontrada em Bronstein (2015).

Este aplicativo explora um modelo de mutualismo direto entre duas espécies (Holland 2012). A ideia central do modelo é que o crescimento populacional de cada espécie ($\frac{dN}{dt}$) é alterado pelas interações tanto com indivíduos da mesma espécie (intraespecífica) como com indivíduos da outra espécie (interespecífica), assim como o modelo de competição de Lotka-Volterra. Quando sozinhas, cada espécie sofre competição intraespecífica e suas populações crescem até atingir suas respectivas capacidades de suporte. Porém, quando as duas espécies interagem elas se beneficiam reciprocamente, permitindo que suas populações crescem além da capacidade de suporte. O modelo também assume que há uma diminuição dos benefícios oriundos da interação mutualística, isto é, que os efeitos positivos recíprocos param de crescer e se estabilizam conforme as populações das duas espécies crescem.

Dadas essas considerações, o modelo pode ser escrito assim:

$$\frac{dN_1}{dt} = r_1N_1 + \frac{\alpha_{12}N_2}{b_2 + N_2}N_1 - d_1N_1^2$$ $$\frac{dN_2}{dt} = r_2N_2 + \frac{\alpha_{21}N_1}{b_1 + N_1}N_2 - d_2N_2^2$$

As descrições de cada parâmetro do modelo estão listadas na tabela abaixo. Em cada uma das equações o primeiro termo ($r_iN_i$) descreve o crescimento populacional na ausência de interações intra- ou interespecíficas. O segundo termo ($\frac{\alpha_{ij}N_j}{b_j + N_j}N_i$) descreve como o crescimento populacional aumenta como uma função de saturação do tamanho da população da espécie mutualista (essa função de saturação segue a forma da curva de Michaelis–Menten). O terceiro termo ($d_iN_i^2$) descreve como a taxa de crescimento populacional de uma espécie diminui conforme sua própria população cresce (competição intraespecífica).

pars <- c("$r_i$",
          "$N_i$",
          "$\\alpha_{ij}$",
          "$d_i$",
          "$b_i$")
descriptions <- c("Crescimento per capita da espécie $i$",
                  "Tamanho populacional da espécie $i$",
                  "Efeito per capita do mutualismo da espécie $j$ na espécie $i$",
                  "Taxa de auto-limitação da espécie $i$",
                  "Constante de meia saturação da equação de Michaelis-Menten equation, isto é, o tamanho populacional da espécie $i$ que provê metade do valor máximo de benefício que pode ser dado à espécie $j$")
param_df <- data.frame(pars, descriptions)
kable(x = param_df,
      format = "html",
      col.names = c("Parâmetro ou Variável", "Descrição"),
      table.attr = "style='width:50%;'") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                position = "center")

Para explorar como as populações crescem com interações mutualistas podemos usar o modelo para simular as trajetórias populacionais ao longo do tempo (selecione "N vs. time"). Podemos também explorar as consequências de longo prazo das interações mutualistas ao analisar os gráficos que mostram as isóclinas de crescimento líquido zero, que mostram as condições sob as quais o crescimento populacional é zero ($\frac{dN_1}{dt} = \frac{dN_2}{dt} = 0$). A análise desses gráficos nos permite identificar os tamanhos populacionais que as espécies mutualistas têm quando entram em equilíbrio (selecione "Retrato de fase").

##### UI #####

# Input panel
wellPanel(
  fluidRow(
    column(4, numericInput(inputId = "r1",
                           label = HTML("r<sub>1</sub>: Taxa de crescimento per capita da sp. 1"),
                           value = 0.5,
                           step = 0.1)),
    column(4, numericInput(inputId = "r2",
                           label = HTML("r<sub>2</sub>: Taxa de crescimento per capita da sp. 2"),
                           value = 0.5,
                           step = 0.1)),
    column(4, numericInput(inputId = "N1",
                           label = "Tamanho populacional inicial da sp. 1",
                           value = 20,
                           min = 0,
                           step = 1))),
  fluidRow(
    column(4, numericInput(inputId = "a12",
                           label = HTML("&alpha;<sub>12</sub>: Efeito da sp. 2 na sp. 1"),
                           value = 0.8,
                           min = 0,
                           step = 0.1)),
    column(4, numericInput(inputId = "a21",
                           label = HTML("&alpha;<sub>21</sub>: Efeito da sp. 1 na sp. 2"),
                           value = 0.4,
                           min = 0,
                           step = 0.1)),
    column(4, numericInput(inputId = "N2",
                           label = "Tamanho populacional inicial da sp. 2",
                           value = 40,
                           min = 0,
                           step = 1))),
  fluidRow(
    column(4, numericInput(inputId = "d1",
                           label = HTML("d<sub>1</sub>: Taxa de auto-limitação da sp. 1"),
                           value = 0.02,
                           min = 0,
                           step = 0.01)),
    column(4, numericInput(inputId = "d2",
                           label = HTML("d<sub>2</sub>: Taxa de auto-limitação da sp. 2"),
                           value = 0.01,
                           min = 0,
                           step = 0.01)),
    column(4, numericInput(inputId = "time",
                           label = "Tempo de duração da simulação",
                           value = 50,
                           min = 1,
                           step = 1))),
  fluidRow(
    column(4, numericInput(inputId = "b1",
                           label = HTML("b<sub>1</sub>: Constante de meia saturação da sp. 1"),
                           value = 10,
                           min = 0,
                           step = 1)),
    column(4, numericInput(inputId = "b2",
                           label = HTML("b<sub>2</sub>:  Constante de meia saturação da sp. 2"),
                           value = 10,
                           min = 0,
                           step = 1)),
    column(2, radioButtons(inputId = "plot",
                           label = "Gráfico",
                           choices = c("N vs. tempo" = "time",
                                       "Retrato de fase" = "phase",
                                       "Ambos" = "both"),
                           selected = "both")),
    column(2, conditionalPanel(
      condition = "input.plot != 'time'",
      checkboxGroupInput(inputId = "phase_opt",
                         label = "Draw",
                         choices = c("Vector field" = "vec",
                                     "Population trajectories" = "traj"),
                         selected = c("vec", "traj")))))
)

# Output panel
fluidRow(
  column(12, renderPlot(plot(), height = 500))
)

##### Server #####

# Validate input
observeEvent(input$a12, {
  if (input$a12 <= 0) updateNumericInput(inputId = "a12", value = 0.1)
})
observeEvent(input$a21, {
  if (input$a21 <= 0) updateNumericInput(inputId = "a21", value = 0.1)
})
observeEvent(input$d1, {
  if (input$d1 <= 0) updateNumericInput(inputId = "d1", value = 0.01)
})
observeEvent(input$d2, {
  if (input$d2 <= 0) updateNumericInput(inputId = "d2", value = 0.01)
})
observeEvent(input$b1, {
  if (input$b1 <= 0) updateNumericInput(inputId = "b1", value = 1)
})
observeEvent(input$b2, {
  if (input$b2 <= 0) updateNumericInput(inputId = "b2", value = 1)
})
observeEvent(input$N1, {
  if (input$N1 <= 0) updateNumericInput(inputId = "N1", value = 1)
})
observeEvent(input$N2, {
  if (input$N2 <= 0) updateNumericInput(inputId = "N2", value = 1)
})
observeEvent(input$time, {
  if (input$time < 1) updateNumericInput(inputId = "time", value = 1)
})

# Retrieve user inputs
params <- reactive({c(r1 = input$r1,
                      r2 = input$r2,
                      a12 = input$a12,
                      a21 = input$a21,
                      d1 = input$d1,
                      d2 = input$d2,
                      b1 = input$b1,
                      b2 = input$b2)})
init <- reactive({c(N1 = input$N1, N2 = input$N2)})
time <- reactive({input$time})
vec <- reactive({"vec" %in% input$phase_opt})
traj <- reactive({"traj" %in% input$phase_opt})

# Run mutualism model
sim <- reactive({run_mutualism(time(), init(), params())})

# Plot population trajectories over time
plot <- reactive({
  if (input$plot == "time") {
    plot_mutualism_time(sim()) +
      theme(aspect.ratio = 1)
  } else if (input$plot == "phase") {
    plot_mutualism_portrait(sim(), vec(), traj()) +
      theme(aspect.ratio = 1)
  } else {
    wrap_plots(plot_mutualism_time(sim()),
                          plot_mutualism_portrait(sim(), vec(), traj()),
                          nrow = 1) +
      theme(aspect.ratio = 1)
  }
})

References


# Print footer
suppressWarnings(print_app_footer(language = "pt"))


gauravsk/ecoevoapps documentation built on July 9, 2024, 9:37 p.m.