2011-03-03 22 views
14

Ci sono delle librerie python che mi permetteranno di tracciare z = f (x, y) dove z è rappresentato come il colore in un'immagine densamente rasterizzata (al contrario del colore di un mucchio di punti scatterplot)? In tal caso, quale funzione devo usare?Come tracciare la funzione 3D come mappa di colori 2D in python?

Sembra che alcune delle funzioni di contorno in matplotlib.pyplot si avvicinino a ciò che desidero, ma disegnano linee di contorno e non lo voglio.

risposta

8

Date un'occhiata alla documentazione per pcolor o imshow in matplotlib.

Un altro buon punto di partenza è dare un'occhiata alla galleria matplotlib e vedere se c'è un tipo di trama che corrisponde a quello che stai cercando e quindi utilizzare il codice di esempio come punto di saltare fuori per il proprio lavoro:

http://matplotlib.sourceforge.net/gallery.html

+0

quelli o 'matshow'. – Autoplectic

+0

Non suggerirei imshow per un array 3d. –

8

ecco un semplice esempio concreto (funziona anche per funzioni che non possono assumere gli argomenti di matrice per x e y):

# the function to be plotted 
def func(x,y):  
    # gives vertical color bars if x is horizontal axis 
    return x 

import pylab 

# define the grid over which the function should be plotted (xx and yy are matrices) 
xx, yy = pylab.meshgrid(
    pylab.linspace(-3,3, 101), 
    pylab.linspace(-3,3, 111)) 

# indexing of xx and yy (with the default value for the 
# 'indexing' parameter of meshgrid(..)) is as follows: 
# 
# first index (row index) is y coordinate index 
# second index (column index) is x coordinate index 
# 
# as required by pcolor(..) 

# fill a matrix with the function values 
zz = pylab.zeros(xx.shape) 
for i in range(xx.shape[0]): 
    for j in range(xx.shape[1]): 
     zz[i,j] = func(xx[i,j], yy[i,j]) 

# plot the calculated function values 
pylab.pcolor(xx,yy,zz) 

# and a color bar to show the correspondence between function value and color 
pylab.colorbar() 

pylab.show() 
+1

Il codice di loop è sbagliato: stai iterando attraverso gli oggetti sbagliati. Funziona solo perché xx e yy hanno la stessa lunghezza. Prova con altri valori invece di 101 per vedere cosa intendo. – marcv81

+0

grazie per averlo indicato, che dovrebbe essere risolto ora –

+1

Sembra funzionare, grazie per il tempo dedicato a rivisitare la risposta. Personalmente preferisco l'approccio un po 'più semplice 'xx = pylab.linspace (-3,3, 101)', lo stesso per 'yy', quindi iterare con' for i in xrange (len (xx)) 'e' for j in xrange (len (yy)) ', e usa' zz [i, j] = func (xx [i], yy [j]) '. – marcv81

1

dare credito dove è dovuto: questa è solo una leggera variazione della risposta di Andre Holzner. Per favore, invitalo se devi!

import pylab 

def f(x, y): 
    return pylab.cos(x) + pylab.sin(y) 

xx = pylab.linspace(-5, 5, 100) 
yy = pylab.linspace(-5, 5, 100) 
zz = pylab.zeros([len(xx), len(yy)]) 

for i in xrange(len(xx)): 
    for j in xrange(len(yy)): 
     zz[j, i] = f(xx[i], yy[j]) 

pylab.pcolor(xx, yy, zz) 
pylab.show() 

La sintassi è forse più facile da leggere con minimo strettamente di dimensioni di matrice e indici. Si basa sul seguente punto (citato dal doc).

If either or both of X and Y are 1-D arrays or column vectors, they will be expanded as needed into the appropriate 2-D arrays, making a rectangular grid.

+0

Il doppio ciclo, tuo e di Andre, è inutile e nefasto perché puoi semplicemente scrivere 'zz = func (xx, yy)' che è probabilmente più veloce di ordini di grandezza. – gboffi

+0

In realtà ho provato qualcosa del genere ma non ho potuto farlo funzionare! Con o senza inizializzare zz con zeri (riga prima dei cicli nidificati) non fa alcuna differenza. Puoi farlo funzionare? – marcv81

+0

Vedere la mia pseudo risposta sotto – gboffi

1

di espandere il mio commento di cui sopra, ecco alcuni modi possibili di calcolare una funzione su una griglia

[email protected]:~/Documents/tmp$ cat grid.py 
import numpy as np 

def z(x,y): 
    return np.sin(np.sqrt(x*x+y*y)) 

x = np.linspace(-1,1,11) 
y = np.linspace(-2,2,21) 

# naive 

Z0 = np.zeros((len(y), len(x))) 
for i, X in enumerate(x): 
    for j, Y in enumerate(y): 
     Z0[j,i] = z(X,Y) 

# trampoline on a double list comprehension, 
# it is possibly faster, sure it uses more memory 

Z1 = np.array([[z(X,Y) for X in x] for Y in y]) 

# numpy has meshgrid, 
# meshgrid uses twice memory as the result matrix but 
# if used _correctly_ it's FAST 

X, Y = np.meshgrid(x, y) 

# numpy can avoid you explicit looping, 
# but if you are so inclined... 

Z2 = np.zeros((len(y), len(x))) 
for r in range(len(y)): 
    for c in range(len(x)): 
     Z2[r, c] = z(X[r, c], Y[r, c]) 

# numpy has ufuncs, and 
# t h i s i s t h e w a y t o g o 

Z3 = z(X, Y) 

# numpy has broadcasting (it's slower than Z = z(X, Y), less memory) 

Z4 = z(x, y[:,None]) 

# note that x is still a _row_ of numbers, indexed by _columns_, 
# while y[:,None] is now a _column_ of numbers, indexed by _rows_, 
# so that Z4[row,column] <-- z(x[column], y[row]) 

# a bit of testing 

# in previous answers, Z2 (i.e., explicit loops) 
# is the preferred method --- here we show that the other four 
# possible methods give you exactly the same result 

print np.all(Z2==Z0) 
print np.all(Z2==Z1) 
print np.all(Z2==Z3) 
print np.all(Z2==Z4) 
[email protected]:~/Documents/tmp$ python2 grid.py 
True 
True 
True 
True 
[email protected]:~/Documents/tmp$ 
+0

OK, mi mancava meshgrid. Grazie! – marcv81

Problemi correlati