Modifica casuale della mappa raster dei tipi di habitat?


12

Ho un raster di tipi di habitat per un'area specifica in Scozia. Devo creare scenari di habitat futuri con cambiamenti nell'habitat per valutare la vitalità della popolazione di una specie di uccelli.

Ad esempio, in futuro potrebbe esserci un 10% di foreste in più nell'area. Vorrei modificare la mappa attuale aggiungendo casualmente la silvicoltura in blocchi di una certa dimensione. Finora sto pensando di selezionare punti casuali da un raster che identifica le aree in cui potrebbe verificarsi la silvicoltura e fa crescere i blocchi di dimensioni corrette usando una sorta di automi cellulari.

Sembra questo il modo migliore per farlo? C'è un metodo migliore?

Se questo è il modo migliore disponibile, come potrei farlo in, preferibilmente, R? (Attualmente sto esaminando la funzione di punti in "spatstat" insieme al pacchetto CellularAutomata)

Ho anche accesso a GRASS, QGis e ArcMap 10 se ci sono modi più semplici in ognuno di essi.


Hai già guardato il rasterpacchetto? Ha molti strumenti per lavorare con dati raster (noo, rly?).
Roman Luštrik,

Grazie romano. Sì, questo dovrebbe darmi gli strumenti per leggere e manipolare la mia mappa di base.
Matt Geary,

Risposte:


18

Hai pensato di usare una catena Markov ? Questo è effettivamente un "automa cellulare probabilistico", fornendo così la casualità desiderata. Invece di prescrivere la nuova generazione in termini di vicini locali della generazione esistente, specifica una distribuzione di probabilità per la nuova generazione. Tale distribuzione può essere stimata, ad esempio, da sequenze temporali di immagini della stessa area o simili.

Intuitivamente, questo modello afferma che una cellula non effettuerà necessariamente una transizione da forestale a non forestale (o viceversa ), ma le possibilità che questa transizione dipenda dalla copertura del terreno immediatamente circostante. Può gestire più classi di copertura, configurazioni complesse di quartieri e persino essere generalizzato per "ricordare" la storia recente dell'evoluzione della copertura del suolo.

Le transizioni possono essere implementate usando le istruzioni Map Algebra, il che rende questo metodo praticabile in qualsiasi GIS basato su raster, anche quelli senza accesso diretto o rapido ai dati a livello di cella. L'uso di R rende ancora più semplice.

Ad esempio, considera questa configurazione iniziale con solo due classi, bianco e nero:

Griglia di copertura del suolo

Per illustrare cosa può accadere, ho creato un modello con parametri (non basato su alcun dato) in cui la transizione al nero avviene con probabilità 1 - q ^ k dove k è il numero medio di cellule nere all'interno del vicinato 3 per 3 (k = 0, 1/9, 2/9, ..., 1). Quando q è piccolo o la maggior parte del quartiere è già nero, la nuova cella sarà nera. Ecco quattro simulazioni indipendenti della decima generazione per cinque valori di q che vanno da 0,25 a 0,05:

Tabella dei risultati

Evidentemente questo modello ha molte delle caratteristiche di una CA ma include anche un effetto casuale utile per esplorare risultati alternativi.


Codice

Di seguito implementa la simulazione in 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])))

+1 Molto interessante. Se avessi dati storici sul landcover per una particolare area, sarebbe possibile derivare q e / o k?
Kirk Kuykendall,

2
@Kirk Sì, ma non lo consiglierei: il modello che ho usato per l'illustrazione è troppo semplicistico. Ma puoi ricavare qualcosa di meglio: osservando le frequenze empiriche delle transizioni fuori da ogni configurazione di vicinato che si è verificata, puoi creare modelli di evoluzione futura le cui transizioni emulano statisticamente l'evoluzione passata. Se le frequenze di transizione sono spazialmente omogenee e se il futuro continua ad agire come il passato, l'esecuzione di alcune di queste simulazioni può dare un quadro chiaro di ciò che il futuro è destinato a contenere.
whuber

Grazie, questo sembra fare esattamente ciò di cui ho bisogno. Sarebbe possibile fissare un limite alla proporzione dell'area che cambia?
Matt Geary,

@Matt Sì, almeno in senso probabilistico. La teoria descrive come le catene di Markov raggiungano una miscela asintoticamente stabile di proporzioni di ciascuno stato. Questo è un equilibrio dinamico: ad ogni generazione molte celle possono cambiare, ma il risultato netto è di mantenere le loro proporzioni all'interno della griglia uguali (fino a piccole deviazioni di probabilità).
whuber

1
Sono un programmatore R terribile. Posso condividere il codice Mathematica che ho usato; con le funzioni di applicazione di R, dovrebbe portarlo bene. È necessario un kernel, una regola di transizione e una procedura per applicarli a un array 2D 0/1. Quindi: kernel = ConstantArray[1/3^2, {3,3}]per il kernel; transitionRule [k_] := With[{q = 0.1}, Boole[RandomReal[{0, 1}] > q^k]]per la regola; e next[a_, kernel_, f_] := Map[f, ListConvolve[kernel, a, {1, 1}, 0], {2}]applicarli a un array a . Ad esempio, per tracciare quattro generazioni dall'inizio , utilizzare ArrayPlot /@ NestList[next[#, kernel, transitionRule] &, start, 3].
whuber
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.