Criando raster escolhendo aleatoriamente o valor da célula de várias rasters sobrepostas?

10

Estou usando o ArcGIS Desktop 10 com sua extensão Spatial Analyst.

Como combinar vários rasters em um, sempre escolhendo aleatoriamente os valores das células sobrepostas?

Eu tenho uma imagem que pode explicar isso melhor:

exemplo

Sam
fonte

Respostas:

7

Pick foi criado para problemas como este. Pense nisso como a versão "switch" (ou "case") de "con", que é a implementação da álgebra de mapa de "if ... else".

Se houver três rasters sobrepostos, por exemplo, a sintaxe (Python) seria semelhante a

inPositionRaster = 1 + int(3 * CreateRandomRaster())
Pick(inPositionRaster, [inRas01, inRas02, inRas03])

Observe que pickcomeça a indexação em 1, não em 0.


Editar

(veja o tópico do comentário)

Para lidar com os valores NoData, primeiro você precisa desativar o tratamento NoData do ArcGIS. Faça isso criando grades que tenham um valor especial (mas válido) no lugar de NoData, como 99999 (ou qualquer outra coisa: mas certifique-se de escolher um valor maior que qualquer número válido que possa aparecer: isso será útil mais tarde) . Isso requer o uso da solicitação IsNull, como em

p01 = Con(IsNull(inRas01), 99999, inRas01)
p02 = Con(IsNull(inRas02), 99999, inRas01)
p03 = Con(IsNull(inRas03), 99999, inRas01)

Por exemplo, considere o caso dessas grades de uma linha (NoData é mostrado como "*"):

inRas01:  1  2 19  4  *  *  *  *
inRas02:  9  2  *  * 13 14  *  *
inRas03: 17  *  3  * 21  * 23  *

O resultado é colocar um 99999 no lugar de cada "*".

Em seguida, imagine todas essas rasters como matrizes planas de blocos de madeira com NoData correspondente a blocos ausentes (furos). Quando você empilhar verticalmente esses rasters, os blocos cairão nos buracos abaixo deles. Precisamos desse comportamento para evitar escolher valores NoData: não queremos lacunas verticais nas pilhas de blocos. A ordem dos blocos em cada torre realmente não importa. Para este fim, podemos obter cada torre, classificando os dados :

q01 = Rank(1, [p01, p02, p03])
q02 = Rank(2, [p01, p02, p03])
q03 = Rank(3, [p01, p02, p03])

No exemplo, obtemos

q01:      1     2     3     4    13    14    23 99999
q02:      9     2    19 99999    21 99999 99999 99999
q03:     17 99999 99999 99999 99999 99999 99999 99999

Observe que as classificações são do menor para o maior, de modo que q01 contém os valores mais baixos em cada local, q02 contém o segundo mais baixo etc. Os códigos NoData não começam a aparecer até que todos os números válidos sejam coletados, porque esses códigos são maiores que quaisquer números válidos.

Para evitar escolher esses códigos NoData durante a seleção aleatória, você precisa saber quantos blocos estão empilhados em cada local: isso nos diz quantos valores válidos ocorrem. Uma maneira de lidar com isso é contar o número de códigos NoData e subtraí-lo do número total de grades de seleção:

n0 = 3 - EqualToFrequency(99999, [q01, q02, q03])

Isso gera

n0:       3 2 2 1 2 1 1 0

Para lidar com os casos em que n = 0 (para que não haja nada disponível para seleção), defina-os como NoData:

n = SetNull(n0 == 0, n0)

Agora

n:        3 2 2 1 2 1 1 *

Isso também garantirá que seus códigos NoData (temporários) desapareçam no cálculo final. Gere valores aleatórios entre 1 e n:

inPositionRaster = 1 + int(n * CreateRandomRaster())

Por exemplo, essa varredura pode parecer

inPositionRaster: 3 2 1 1 2 1 1 *

Todos os seus valores estão entre 1 e o valor correspondente em [n].

Selecione os valores exatamente como antes:

selection = Pick(inPositionRaster, [q01, q02, q03])

Isso resultaria em

selection:       17  2  3  4 21 14 23  *

Para verificar se está tudo bem, tente selecionar todas as células de saída que possuem o código NoData (99999 neste exemplo): não deve haver nenhuma.

Embora este exemplo em execução use apenas três grades para seleção, eu o escrevi de uma maneira que generaliza facilmente para qualquer número de grades. Com muitas grades, escrever um script (para repetir as operações repetidas) será inestimável.

whuber
fonte
Você sabe como eu poderia ignorar os valores NoData dos cálculos (com Raster Calculator e Python)?
Sam
Sam, "Ignore" como, exatamente? Eu acredito que o comportamento padrão é produzir NoData onde quer que um ou mais rasters de entrada estejam NoData (mas não tenho certeza disso no caso de pick: se inPositionRaster e o raster selecionado tiverem valores válidos em uma célula, o resultado será plausível para essa célula deve ser o valor da varredura selecionada, independentemente do que qualquer outra rasters possa conter). Em que comportamento alternativo você está pensando?
whuber
Eu preciso que ele selecione apenas os valores numéricos inteiros. Digamos que eu tenho três rasters. Para uma célula, seus valores são os seguintes: 4,5, NoData. Quero que o outroter tenha 4 ou 5 nessa célula, mas nunca o NoData.
Sam
Estou tendo problemas para fazer esse 1 + Int (n * CreateRandomRaster ()) funcionar.
24412 Sam
"Problema" em que sentido? Por favor, seja específico!
whuber
4

Usando python e ArcGIS 10 e usando a função con que possui a seguinte sintaxe:

Con (in_conditional_raster, in_true_raster_or_constant, {in_false_raster_or_constant}, {where_clause})

A idéia aqui é ver se o valor na varredura aleatória é menor que 0,5, se for escolher raster1, caso contrário, escolha raster2. NoData+ data = NoDataentão primeiro defina estes valores reclassificados com NoData0:

import arcpy
from arcpy import env
from arcpy.sa import *
env.workspace = "C:/sapyexamples/data"

ras1_NoNull = Con(IsNull("elevation1"),0, "elevation1")  # remove NoData
ras2_NoNull = Con(IsNull("elevation2"),0, "elevation2")  # remove NoData
randRaster = CreateRandomRaster(100, 2, Extent(0, 0, 150, 150)) # raster generated between 0 and 1; 100 is seed value

outCon = Con(randRaster < 0.5, ras1_NoNull,  ras2_NoNull)  

outCon.save("C:/outcon.img")   # save raster

EDIT: Acabei de perceber que você não está adicionando os NoDatavalores para que a peça possa ficar de fora.

djq
fonte
Ainda estou trabalhando nas minhas habilidades em Python. Existe uma maneira de inserir isso na Calculadora Raster que também excluiria os valores NoData do processo? Eu tenho 10 rasters e alguns têm NoData onde outros têm valores.
Sam
Eu acho que você pode criar condições usando algo parecido com isso na calculadora rasterCon(IsNull(ras1), 0, ras2)
DJQ
Infelizmente, isso realmente não exclui os valores NoData: apenas os substitui por zeros. Em alguns casos, isso pode ser apropriado, mas provavelmente não aqui!
whuber
hmm, bom ponto @whuber. Então, o que significa excluir NoData? É apenas para garantir que eles não sejam escolhidos ao escolher aleatoriamente?
DJQ
É assim que eu interpretei (veja minha resposta editada neste tópico), mas continua sendo uma boa pergunta. Ignorar os valores de ND dessa maneira faz com que as grades restantes sejam selecionadas com maior probabilidade, o que pode ser um efeito colateral indesejável. Tudo depende da finalidade do cálculo.
whuber
1

Eu apenas criaria uma varredura aleatória ( ajuda ) da mesma extensão e tamanho de célula. Em seguida, usando CON ( ajuda ), defina-o para selecionar o valor da 1ª varredura se a célula da varredura aleatória tiver um valor <128 (se uma varredura aleatória for 0 - 255), caso contrário, escolha um valor da 2ª varredura.

Espero que faça sentido :)

jareks
fonte
Você sabe como selecionar apenas os rasters com valores? Por exemplo, na minha figura, existem quatro 2 e dois 3 que se sobrepõem ao NoData. Eu quero ter certeza de que ele seleciona apenas aqueles rasters com valores em uma célula e não o NoData.
Sam
Desculpe por não responder. Você ainda está com problemas com o NoData?
jareks