plots - python graph function
Paginación/desplazamiento a través de un conjunto de mapas de calor 2D en matplotlib (2)
La solución podría ser utilizar un control deslizante como en la excelente respuesta de @hashmuke. En su respuesta, mencionó que "el control deslizante es continuo mientras que el índice de capa es un entero discreto [...]"
Esto me llevó a pensar en una solución que no tendría esta restricción y tendría
un aspecto más parecido a una página
.
El resultado es
PageSlider
.
Control
Slider
subclases utiliza la funcionalidad del control deslizante, pero muestra el control deslizante en pasos enteros que comienzan en
1
.
Toma el número de páginas
numpages
como argumento init, pero a excepción de eso funciona como
Slider
visto desde el exterior.
Además, también proporciona un botón de retroceso y avance.
Un ejemplo, similar al de @hashmuke, se da debajo de la clase.
import matplotlib.widgets
import matplotlib.patches
import mpl_toolkits.axes_grid1
class PageSlider(matplotlib.widgets.Slider):
def __init__(self, ax, label, numpages = 10, valinit=0, valfmt=''%1d'',
closedmin=True, closedmax=True,
dragging=True, **kwargs):
self.facecolor=kwargs.get(''facecolor'',"w")
self.activecolor = kwargs.pop(''activecolor'',"b")
self.fontsize = kwargs.pop(''fontsize'', 10)
self.numpages = numpages
super(PageSlider, self).__init__(ax, label, 0, numpages,
valinit=valinit, valfmt=valfmt, **kwargs)
self.poly.set_visible(False)
self.vline.set_visible(False)
self.pageRects = []
for i in range(numpages):
facecolor = self.activecolor if i==valinit else self.facecolor
r = matplotlib.patches.Rectangle((float(i)/numpages, 0), 1./numpages, 1,
transform=ax.transAxes, facecolor=facecolor)
ax.add_artist(r)
self.pageRects.append(r)
ax.text(float(i)/numpages+0.5/numpages, 0.5, str(i+1),
ha="center", va="center", transform=ax.transAxes,
fontsize=self.fontsize)
self.valtext.set_visible(False)
divider = mpl_toolkits.axes_grid1.make_axes_locatable(ax)
bax = divider.append_axes("right", size="5%", pad=0.05)
fax = divider.append_axes("right", size="5%", pad=0.05)
self.button_back = matplotlib.widgets.Button(bax, label=ur''$/u25C0$'',
color=self.facecolor, hovercolor=self.activecolor)
self.button_forward = matplotlib.widgets.Button(fax, label=ur''$/u25B6$'',
color=self.facecolor, hovercolor=self.activecolor)
self.button_back.label.set_fontsize(self.fontsize)
self.button_forward.label.set_fontsize(self.fontsize)
self.button_back.on_clicked(self.backward)
self.button_forward.on_clicked(self.forward)
def _update(self, event):
super(PageSlider, self)._update(event)
i = int(self.val)
if i >=self.valmax:
return
self._colorize(i)
def _colorize(self, i):
for j in range(self.numpages):
self.pageRects[j].set_facecolor(self.facecolor)
self.pageRects[i].set_facecolor(self.activecolor)
def forward(self, event):
current_i = int(self.val)
i = current_i+1
if (i < self.valmin) or (i >= self.valmax):
return
self.set_val(i)
self._colorize(i)
def backward(self, event):
current_i = int(self.val)
i = current_i-1
if (i < self.valmin) or (i >= self.valmax):
return
self.set_val(i)
self._colorize(i)
if __name__ == "__main__":
import numpy as np
from matplotlib import pyplot as plt
num_pages = 23
data = np.random.rand(9, 9, num_pages)
fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.18)
im = ax.imshow(data[:, :, 0], cmap=''viridis'', interpolation=''nearest'')
ax_slider = fig.add_axes([0.1, 0.05, 0.8, 0.04])
slider = PageSlider(ax_slider, ''Page'', num_pages, activecolor="orange")
def update(val):
i = int(slider.val)
im.set_data(data[:,:,i])
slider.on_changed(update)
plt.show()
Estoy generando diagramas de mapa de calor 2D de un conjunto de datos 3D. Me gustaría poder tener un mecanismo para navegar interactivamente por cada panel. A continuación se muestra un código de muestra simple, me gustaría poder ver interactivamente ambos paneles (es decir, z = [0,1]) a través de una barra deslizante (o algún otro medio). ¿Es esto posible con matplotlib o es algo que tendré que hacer después del procesamiento después de generar los archivos de imagen?
import numpy as np
from matplotlib import pyplot as plt
data = np.random.randint(10, size=(5, 5, 2))
data_slice = np.zeros((5,5))
for i in range(0, 5):
for j in range(0, 5):
data_slice[i][j] = data[i][j][0]
plt.imshow(data_slice, cmap=''hot'', interpolation=''nearest'')
plt.show()
Editar: quiero poder hacer esto de forma interactiva y parece que el posible duplicado está tratando de hacer esto automáticamente.
Puede animar las capas como lo sugiere el comentario de Andrew o puede caminar manualmente a través de las capas usando un control deslizante de la siguiente manera:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.widgets import Slider
# generate a five layer data
data = np.random.randint(10, size=(5, 5, 5))
# current layer index start with the first layer
idx = 0
# figure axis setup
fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.15)
# display initial image
im_h = ax.imshow(data[:, :, idx], cmap=''hot'', interpolation=''nearest'')
# setup a slider axis and the Slider
ax_depth = plt.axes([0.23, 0.02, 0.56, 0.04])
slider_depth = Slider(ax_depth, ''depth'', 0, data.shape[2]-1, valinit=idx)
# update the figure with a change on the slider
def update_depth(val):
idx = int(round(slider_depth.val))
im_h.set_data(data[:, :, idx])
slider_depth.on_changed(update_depth)
plt.show()
El control deslizante continúa mientras el índice de capa es un entero discreto, espero que no sea un problema. Aquí está la figura resultante,