#using Pkg
#Pkg.activate(joinpath(ENV["HOME"], ".julia", "dev", "ConScape"))
using ConScape
using SparseArrays
using Statistics
using Plots
Dispersal mortality
Demonstration of independent likelihood and cost of movement
In this notebook, we demonstrate the possibility to use independent movement probablities and costs, similar to (Fletcher Jr et al. 2019) and (Marx et al. 2020).
Preamble
See notebook Getting Started for a ‘basic workflow’ to learn about the fundamentals on data import and the creation of a ConScape Grid
:
= joinpath(ENV["HOME"], "Downloads", "input_maps")
datadir = joinpath(ENV["TMPDIR"], "figures")
outdir if !isdir(outdir)
mkdir(outdir)
end
"C:/Users/bram.van.moorter/Documents/ConScape_website/site/notebooks/data/"
We use the data provided in (Marx et al. 2020):
= ConScape.readasc(joinpath(datadir,
mov_prob, meta_p "prob_panther_cropped.asc"))
= ConScape.readasc(joinpath(datadir,
hab_qual, meta_q "prob_panther_cropped.asc"))
([0.111111111938953 0.5 … 0.111111111938953 0.16666667163372; 0.125 0.125 … 0.111111111938953 0.16666667163372; … ; NaN NaN … 1.0 0.111111111938953; NaN NaN … 1.0 0.333333343267441], Dict{Any, Any}("cellsize" => 500.0, "nrows" => 99, "nodata_value" => -999, "ncols" => 174, "xllcorner" => 615138.0, "yllcorner" => 257108.0))
Note, we did not have quality data for each pixel, for this demonstration we simply assumed that the permeability adequately represents quality (see Notebook Getting Started for a better example with independent quality data).
We remove negative values:
= max.(0, mov_prob)
mov_prob = max.(0, hab_qual); hab_qual
Cost data
In addition to the data on the habitat quality and the likelihood of movement, we also have independent data on the cost of movement ((Marx et al. 2020)):
= ConScape.readasc(joinpath(datadir,
mov_cost, meta_c "mort_panther_cropped.asc"))
= max.(0, mov_cost); mov_cost
As discussed in vanmoorter2021defining, to use the mortality risk as a cost in the RSP framework, we need to define the cost as the negative logarithm of the survival probability between adjacent pixels:
= -log.(1 .- mov_cost); mov_cost
We create the Grid
by using these cost data, instead of a transformation from the likelihood of movement:
= ConScape.Grid(size(mov_prob)...,
g =ConScape.graph_matrix_from_raster(mov_prob),
affinities=hab_qual,
qualities=ConScape.graph_matrix_from_raster(mov_cost)); costs
┌ Info: cost graph contains 15 strongly connected subgraphs
└ @ ConScape C:\Users\bram.van.moorter\.julia\packages\ConScape\spkWs\src\grid.jl:215
┌ Info: removing 14 nodes from affinity and cost graphs
└ @ ConScape C:\Users\bram.van.moorter\.julia\packages\ConScape\spkWs\src\grid.jl:225
To visualize the movement costs, we define the following function, similar to the plot_indegrees
function we used earlier (see Notebook Getting Started):
function plot_incost(g; kwargs...)
= sum(g.costmatrix, dims=1)
values = zeros(g.nrows, g.ncols)
canvas for (i,v) in enumerate(values)
= v
canvas[g.id_to_grid_coordinate_list[i]] end
heatmap(canvas, yflip=true, axis=nothing, border=:none; kwargs...)
end
plot_incost (generic function with 1 method)
plot_incost(g, title="Mortality risk")
Computing the survival probability
Now we can compute the GridRSP
:
= ConScape.GridRSP(g, θ=1.0); h
Note that to compute the survival probability from \(s\) to \(t\) corresponding to the mortality cost associated to edges \((i,j)\), we need to set \(\theta=1.0\) ((Moorter et al. 2021)).
The survival probability from all source pixels to a target pixel (e.g. 15000) is:
= zeros(17212)
tmp 15000] = 1
tmp[
display(ConScape.plot_values(g, tmp, title="Target"))
= ConScape.survival_probability(h);
surv display(ConScape.plot_values(g, map(t -> t==1 ? NaN : t, surv[:,15000]), title="Survival probability"))
Survival probability to a target.
Finally, we can use these survival probabilities to compute for each pixel the amount of habitat it is functionally connected to:
= ConScape.connected_habitat(h,
func =ConScape.survival_probability);
connectivity_functionheatmap(Array(func), yflip=true, title="Functional habitat") ConScape.
Summary
The ConScape library allows users to define the cost of movement between adjacent pixels both as a transformation from the likelihood of movement, but also from independent cost data. This application is very useful to model dispersal with mortality ((Fletcher Jr et al. 2019)), but could also be applied in combination with ‘energy landscapes’ discussed in: (Moorter et al. 2021).