2015-06-18 9 views
14

Il mio script python utilizza matplotlib per tracciare una "heat map" 2D di un dataset x, y, z. I miei valori xey rappresentano i residui amminoacidici in una proteina e possono quindi essere solo numeri interi. Quando ho zoom della trama, sembra che questo:Matplotlib: Come forzare le etichette di graduazione del numero intero?

2D heat map with float tick marks

Come ho detto, i valori float sugli assi XY non hanno senso con i miei dati e pertanto voglio farlo sembrare come questo: enter image description here

Qualche idea su come raggiungere questo obiettivo? Questo è il codice che genera la trama:

def plotDistanceMap(self): 
    # Read on x,y,z 
    x = self.currentGraph['xData'] 
    y = self.currentGraph['yData'] 
    X, Y = numpy.meshgrid(x, y) 
    Z = self.currentGraph['zData'] 
    # Define colormap 
    cmap = colors.ListedColormap(['blue', 'green', 'orange', 'red']) 
    cmap.set_under('white') 
    cmap.set_over('white') 
    bounds = [1,15,50,80,100] 
    norm = colors.BoundaryNorm(bounds, cmap.N) 
    # Draw surface plot 
    img = self.axes.pcolor(X, Y, Z, cmap=cmap, norm=norm) 
    self.axes.set_xlim(x.min(), x.max()) 
    self.axes.set_ylim(y.min(), y.max()) 
    self.axes.set_xlabel(self.currentGraph['xTitle']) 
    self.axes.set_ylabel(self.currentGraph['yTitle']) 
    # Cosmetics 
    #matplotlib.rcParams.update({'font.size': 12}) 
    xminorLocator = MultipleLocator(10) 
    yminorLocator = MultipleLocator(10) 
    self.axes.xaxis.set_minor_locator(xminorLocator) 
    self.axes.yaxis.set_minor_locator(yminorLocator) 
    self.axes.tick_params(direction='out', length=6, width=1) 
    self.axes.tick_params(which='minor', direction='out', length=3, width=1) 
    self.axes.xaxis.labelpad = 15 
    self.axes.yaxis.labelpad = 15 
    # Draw colorbar 
    colorbar = self.figure.colorbar(img, boundaries = [0,1,15,50,80,100], 
            spacing = 'proportional', 
            ticks = [15,50,80,100], 
            extend = 'both') 
    colorbar.ax.set_xlabel('Angstrom') 
    colorbar.ax.xaxis.set_label_position('top') 
    colorbar.ax.xaxis.labelpad = 20 
    self.figure.tight_layout()  
    self.canvas.draw() 

risposta

28

Questo dovrebbe essere più semplice:

(da https://scivision.co/matplotlib-force-integer-labeling-of-axis/)

import matplotlib.pyplot as plt 
from matplotlib.ticker import MaxNLocator 
#... 
ax = plt.figure().gca() 
#... 
ax.xaxis.set_major_locator(MaxNLocator(integer=True)) 
+1

Non inserisce l'etichetta del segno di spunta nel punto centrale della regione specificata (come nell'immagine campione della domanda) e manca ogni secondo (senza etichetta). C'è un semplice trucco per raggiungerli? Il '2' dovrebbe essere nella posizione di 2,5, non a 2,0. – Andris

+0

@Andris wow su questo non ho assolutamente idea. Ma sembra strano comunque modificare la libreria di stampa per questo compito, probabilmente dovresti invece modificare i tuoi dati. L'immagine di esempio a cui ti riferisci sembra essere stata modificata con vernice o qualcosa di simile, quindi non significa che tale output sia possibile con matplotlib. –

+1

Questo dà risultati molto strani per me. Trasforma i tick [0, 2, 4, 8, 10] in [0.0, 1.5, 3.0, 4.5, 7.5, 9.0, 10.5]. Dato ciò che [docs] (http://matplotlib.org/api/ticker_api.html#matplotlib.ticker.MaxNLocator) dice che questo non dovrebbe accadere. – Annan

1

Sulla base di una risposta per modifying tick labels mi si avvicinò con una soluzione, non so se funzionerà nel tuo caso, come lo snippet di codice non può essere eseguita in se stesso.

L'idea è di forzare le etichette di graduazione su una spaziatura .5, quindi sostituire ogni .5 tick con la sua controparte intera e gli altri con una stringa vuota.

import numpy 
import matplotlib.pyplot as plt 

fig, (ax1, ax2) = plt.subplots(1,2) 

x1, x2 = 1, 5 
y1, y2 = 3, 7 

# first axis: ticks spaced at 0.5 
ax1.plot([x1, x2], [y1, y2]) 
ax1.set_xticks(numpy.arange(x1-1, x2+1, 0.5)) 
ax1.set_yticks(numpy.arange(y1-1, y2+1, 0.5)) 

# second axis: tick labels will be replaced 
ax2.plot([x1, x2], [y1, y2]) 
ax2.set_xticks(numpy.arange(x1-1, x2+1, 0.5)) 
ax2.set_yticks(numpy.arange(y1-1, y2+1, 0.5)) 

# We need to draw the canvas, otherwise the labels won't be positioned and 
# won't have values yet. 
fig.canvas.draw() 

# new x ticks '1'->'', '1.5'->'1', '2'->'', '2.5'->'2' etc. 
labels = [item.get_text() for item in ax2.get_xticklabels()] 
new_labels = [ "%d" % int(float(l)) if '.5' in l else '' for l in labels] 
ax2.set_xticklabels(new_labels) 

# new y ticks 
labels = [item.get_text() for item in ax2.get_yticklabels()] 
new_labels = [ "%d" % int(float(l)) if '.5' in l else '' for l in labels] 
ax2.set_yticklabels(new_labels) 

fig.canvas.draw() 
plt.show() 

Se si desidera eseguire lo zoom fuori un sacco, che avrà bisogno di qualche attenzione in più, come questo produce un insieme molto denso di etichette delle tacche poi.

+0

Grazie per la risposta! Farò un tentativo. – gha

Problemi correlati