2013-07-27 18 views
7

Chciałbym wiedzieć, jak działa numpy.gradient. Użyłem gradientu, aby spróbować obliczyć prędkość grupy (prędkość grupy pakietu falowego jest pochodną częstotliwości w odniesieniu do liczb falowych, a nie grupy prędkości). Wprowadziłem do niego tablicę 3-kolumnową, pierwsze 2 kolumny to współrzędne x i y, trzecia kolumna to częstotliwość tego punktu (x, y). Trzeba obliczyć nachylenie i ja spodziewałam 2d wektor, będąc definicji gradientuObliczenia gradientowe z pytonem

df/dx*i+df/dy*j+df/dz*k 

i moja funkcja tylko funkcją x, yi nie spodziewać się czegoś podobnego

df/dx*i+df/dy*j 

ale mam 2 tablice z 3 kolumny każdy, tj. 2 wektory wektorowe; na początku myślałem, że suma tych dwóch da mi wektor, którego szukam, ale składnik z nie zniknie. Mam nadzieję, że wyjaśniłem wystarczająco jasno. Chciałbym wiedzieć, jak działa numpy.gradient i czy jest to właściwy wybór dla mojego problemu. W przeciwnym razie chciałbym wiedzieć, czy istnieje jakakolwiek inna funkcja Pythona, której mogę użyć.

Chodzi mi o to: Chcę, aby obliczyć gradient tablicy wartości:

data=[[x1,x2,x3]...[x1,x2,x3]] 

gdzie x1, x2 są współrzędne punktów na jednolitej siatki (moje punkty od strefy Brillouina) i x3 jest wartość częstotliwości dla tego punktu. Podaję również dane wejściowe dla wyprowadzenia dla 2 kierunków:

stepx=abs(max(unique(data[:,0])-min(unique(data[:,0]))/(len(unique(data[:,0]))-1) 

to samo dla kierunku y. Nie zbudowałem swoich danych na siatce, mam już siatkę, dlatego nie pomagają mi dobre przykłady podane tutaj w odpowiedziach. bardziej stosowny przykład powinien mieć siatkę punktów i wartości, takich jak jeden mam:

data=[] 
for i in range(10): 
    for j in range(10): 
    data.append([i,j,i**2+j**2]) 

data=array(data,dtype=float) 

gx,gy=gradient(data) 

innego co mogę dodać, to to, że moja siatka nie jest kwadratem jeden, ale ma kształt wielokąta, będących Brillouin strefa kryształu 2d.

Zrozumiałem, że numpy.gradient działa poprawnie tylko na kwadratowej siatce wartości, a nie tego, czego szukam. Nawet jeśli zrobię moje dane jako siatkę, która miałaby wiele zer poza poligonem moich oryginalnych danych, to dodałoby naprawdę wysokie wektory do mojego gradientu, wpływając (negatywnie) na precyzję obliczeń. Ten moduł wydaje mi się raczej zabawką niż narzędziem, ma poważne ograniczenia imho.

Problem rozwiązany za pomocą słowników.

+0

Soooo jakie jest pytanie? Z jakiego modułu powinieneś skorzystać? Czy coś idzie nie tak? – Stephan

+0

Pytanie, co robi gradient? Dlaczego daje mi 2 wektory 3d zamiast wektora 1d? Czy gradient faktycznie oblicza gradient? Przez jego wyjście nie mogę powiedzieć. Nie wygląda mi to dokładnie. –

+0

Myślałem, że było jasne, trzeci komponent mojego wejścia to pole skalarne, każda wartość na trzecim komponencie jest wartością mojej funkcji dla każdego punktu (x, y). –

Odpowiedz

22

Musisz podać gradient matrycę, która opisuje twoje wartości częstotliwości kątowej dla twoich (x,y) punktów. na przykład

def f(x,y): 
    return np.sin((x + y)) 
x = y = np.arange(-5, 5, 0.05) 
X, Y = np.meshgrid(x, y) 
zs = np.array([f(x,y) for x,y in zip(np.ravel(X), np.ravel(Y))]) 
Z = zs.reshape(X.shape) 

gx,gy = np.gradient(Z,0.05,0.05) 

Widać, że wykreślenie oo jako powierzchni daje:

sinxpy

Oto jak interpretować swoje gradient:

gx jest macierzą która daje zmianę dz/dx w ogóle zwrotnica. na przykład gx [0] [0] to dz/dx o (x0,y0).Wizualizacja gx pomaga w zrozumieniu:

gx

Ponieważ moje dane zostały wygenerowane z f(x,y) = sin(x+y) gy wygląda tak samo.

poniżej bardziej oczywiste przykład za pomocą f(x,y) = sin(x) ...

f (x, y) enter image description here

a gradienty

g2

g1

aktualizacja Przyjrzyjmy się parom xy.

Jest to kod użyłem:

def f(x,y): 
    return np.sin(x) 
x = y = np.arange(-3,3,.05) 
X, Y = np.meshgrid(x, y) 
zs = np.array([f(x,y) for x,y in zip(np.ravel(X), np.ravel(Y))]) 
xy_pairs = np.array([str(x)+','+str(y) for x,y in zip(np.ravel(X), np.ravel(Y))]) 
Z = zs.reshape(X.shape) 
xy_pairs = xy_pairs.reshape(X.shape) 

gy,gx = np.gradient(Z,.05,.05) 

Teraz możemy spojrzeć i zobaczyć dokładnie to, co się dzieje. Powiedzmy, że chcieliśmy wiedzieć, który punkt był związany z wartością pod adresem Z[20][30]? Potem ...

>>> Z[20][30] 
-0.99749498660405478 

A chodzi o to

>>> xy_pairs[20][30] 
'-1.5,-2.0' 

Czy to prawda? Sprawdźmy.

>>> np.sin(-1.5) 
-0.99749498660405445 

Tak.

Jakie są nasze komponenty gradientowe w tym punkcie?

>>> gy[20][30] 
0.0 
>>> gx[20][30] 
0.070707731517679617 

Czy to sprawdzić?

dz/dy always 0 wyboru. dz/dx = cos(x) i ...

>>> np.cos(-1.5) 
0.070737201667702906 

Wygląda dobrze.

Zauważysz, że nie są one poprawne, ponieważ moje dane Z nie są ciągłe, rozmiar kroku 0.05 i gradient może jedynie przybliżać szybkość zmian.

+0

Siatka jest już w pliku podaję numpy.gradient. Nie mogę obliczyć funkcji tak jak ty, ponieważ nie znam równania. Otrzymałem te wartości z obliczeń ab initio. I znowu: nie wiem, dlaczego powinienem mieć 2 wektory 3D, gdy dla gradientu funkcji 2 zmiennych jest wektor 2d ... –

+1

Moja funkcja była częścią wymyślonego przykładu, środka do generowania danych Z. Mówisz w swoim pytaniu, że masz już dane "x, y, z", więc nie potrzebujesz funkcji ... po prostu wykonuj Z odpowiednio z danymi częstotliwości. 'gx' i' gy' dają 'x' i' y' pochodne dla każdego punktu w Z, który powinien być macierzą 'X' na podstawie' Y'. – seth

+0

Już próbowałem zrobić to, co zrobiłeś w twoim przykładzie, ale gradient wciąż daje mi 2 trójwymiarowe wektory ... Obliczenia Ab initio dają mi 8 częstotliwości dla każdego punktu (to jest relacja dyspersji fononów) Siatka to próbkowanie strefy brillouina . Nie wiem jak zrobić Z odpowiednio, powinno być już odpowiednie ... Może gradient po prostu nie obliczyć gradientu? Próbowałem z x ** 2 + y ** 2, gradiend powinien być 2d wektor: (2x, 2y), ale wciąż dostaję 2 3-d wektory. Jak mogę uzyskać rzeczywisty gradient z takich wydruków? –