Bat White Nose Syndrome

No preview image

1 collaborator

Default-person Frederick Peck (Author)

Tags

(This model has yet to be categorized with any tags)
Visible to everyone | Changeable by the author
Model was written in NetLogo 6.4.0 • Viewed 3 times • Downloaded 0 times • Run 0 times
Download the 'Bat White Nose Syndrome' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

globals
[
  ;; bat variables
  how-many-bats-to-start
  percent-infected-to-start
  average-lifespan
  average-infection-to-death-time
  average-recovery-time
  average-fungal-threshold
  susceptible-bat-color
  infected-bat-color
  dead-bat-color
  immune-bat-color
  how-many-bats
  flash-time
  adult-size
  baby-size
  adult-age
  birth-probability
  adult-death-probability
  baby-death-probability

  ;; seasonal variables
  cycle-length
  transition-length
  spring-start
  summer-start
  autumn-start
  winter-start
  tmod
  season
  winter-color
  summer-color
  season-color-scale

  ;; cave variables
  cave-size
  cave-color
  contaminated-color
  fungal-patch-size
]


turtles-own
[
  infected?
  cured?
  immune?
  susceptible?
  contagious?
  dead?
  recovery-time
  infection-to-death-time
  fungal-threshold
  has-been-infected?
  infection-length
  recovery-length
  lifespan
  age
  sex
  fungal-load
  flashing?
  flash-length
  adult?
  given-birth-this-year?
]


patches-own
[
  contaminated?
  cave?
  border?
  cave-border?
]


;;;
;;; SETUP PROCEDURES
;;;

to setup
  clear-all
  set cycle-length 365
  set summer-color 93
  set winter-color black
  set season-color-scale [12 17 25 27]

  set contaminated-color red + 4

  set transition-length cycle-length / 10
  set spring-start 0
  set summer-start spring-start + transition-length
  set autumn-start summer-start + 4 * transition-length
  set winter-start autumn-start + transition-length

  set season "winter"

  set cave-size 65
  set cave-color 122
  set fungal-patch-size 20

  set how-many-bats-to-start 30
  set percent-infected-to-start 0
  set average-infection-to-death-time (1 * transition-length)
  set average-recovery-time (3 * transition-length)
  set average-lifespan (15 * cycle-length)
  set average-fungal-threshold 15

  set susceptible-bat-color white
  set immune-bat-color magenta
  set infected-bat-color red
  set dead-bat-color gray

  set adult-size 5
  set baby-size 2
  set adult-age cycle-length

  set birth-probability 0.005
  set adult-death-probability 0.0008
  set baby-death-probability 0.001

  set flash-time 20

  setup-bats
  setup-patches

  reset-ticks
end 

to setup-bats
  let number-immune 0
  let number-infected ((how-many-bats-to-start - number-immune) * (percent-infected-to-start / 100))
  let number-susceptible (how-many-bats-to-start - number-immune - number-infected)

  ;; Create the immune, infected, and succeptible bats
  create-turtles number-immune
  [
    create-default-bat
      adult-age + 1
      max-pxcor - random-float cave-size
      max-pycor - random-float cave-size
      false

    set susceptible? false
    set immune? true

    assign-bat-visible-traits
  ]


  create-turtles number-infected
  [
    create-default-bat
      adult-age + 1
      max-pxcor - random-float cave-size
      max-pycor - random-float cave-size
      false

    set infected? true
    set contagious? true
    set has-been-infected? true

    assign-bat-visible-traits
  ]

  create-turtles number-susceptible
  [
    create-default-bat
      adult-age + 1
      max-pxcor - random-float cave-size
      max-pycor - random-float cave-size
      false

    set susceptible? true

    assign-bat-visible-traits
  ]
end 

to assign-bat-visible-traits
  ifelse adult?
    [ set size adult-size ]
    [ set size baby-size ]

  (ifelse
    flashing? [
      ifelse flash-length <= flash-time [
        set size adult-size + 2
        let alternate-color susceptible-bat-color
        if immune-after-recovery?
          [ set alternate-color immune-bat-color]
        set color ifelse-value (color = infected-bat-color) [alternate-color] [infected-bat-color]
        set flash-length flash-length + 1
      ]
      [
        set size adult-size
        set flashing? false
        set flash-length 0
      ]
    ]
    dead? [
      set color dead-bat-color
    ]
    infected? [
      set color infected-bat-color
    ]
    susceptible? [
      set color susceptible-bat-color
    ]
    [  ; immune
      set color immune-bat-color
    ])

  ; set label age
end 

to create-default-bat [bat-age start-x start-y inherit-disease-traits?]
  set how-many-bats how-many-bats + 1

  setxy start-x start-y

  ;; these traits are inherited, only set them if this bat is not inheriting them
  if inherit-disease-traits? = false [
    set infected? false
    set susceptible? false
    set contagious? false
    set immune? false
  ]

  set cured? false
  set has-been-infected? false
  set dead? false
  set flashing? false
  set given-birth-this-year? false
  set adult? false

  set fungal-load 0

  set sex one-of ["male" "female"]

  set age bat-age
  if age > adult-age
    [ set adult? true ]

  ;; Set the lifespan to fall on a normal distribution around average lifespan
  set lifespan random-normal average-lifespan (average-lifespan / 4)

  (ifelse lifespan > (average-lifespan * 2)
    [ set lifespan (average-lifespan * 2) ]
  lifespan < 0
    [ set lifespan (average-lifespan / 2) ]
  )


  ;; Set the recovery time to fall on a normal distribution around the mean
  set recovery-time random-normal average-recovery-time (average-recovery-time / 4)

  (ifelse recovery-time > (average-recovery-time * 2)
    [ set recovery-time (average-recovery-time * 2) ]
  recovery-time < 0
    [ set recovery-time (average-recovery-time / 2) ]
  )


  ;; Set the infection-to-death time to fall on a normal distribution around the mean
  set infection-to-death-time random-normal average-infection-to-death-time (average-infection-to-death-time / 4)

  (ifelse infection-to-death-time > (average-infection-to-death-time * 2)
    [ set infection-to-death-time (average-infection-to-death-time * 2) ]
  infection-to-death-time < 0
    [ set infection-to-death-time (average-infection-to-death-time / 2) ]
  )


  ;; Set the threshold for infection to fall on a normal distribution around the mean
  set fungal-threshold floor (random-normal average-fungal-threshold (average-fungal-threshold / 4))

  (ifelse fungal-threshold > (average-fungal-threshold * 2)
    [ set fungal-threshold (average-fungal-threshold * 2) ]
  fungal-threshold < 0
    [ set fungal-threshold floor (average-fungal-threshold / 2) ]
  )
end 

to setup-patches

  ;; Set defaults
  ask patches [
    set cave? false
    set border? false
    set cave-border? false
    set contaminated? false
  ]

  ;; Set the border of the world
  ask patches with [
    pxcor = max-pxcor or
    pxcor = min-pxcor or
    pycor = max-pycor or
    pycor = min-pycor
  ]
  [
    set border? true
  ]

  ;; Set the cave
  ask patches with [
    pxcor >= (max-pxcor - cave-size) and
    pycor >= (max-pycor - cave-size)
  ] [
    set cave? true
    set pcolor cave-color
  ]

  ;; Draw a border around the cave
  ask patches with [
    pxcor = (max-pxcor - cave-size - 1) and
    pycor >= (max-pycor - cave-size - 1)
  ] [
    set cave-border? true
    set pcolor white
  ]
  ask patches with [
    pxcor >= (max-pxcor - cave-size - 1) and
    pycor = (max-pycor - cave-size - 1)
  ] [
    set cave-border? true
    set pcolor white
  ]

  ;; Set the contaminated patches - make sure one is near the center; the others can be completely random
  let cx mean [pxcor] of patches with [cave?]
  let cy mean [pycor] of patches with [cave?]
  let radius 15

  let random-near-cave-center one-of patches with [
    distancexy cx cy <= radius
  ]
  create-contaminated-area random-near-cave-center

  repeat fungal-patches - 1 [
    let candidate nobody
    while [candidate = nobody] [
      let try-one one-of patches with [cave? and not contaminated?]
      let nearby nobody
      ask try-one
      [ set nearby patches in-radius (fungal-patch-size / 3 )
      ]
      if not any? nearby with [contaminated?] [
        set candidate try-one
      ]
    ]
    create-contaminated-area candidate
  ]



  ;repeat fungal-patches - 1 [
  ;  let random-cave one-of patches with [cave? = true ]
  ;  create-contaminated-area random-cave
  ;]

  ask patches with [ not cave? ]
  [
    set contaminated? false
  ]

  ask patches with [ contaminated? = true ]
  [
    set pcolor red + 4
  ]


  ask patch 0 (max-pycor - 3) [
    set plabel season
  ]
end 

to create-contaminated-area [center-patch]
  let open-patches (list center-patch)
  let contaminated-patches []

  ;; grow until we reach the desired size
  while [length contaminated-patches < fungal-patch-size and not empty? open-patches] [
    let current one-of open-patches
    set open-patches remove current open-patches
    if not member? current contaminated-patches [
      set contaminated-patches lput current contaminated-patches
      ask current [
        set contaminated? true
      ]

      ;; add neighbors with some randomness
      ask current [
        ask neighbors4 with [not member? self contaminated-patches and random-float 1.0 < 0.8] [
          set open-patches lput self open-patches
        ]
      ]
    ]
  ]
end 


;;;
;;; GO PROCEDURES
;;;

to go
  set tmod ticks mod cycle-length

  set-season

  if all? turtles [ dead? ] [
end -sim
    stop
  ]

  ; if all? patches [ not contaminated? ]
  ;  [ stop ]

  ask patches
    [ color-patches ]

  ask turtles with [ not dead? ] [
    if infected? [
      set infection-length infection-length + 1
      if [cave? = false] of patch-here
       [ set recovery-length recovery-length + 1 ]
      maybe-recover
    ]

    if contagious?
      [ direct-infect ]

    if not immune?
      [ indirect-infect ]

   if allow-birth? [
     if (sex = "female") and (given-birth-this-year? = false) and ([cave? = false] of patch-here)
       [ maybe-give-birth ]
    ]

    move
    age-one-day
    maybe-die
    assign-bat-visible-traits
  ]

  grow-or-shrink-fungus

  tick
end 

to set-season
  (ifelse
    tmod > winter-start [
      set season "winter"
      ask turtles [ set given-birth-this-year? false ]
    ]
    (tmod > autumn-start) and (tmod <= winter-start) [
      set season "autumn"
    ]
    (tmod > summer-start) and (tmod <= autumn-start) [
      set season "summer"
    ]
    tmod <= summer-start [
      set season "spring"
    ]
  )
end 

to move
  (ifelse
    season = "spring" [
      (ifelse
        [cave? or cave-border?] of patch-here
        [
          set heading away-from-cave
        ]
        [border? = true] of patch-here
        [
          set heading away-from-border
        ]
        [
          rt 10 - random-float 20
        ]
      )
      fd floor (tmod / 10)
    ]
    season = "summer" [
      (ifelse
        [cave? or cave-border?] of patch-here
        [
          set heading away-from-cave
        ]
        [border? = true] of patch-here
        [
          set heading away-from-border
        ]
        [
          rt 10 - random-float 20
        ]
      )
      fd 5
    ]
    season = "autumn" [
      set heading towards-cave
      ; fd 5
      fd floor ((transition-length - (tmod - autumn-start)) / 3)
    ]
    season = "winter" [
    if [cave? = false] of patch-here
      [
        set heading towards-cave
        fd 2
      ]
    ]
    )
end 

to-report towards-cave
  let target-x max-pxcor - random cave-size
  let target-y max-pycor - random cave-size

  let d-x target-x - xcor
  let d-y target-y - ycor

  ;; calculate absolute heading
  let absolute-heading atan d-x d-y

  report absolute-heading
end 

to-report away-from-cave
  let repel-x max-pxcor
  let repel-y max-pycor

  let d-x xcor - repel-x
  let d-y ycor - repel-y

  let escape-heading atan d-x d-y + random-float 30 - 15

  report escape-heading
end 

to-report away-from-border
  let away-heading heading + 100 - random-float 20

  report away-heading
end 

to age-one-day
  set age age + 1
  if age > adult-age
    [ set adult? true ]
end 


;; Direct infection can occur to any susceptible bat nearby an infected bat

to direct-infect
   let nearby-susceptible (other turtles in-radius 10) with [ susceptible? ]

   ask nearby-susceptible [
    let d distance myself
    let distance-factor 1

    let base-probability 100 - resistance-to-direct-infection
      ;; Inverse-square decay
      ; if d > 0
        ; [ set distance-factor 1 / (d ^ 2) ]

      ;; step-wise decay; better for cave?
      (ifelse
        d <= 2
          [ set distance-factor 1 ]
        d <= 5
          [ set distance-factor 0.5 ]
        d <= 10
          [ set distance-factor 0.1 ]
      )

    let final-probability base-probability * distance-factor

      if random-float 100 < final-probability [
        set fungal-load fungal-load + 1
        maybe-get-sick
      ]
    ]
end 


;; Indirect infection can occur to any susceptible bat on a contaminated patch

to indirect-infect
  if [contaminated?] of patch-here and random-float 100 > resistance-to-indirect-infection
  [
    set fungal-load fungal-load + 1
    maybe-get-sick
  ]
end 

to maybe-get-sick
  if fungal-load >= fungal-threshold [
    set infected? true
    set contagious? true
    set susceptible? false
    set has-been-infected? true
  ]
end 

to maybe-recover
  if ([cave? = false] of patch-here) and (recovery-length > recovery-time)
  [
    set infected? false
    set contagious? false
    set cured? true

    set fungal-load 0
    set recovery-length 0
    set infection-length 0

    set flashing? true
    set flash-length 0

    ifelse immune-after-recovery? [
      set susceptible? false
      set immune? true
    ]
    [
      set susceptible? true
    ]
  ]
end 

to maybe-die
  ;; die due to infection
  if tolerance = 0
    [ set tolerance 1 ]
  let season-survival-prob tolerance / 100
  let daily-survival-prob exp ( ln(season-survival-prob) / (4 * transition-length) )

  if (infection-length > infection-to-death-time) and (random-float 1.0 > daily-survival-prob) [
    set dead? true
    set contagious? false
    set how-many-bats how-many-bats - 1
  ]

  ;; Die of natural causes
  if (dead? = false) and (allow-natural-death? = true) [
    if ( age > lifespan ) ; die from old age
      or ( ( adult? and (random-float 1.0 < adult-death-probability) )
      or ( not adult? and (random-float 1.0 < baby-death-probability) ) ) ; die due to other factors
      [
        set dead? true
        set contagious? false
        set how-many-bats how-many-bats - 1
      ]
  ]
end 

to maybe-give-birth
   if random-float 1.0 < birth-probability [
     hatch 1 [
       create-default-bat 0 xcor ycor true
       set susceptible? true
     ]

    set given-birth-this-year? true
  ]
end 

to grow-or-shrink-fungus

  let growth-prob 0.00001
  let shrink-prob 0.00001

  ;; Growth is more likely if climate > 0, Shrinkage is more likely if climate < 0
  (ifelse
    climate > 0 [
      set growth-prob 0.001 * climate
      set shrink-prob 0.001 / (climate)
    ]
    climate < 0 [
      set growth-prob 0.001 / (abs climate)
      set shrink-prob 0.001 * (abs climate)
    ]
    climate = 0 [
      set growth-prob 0.001
      set shrink-prob 0.001
    ]
  )


  ; Grow fungus
  let new-growth patches with [contaminated?]
  ask new-growth [
    ask neighbors4 with [
      not contaminated? and cave? and random-float 1.0 < growth-prob
    ] [
      set contaminated? true
      set pcolor contaminated-color
    ]
  ]

  ; Shrink fungus
  ask patches with [contaminated? and random-float 1.0 < shrink-prob ] [
    set contaminated? false
    set pcolor cave-color
  ]
end 

to color-patches
  if not contaminated? and not (cave? or cave-border?)
  [
    (ifelse
      season = "winter" [
        set pcolor winter-color
      ]
      season = "autumn" [
        ;; summer -> winter transition
        let factor (tmod - (cycle-length / 2)) / transition-length
        let idx floor ((1 - factor) * (length season-color-scale - 1))
        set pcolor item idx season-color-scale
      ]
      season = "summer" [
        set pcolor summer-color
      ]
      season = "spring" [
        ;; winter -> summer transition
        let factor tmod / transition-length
        let idx floor (factor * (length season-color-scale - 1))
        set pcolor item idx season-color-scale
      ]
    )
  ]

  ask patch 0 (max-pycor - 3) [
    set plabel season
  ]
end 

to end-sim
  ask patches with [not contaminated? and not (cave? or cave-border?)] [
    set pcolor infected-bat-color
    ask patch 0 (max-pycor - 3) [
      set plabel "** all dead **"
    ]
  ]
end 

There is only one version of this model, created 3 days ago by Frederick Peck.

Attached files

No files

This model does not have any ancestors.

This model does not have any descendants.