Créer un raster en choisissant aléatoirement la valeur d'une cellule parmi plusieurs rasters qui se chevauchent?

10

J'utilise ArcGIS Desktop 10 avec son extension Spatial Analyst.

Comment combiner plusieurs rasters en un seul, en choisissant toujours au hasard parmi les valeurs des cellules qui se chevauchent?

J'ai une image qui peut mieux expliquer cela:

exemple

Sam
la source

Réponses:

7

Pick a été créé pour des problèmes comme celui-ci. Considérez-le comme la version "switch" (ou "case") de "con", qui est l'implémentation d'algèbre de carte de "if ... else".

S'il y a 3 rasters qui se chevauchent, par exemple, la syntaxe (Python) ressemblerait à

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

Notez que l' pickindexation commence à 1, pas à 0.


Éditer

(voir le fil des commentaires)

Pour gérer les valeurs NoData, vous devez d'abord désactiver la gestion NoData d'ArcGIS. Pour ce faire, créez des grilles qui ont une valeur spéciale (mais valide) à la place de NoData, comme 99999 (ou autre chose: mais assurez-vous de choisir une valeur plus grande que tout nombre valide pouvant apparaître: cela sera pratique plus tard) . Cela nécessite l' utilisation de la demande IsNull, comme dans

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

Par exemple, considérons le cas de ces grilles à une ligne (NoData est représenté par "*"):

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

Le résultat est de mettre un 99999 à la place de chaque "*".

Ensuite, imaginez tous ces rasters comme des tableaux plats de blocs de bois avec NoData correspondant aux blocs manquants (trous). Lorsque vous empilez verticalement ces rasters, les blocs tomberont dans les trous situés en dessous. Nous avons besoin de ce comportement pour éviter de choisir des valeurs NoData: nous ne voulons pas de lacunes verticales dans les piles de blocs. L'ordre des blocs dans chaque tour n'a pas vraiment d'importance. À cette fin, nous pouvons obtenir chaque tour en classant les données :

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

Dans l'exemple, on obtient

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

Notez que les rangs sont du plus bas au plus élevé, de sorte que q01 contient les valeurs les plus basses à chaque emplacement, q02 contient le deuxième plus bas, etc. Les codes NoData ne commencent pas à apparaître jusqu'à ce que tous les nombres valides soient collectés, car ces codes sont plus grands que tous les nombres valides.

Afin d'éviter de choisir ces codes NoData lors de la sélection aléatoire, vous devez savoir combien de blocs sont empilés à chaque emplacement: cela nous indique combien de valeurs valides se produisent. Une façon de gérer cela est de compter le nombre de codes NoData et de le soustraire du nombre total de grilles de sélection:

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

Cela donne

n0:       3 2 2 1 2 1 1 0

Pour gérer les cas où n = 0 (il n'y a donc rien de disponible à sélectionner), définissez-les sur NoData:

n = SetNull(n0 == 0, n0)

Maintenant

n:        3 2 2 1 2 1 1 *

Cela garantira également que vos codes NoData (temporaires) disparaissent dans le calcul final. Générez des valeurs aléatoires entre 1 et n:

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

Par exemple, ce raster pourrait ressembler à

inPositionRaster: 3 2 1 1 2 1 1 *

Toutes ses valeurs sont comprises entre 1 et la valeur correspondante dans [n].

Sélectionnez les valeurs exactement comme avant:

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

Il en résulterait

selection:       17  2  3  4 21 14 23  *

Pour vérifier que tout va bien, essayez de sélectionner toutes les cellules de sortie qui ont le code NoData (99999 dans cet exemple): il ne devrait pas y en avoir.

Bien que cet exemple en cours d'exécution n'utilise que trois grilles pour sélectionner, je l'ai écrit d'une manière qui se généralise facilement à n'importe quel nombre de grilles. Avec beaucoup de grilles, l'écriture d'un script (pour parcourir les opérations répétées) sera inestimable.

whuber
la source
Savez-vous comment je pourrais ignorer les valeurs NoData des calculs (avec Raster Calculator et Python)?
Sam
Sam, "Ignorer" comment, précisément? Je crois que le comportement par défaut est de produire NoData là où un ou plusieurs rasters en entrée sont NoData (mais je ne suis pas complètement sûr de cela dans le cas de pick: si inPositionRaster et le raster sélectionné ont tous les deux des valeurs valides dans une cellule, alors plausiblement le résultat pour cette cellule doit être la valeur du raster sélectionné, quel que soit le contenu des autres rasters). À quel autre comportement pensez-vous?
whuber
J'en ai besoin pour sélectionner uniquement parmi les valeurs de nombre entier. Disons que j'ai trois rasters. Pour une cellule, leurs valeurs sont les suivantes: 4,5, NoData. Je veux que l'outraster ait un 4 ou 5 dans cette cellule mais jamais le NoData.
Sam
J'ai du mal à faire fonctionner ce 1 + Int (n * CreateRandomRaster ()).
Sam
"Trouble" dans quel sens? Soyez précis s'il vous plait!
whuber
4

En utilisant python et ArcGIS 10 et en utilisant la fonction con qui a la syntaxe suivante:

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

L'idée ici est de voir si la valeur dans le raster aléatoire est inférieure à 0,5, s'il s'agit de raster1, sinon de raster2. NoData+ data = NoDatadéfinissez d'abord ces valeurs de reclassification avec 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: Je viens de réaliser que vous n'ajoutez pas les NoDatavaleurs de sorte que la pièce puisse être laissée de côté.

djq
la source
Je travaille toujours sur mes compétences en Python. Existe-t-il un moyen d'entrer cela dans la calculatrice raster qui exclurait également les valeurs NoData du processus? J'ai 10 rasters et certains ont NoData où d'autres ont des valeurs.
Sam
Je pense que vous pouvez créer des conditions en utilisant quelque chose comme ça dans la calculatrice rasterCon(IsNull(ras1), 0, ras2)
djq
Malheureusement, cela n'exclut pas réellement les valeurs NoData: il les remplace simplement par des zéros. Dans certains cas, cela pourrait être approprié, mais probablement pas ici!
whuber
hmm, bon point @whuber. Alors qu'est-ce que cela signifie d'exclure NoData? Est-ce juste pour s'assurer qu'ils ne sont pas sélectionnés lors d'un choix aléatoire?
djq
C'est ainsi que je l'ai interprété (voir ma réponse modifiée dans ce fil), mais cela reste une bonne question. En ignorant les valeurs ND de cette manière, les grilles restantes sont sélectionnées avec une plus grande probabilité, ce qui pourrait être un effet secondaire indésirable. Tout dépend de l'objectif du calcul.
whuber
1

Je voudrais simplement créer un raster aléatoire ( aide ) de la même étendue et de la même taille de cellule. Ensuite, en utilisant CON ( aide ), définissez-le pour choisir la valeur du 1er raster si la cellule du raster randomisé a une valeur <128 (si un raster aléatoire est compris entre 0 et 255), sinon choisissez une valeur du 2ème raster.

J'espère que cela a du sens :)

jareks
la source
Savez-vous comment sélectionner uniquement des rasters avec des valeurs? Par exemple, dans ma figure, il y a quatre 2 et deux 3 qui se chevauchent avec NoData. Je veux m'assurer qu'il ne sélectionne que parmi les rasters avec des valeurs dans une cellule et non pas NoData.
Sam
Désolé de ne pas avoir répondu. Vous rencontrez toujours des problèmes avec NoData?
jareks