Respostas:
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 pick
começa a indexação em 1, não em 0.
(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.
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?
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 = NoData
então primeiro defina estes valores reclassificados com NoData
0:
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 NoData
valores para que a peça possa ficar de fora.
Con(IsNull(ras1), 0, ras2)
NoData
? É apenas para garantir que eles não sejam escolhidos ao escolher aleatoriamente?
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 :)