Czy tworzysz raster, wybierając losowo wartość komórki z wielu nakładających się rastrów?

10

Korzystam z ArcGIS Desktop 10 z rozszerzeniem Spatial Analyst.

Jak połączyć wiele rastrów w jeden, zawsze wybierając losowo spośród wartości nakładających się komórek?

Mam obraz, który może to lepiej wyjaśnić:

przykład

Sam
źródło

Odpowiedzi:

7

Pick został stworzony dla takich problemów. Potraktuj to jako wersję „con”, która jest implementacją algebry map „if ... else” w wersji „switch” (lub „case”).

Jeśli na przykład istnieją 3 nakładające się rastry, wyglądałaby składnia (Python)

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

Pamiętaj, że pickindeksowanie rozpoczyna się od 1, a nie od 0.


Edytować

(patrz temat komentarza)

Aby poradzić sobie z wartościami NoData, najpierw musisz wyłączyć obsługę NoData ArcGIS. Zrób to, tworząc siatki, które mają specjalną (ale prawidłową) wartość zamiast NoData, taką jak 99999 (lub cokolwiek innego, ale pamiętaj, aby wybrać wartość większą niż jakikolwiek prawidłowy numer, który może się pojawić: będzie to przydatne później) . To wymaga użycia wniosek IsNull, podobnie jak w

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

Na przykład rozważmy przypadek tych jednorzędowych siatek (NoData jest pokazana jako „*”):

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

Rezultatem jest wstawienie 99999 w miejsce każdego „*”.

Następnie wyobraź sobie te wszystkie rastry jako płaskie tablice drewnianych klocków z NoData odpowiadającymi brakującym blokom (dziurom). Kiedy ustawisz pionowo te rastry, bloki wpadną w dowolne otwory pod nimi. Potrzebujemy takiego zachowania, aby uniknąć wybierania wartości NoData: nie chcemy żadnych pionowych przerw w stosach bloków. Kolejność bloków w każdej wieży tak naprawdę nie ma znaczenia. W tym celu możemy uzyskać każdą wieżę poprzez uszeregowanie danych :

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

W przykładzie otrzymujemy

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

Zauważ, że rangi są od najniższej do najwyższej, więc q01 zawiera najniższe wartości w każdej lokalizacji, q02 zawiera drugą najniższą, itd. Kody NoData nie zaczynają się wyświetlać, dopóki wszystkie prawidłowe liczby nie zostaną zebrane, ponieważ te kody są większe niż jakiekolwiek prawidłowe liczby.

Aby uniknąć wybierania tych kodów NoData podczas losowego wyboru, musisz wiedzieć, ile bloków jest ułożonych w stos w każdej lokalizacji: informuje nas o tym, ile prawidłowych wartości występuje. Jednym ze sposobów poradzenia sobie z tym jest policzenie liczby kodów NoData i odjęcie ich od całkowitej liczby siatek wyboru:

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

To daje

n0:       3 2 2 1 2 1 1 0

Aby obsłużyć przypadki, w których n = 0 (więc nie ma już nic do wyboru), ustaw je na NoData:

n = SetNull(n0 == 0, n0)

Teraz

n:        3 2 2 1 2 1 1 *

Zagwarantuje to również, że twoje (tymczasowe) kody NoData znikną w końcowym obliczeniu. Wygeneruj losowe wartości od 1 do n:

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

Na przykład ten raster może wyglądać

inPositionRaster: 3 2 1 1 2 1 1 *

Wszystkie jego wartości mieszczą się w przedziale od 1 do odpowiedniej wartości w [n].

Wybierz wartości dokładnie tak jak poprzednio:

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

Spowodowałoby to

selection:       17  2  3  4 21 14 23  *

Aby sprawdzić, czy wszystko jest w porządku, spróbuj wybrać wszystkie komórki wyjściowe, które mają kod NoData (99999 w tym przykładzie): nie powinno być żadnych.

Chociaż ten działający przykład używa tylko trzech siatek do wyboru, napisałem go w sposób, który łatwo uogólnia na dowolną liczbę siatek. Przy wielu siatkach napisanie skryptu (w celu zapętlenia powtarzających się operacji) będzie nieocenione.

Whuber
źródło
Czy wiesz, jak mogłem zignorować wartości NoData z obliczeń (za pomocą Rastra i Pythona)?
Sam
Sam, jak to dokładnie „ignorować”? Wierzę, że domyślnym zachowaniem jest wyprowadzanie NoData wszędzie tam, gdzie jeden lub więcej rastrów wejściowych to NoData (ale nie jestem do końca tego pewien w przypadku pick: jeśli inPositionRaster i wybrany raster mają prawidłowe wartości w komórce, to prawdopodobnie wynik dla tej komórki powinna być wartość wybranego rastra, niezależnie od tego, co może zawierać inny raster). O jakim alternatywnym zachowaniu myślisz?
whuber
Potrzebuję go tylko do wybierania spośród wartości liczb całkowitych. Powiedzmy, że mam trzy rastry. Dla komórki ich wartości są następujące: 4,5, NoData. Chcę, żeby outraster miał albo 4 albo 5 w tej komórce, ale nigdy NoData.
Sam
Mam problem z uruchomieniem tego 1 + Int (n * CreateRandomRaster ()) do pracy.
Sam
„Kłopoty” w jakim sensie? Proszę, bądź konkretny!
whuber
4

Korzystanie z Pythona i ArcGIS 10 i korzystanie z funkcji con, która ma następującą składnię:

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

Chodzi tutaj o sprawdzenie, czy wartość w losowym rastrze jest mniejsza niż 0,5, jeśli wybierzesz raster1, w przeciwnym razie wybierz raster2. NoData+ dane = NoDatawięc najpierw ustaw te przeklasyfikuj dowolne wartości NoDatana 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

EDYCJA: Właśnie zrozumiałem, że nie dodajesz NoDatawartości, aby kawałek mógł zostać pominięty.

djq
źródło
Nadal pracuję nad moimi umiejętnościami w języku Python. Czy istnieje sposób, aby wprowadzić to do kalkulatora rastrowego, który również wykluczyłby wartości NoData z procesu? Mam 10 rastrów, a niektóre mają NoData, a inne mają wartości.
Sam
Myślę, że możesz stworzyć warunki używając czegoś takiego w kalkulatorze rastrowymCon(IsNull(ras1), 0, ras2)
djq
Niestety tak naprawdę nie wyklucza to wartości NoData: po prostu zastępuje je zerami. W niektórych przypadkach może to być właściwe, ale prawdopodobnie nie tutaj!
whuber
hmm, dobry punkt @ whuber. Co to znaczy wykluczać NoData? Czy to po prostu upewnić się, że nie zostaną one wybrane podczas losowego wyboru?
djq
Tak to interpretowałem (zobacz moją zredagowaną odpowiedź w tym wątku), ale pozostaje to dobre pytanie. Ignorowanie wartości ND w ten sposób powoduje, że pozostałe siatki są wybierane z większym prawdopodobieństwem, co może być niepożądanym efektem ubocznym. Wszystko zależy od celu obliczeń.
whuber
1

Po prostu stworzyłbym losowy raster ( pomoc ) o tym samym zakresie i rozmiarze komórki. Następnie za pomocą CON ( pomoc ) ustaw go, aby wybierał wartość z 1. rastra, jeśli komórka z randomizowanego rastra ma wartość <128 (jeśli losowy raster miałby wartość 0–255), w przeciwnym razie wybierz wartość z 2. rastra.

Mam nadzieję, że to ma sens :)

jareks
źródło
Czy wiesz, jak wybierać tylko spośród rastrów z wartościami? Na przykład na mojej figurze są cztery 2 i 2 3, które pokrywają się z NoData. Chcę się upewnić, że wybierze tylko te rastry z wartościami w komórce, a nie NoData.
Sam
Przepraszamy za brak odpowiedzi. Nadal masz problem z NoData?
jareks