2013-03-04 8 views
10

In altre parole, desidero creare una heatmap (o diagramma di superficie) in cui il colore varia in base alle variabili . (In particolare, luminanza = magnitudine e tonalità = fase.) Esiste un modo nativo per farlo? Alcuni esempi di trame simili:Esiste un modo per utilizzare le mappe di colori bivariate in matplotlib?

uses two colorbars, one for magnitude and one for phase

uses a colorbar for magnitude and a circular legend for phase

uses a 2D colorbar to indicate the changes in both variables

Several good examples of exactly(?) what I want to do.

More examples from astronomy, but with non-perceptual hue

+0

Questo è un po 'di non risposta, ma 'imshow' richiede una matrice' NxMx3' o 'NxMx4' in modo da poter eseguire manualmente la mappatura dei colori. Sono d'accordo che sarebbe utile. Potresti ottenere un po 'di trazione classificando in subordine "Normalizza" e disponendo la tua mappa dei colori in modo molto intelligente.Penso che l'ovvia estensione sia lasciare che le mappe dei colori prendano argomenti complessi, ma probabilmente è molto lavoro. – tacaswell

+0

Non sono sicuro di come farlo, ma sei sicuro che sia una buona idea? occhio umano non è molto bravo a stimare i valori dal colore (e la colormap a getto è un famigerato criminale). Usarne due allo stesso tempo può essere un vero killer. Vi consiglio caldamente di leggere 'http: // www.research.ibm.com/people/l/lloydt/color/color.HTM'. – EnricoGiampieri

+0

@EnricoGiampieri: No, non sono sicuro che sia una buona idea, ma voglio provarlo. L'intento è quello di mostrare la magnitudine come leggerezza percettiva e l'angolo di fase come tonalità percettiva (non solo il tipo HSV), con il massimo della crominanza per renderli il più distinti possibile. Gli angoli di fase in aree di bassa magnitudo sono generalmente casuali e dovrebbero comunque essere mascherati. In questo caso saranno mascherati dall'oscurità. [Sì, mi lamento sempre di 'jet'.] (Https://github.com/matplotlib/matplotlib/issues/875): D – endolith

risposta

5

imshow richiederà un NxMx3 (RBG) o NxMx4 (grba) array in modo da poter eseguire la mappatura dei colori 'a mano'.

Potreste essere in grado di ottenere un po 'di trazione per sotto-classing Normalize per mappare il vostro vettore per uno scaler e layout di una mappa di colori personalizzato molto abilmente (ma penso che questo finirà per dover bin uno dei le tue dimensioni).

Ho fatto qualcosa di simile a questo (pdf link, vedere la figura a pagina 24), ma il codice è in MATLAB (e sepolto da qualche parte nei miei archivi).

Sono d'accordo che una mappa a colori a due variabili sarebbe utile (principalmente per rappresentare campi vettoriali molto densi in cui ti trovi in ​​cima al torrente, non importa quello che fai). Penso che l'estensione ovvia sia quella di consentire alle mappe del colore di assumere argomenti complessi. Richiedere sottoclassi specializzate di Normalize e Colormap e sto andando avanti e indietro se penso che sarebbe molto lavoro da implementare. Sospetto che se lo fai funzionare a mano sarà solo una questione di api che litigano.

6

imshow può richiedere un array di voci [r, g, b]. In questo modo puoi convertire i valori assoluti in intensità e fasi - in tonalità.

Userò come esempio numeri complessi, perché per esso ha più senso. Se necessario, è sempre possibile aggiungere gli array numpyZ = X + 1j * Y.

Quindi per i tuoi dati Z puoi utilizzare ad es.

imshow(complex_array_to_rgb(Z)) 

dove (EDIT: ha reso più veloce e più bello grazie a this suggestion)

def complex_array_to_rgb(X, theme='dark', rmax=None): 
    '''Takes an array of complex number and converts it to an array of [r, g, b], 
    where phase gives hue and saturaton/value are given by the absolute value. 
    Especially for use with imshow for complex plots.''' 
    absmax = rmax or np.abs(X).max() 
    Y = np.zeros(X.shape + (3,), dtype='float') 
    Y[..., 0] = np.angle(X)/(2 * pi) % 1 
    if theme == 'light': 
     Y[..., 1] = np.clip(np.abs(X)/absmax, 0, 1) 
     Y[..., 2] = 1 
    elif theme == 'dark': 
     Y[..., 1] = 1 
     Y[..., 2] = np.clip(np.abs(X)/absmax, 0, 1) 
    Y = matplotlib.colors.hsv_to_rgb(Y) 
    return Y 

Così, ad esempio:

Z = np.array([[3*(x + 1j*y)**3 + 1/(x + 1j*y)**2 
       for x in arange(-1,1,0.05)] for y in arange(-1,1,0.05)]) 
imshow(complex_array_to_rgb(Z, rmax=5), extent=(-1,1,-1,1)) 

enter image description here

imshow(complex_array_to_rgb(Z, rmax=5, theme='light'), extent=(-1,1,-1,1)) 

enter image description here

Problemi correlati