Modifier au hasard la carte raster des types d'habitats?

12

J'ai un raster de types d'habitats pour une zone spécifique en Ecosse. Je dois créer de futurs scénarios d'habitat avec des changements d'habitat pour évaluer la viabilité de la population d'une espèce d'oiseau.

Par exemple, à l'avenir, il pourrait y avoir 10% de foresterie en plus dans la région. Je voudrais modifier la carte actuelle en ajoutant au hasard la forêt en blocs d'une certaine taille. Jusqu'à présent, je pense à la sélection de points aléatoires dans un raster qui identifie les zones où la foresterie pourrait se produire et à la croissance des blocs de taille correcte à l'aide d'une sorte d'automates cellulaires.

Cela semble-t-il être la meilleure façon de procéder? Existe-t-il une meilleure méthode?

Si c'est le meilleur moyen disponible, comment pourrais-je le faire dans, de préférence, R? (Je regarde actuellement la fonction rpoints dans "spatstat" avec le package CellularAutomata)

J'ai également accès à GRASS, QGis et ArcMap 10 s'il existe des moyens plus simples dans l'un d'eux.

Matt Geary
la source
Avez-vous déjà regardé le rasterpaquet? Il a beaucoup d'outils pour travailler avec des données raster (noo, rly?).
Roman Luštrik
Merci, Roman. Oui, cela devrait me donner les outils pour lire et manipuler ma carte de base.
Matt Geary

Réponses:

18

Avez-vous pensé à utiliser une chaîne Markov ? Il s'agit effectivement d'un "automate cellulaire probabiliste", fournissant ainsi le caractère aléatoire souhaité. Au lieu de prescrire la nouvelle génération en termes de voisins locaux de la génération existante, elle spécifie une distribution de probabilité pour la nouvelle génération. Cette distribution peut être estimée, disons, à partir de séquences temporelles d'images de zones identiques ou similaires.

Intuitivement, ce modèle dit qu'une cellule ne fera pas nécessairement une transition de boisée à non boisée (ou vice versa ), mais les chances qu'elle fera que la transition dépendra de la couverture terrestre immédiatement autour d'elle. Il peut gérer plusieurs classes de couvertures, des configurations complexes de quartiers et même être généralisé pour «se souvenir» de l'histoire récente de l'évolution de la couverture terrestre.

Les transitions peuvent être implémentées à l'aide d'instructions d'algèbre de carte, ce qui rend cette méthode praticable dans tout SIG basé sur raster, même ceux sans accès direct ou rapide aux données au niveau de la cellule. L'utilisation de R le rend encore plus facile.

Par exemple, considérez cette configuration de départ avec seulement deux classes, blanc et noir:

Grille de couverture terrestre

Pour illustrer ce qui peut arriver, j'ai créé un modèle paramétré (non basé sur des données) dans lequel la transition vers le noir se produit avec la probabilité 1 - q ^ k où k est le nombre moyen de cellules noires dans le voisinage 3 x 3 (k = 0, 1/9, 2/9, ..., 1). Lorsque q est petit ou que la majeure partie du quartier est déjà noire, la nouvelle cellule sera noire. Voici quatre simulations indépendantes de la dixième génération pour cinq valeurs de q allant de 0,25 à 0,05:

Tableau des résultats

Évidemment, ce modèle présente de nombreuses caractéristiques d'une AC, mais il inclut également un effet aléatoire utile pour explorer d'autres résultats.


Code

Ce qui suit implémente la simulation dans R.

#
# Make a transition from state `x` using a kernel having `k.ft` as
# its Fourier transform.
#
transition <- function(x, k.ft, q=0.1) {
  k <- zapsmall(Re(fft(k.ft * fft(x), inverse=TRUE))) / length(x)
  matrix(runif(length(k)) > q^k, nrow=nrow(k))
}
#
# Create the zeroth generation and the fft of a transition kernel.
#
n.row <- 2^7 # FFT is best with powers of 2
n.col <- 2^7
kernel <- matrix(0, nrow=n.row, ncol=n.col)
kernel[1:3, 1:3] <- 1/9
kernel.f <- fft(kernel)

set.seed(17)
x <- matrix(sample(c(0,1), n.row*n.col, replace=TRUE, prob=c(599, 1)), n.row)
#
# Prepare to run multiple simulations.
#
y.list <- list()
parameters <- c(.25, .2, .15, .1, .05)
#
# Perform and benchmark the simulations.
#
i <- 0
system.time({
  for (q in parameters) {
    y <- x
    for (generation in 1:10) {
      y <- transition(y, kernel.f, q)
    }
    y.list[[i <- i+1]] <- y
  }
})
#
# Display the results.
#    
par(mfrow=c(1,length(parameters)))
invisible(sapply(1:length(parameters), 
       function(i) image(y.list[[i]], 
                         col=c("White", "Black"),
                         main=parameters[i])))
whuber
la source
+1 Très intéressant. Si vous disposiez de données historiques sur la couverture terrestre pour une zone particulière, serait-il possible de dériver q et / ou k?
Kirk Kuykendall
2
@Kirk Oui, mais je ne le recommanderais pas: le modèle que j'ai utilisé pour l'illustration est trop simpliste. Mais vous pouvez tirer quelque chose de mieux: en regardant les fréquences empiriques des transitions hors de chaque configuration de quartier qui s'est produite, vous pouvez créer des modèles d'évolution future dont les transitions émulent statistiquement l'évolution passée. Si les fréquences de transition sont spatialement homogènes et si l'avenir continue d'agir comme le passé, l'exécution de quelques-unes de ces simulations peut donner une image claire de ce que l'avenir est susceptible de contenir.
whuber
Merci, cela semble faire exactement ce dont j'ai besoin. Serait-il possible de fixer une limite à la proportion de la zone qui change?
Matt Geary
@Matt Oui, au moins dans un sens probabiliste. La théorie décrit comment les chaînes de Markov atteignent un mélange asymptotiquement stable de proportions de chaque état. Il s'agit d'un équilibre dynamique: à chaque génération, beaucoup de cellules peuvent changer, mais le résultat net est de garder leurs proportions au sein de la grille les mêmes (jusqu'à de petites déviations fortuites).
whuber
1
Je suis un terrible programmeur R. Je peux partager le code Mathematica que j'ai utilisé; avec les fonctions d'application de R, il devrait bien porter. Vous avez besoin d'un noyau, d'une règle de transition et d'une procédure pour les appliquer à un tableau 2D 0/1. Ainsi: kernel = ConstantArray[1/3^2, {3,3}]pour le noyau; transitionRule [k_] := With[{q = 0.1}, Boole[RandomReal[{0, 1}] > q^k]]pour la règle; et next[a_, kernel_, f_] := Map[f, ListConvolve[kernel, a, {1, 1}, 0], {2}]de les appliquer à un tableau a . Par exemple, pour tracer quatre générations depuis le début , utilisez ArrayPlot /@ NestList[next[#, kernel, transitionRule] &, start, 3].
whuber