2015-06-18 12 views
14

Mój skrypt python używa matplotlib do wykreślenia 2D "mapy ciepła" zbioru danych x, y, z. Moje wartości xi y reprezentują reszty aminokwasowe w białku i dlatego mogą być tylko liczbami całkowitymi. Kiedy powiększyć fabuły, wygląda to tak:Matplotlib: Jak wymusić etykiety liczby całkowitej?

2D heat map with float tick marks

Jak powiedziałem, wartości unosić się na osiach xy nie ma sensu z moimi danymi i dlatego ma to wyglądać tak: enter image description here

Jakieś pomysły, jak to osiągnąć? Jest to kod, który generuje działki:

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() 

Odpowiedz

28

ta powinna być prostsza:

(od 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

Nie umieszcza mnie na etykiecie pasków do środkowego punktu danego regionu (jak w przykładowym obrazie pytania), a co sekundę (bez etykiety) brakuje. Czy istnieje prosta sztuczka, aby je osiągnąć? Wartość "2" powinna wynosić 2,5, a nie 2,0. – Andris

+0

@Andris wow o tym nie mam absolutnie żadnego pojęcia. W każdym razie wydaje się dziwne, aby dostosować bibliotekę kreślarską do tego zadania, prawdopodobnie powinieneś zmodyfikować swoje dane. Przykładowy obraz, do którego się odnosisz wydaje się być edytowany za pomocą farby lub czegoś podobnego, więc nie oznacza to, że taki wynik jest możliwy z matplotlib. –

+1

Daje to bardzo dziwne wyniki. Zmienia on kleszcze [0, 2, 4, 8, 10] na [0.0, 1.5, 3.0, 4.5, 7.5, 9.0, 10.5]. Biorąc pod uwagę to, co [docs] (http://matplotlib.org/api/ticker_api.html#matplotlib.ticker.MaxNLocator) mówią, że to nie powinno się zdarzyć. – Annan

1

Na podstawie odpowiedzi na modifying tick labels wymyśliłem rozwiązanie, nie wiem, czy to będzie działać w Twoim przypadku jak Twój fragment kodu nie może być wykonany w sobie.

Chodzi o to, aby zmusić etykiety znaczników do odstępu .5, a następnie zastąpić każdy znak .5 znacznikiem całkowitym, a pozostałe z pustym łańcuchem.

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() 

Jeśli chcesz dużo pomniejszyć, będzie to wymagało dodatkowej opieki, ponieważ w ten sposób powstaje bardzo gęsty zestaw etykiet.

+0

Dziękuję za odpowiedź! Spróbuję tego. – gha

Powiązane problemy