0

The 20 bars in my bar plot have labels stored in

channels=['a','b','c','d','e','f','g','h','i','j','k','m','n','o','p','q','r','s','t','u']

To each label there is associated a nonnegative integer between 0 and 100, and I want to plot 5 bars at a time, using a slider to advance through the channels. I'm trying to modify the approach at Scrollable Bar graph matplotlib to do so. Here's what I have so far:

fig,ax=plt.subplots(figsize=(10,6))

x=np.arange(1,20)
y=np.random.randint(0,100, len(x))
channels=
['a','b','c','d','e','f','g','h','i','j','k','m','n','o','p','q','r','s','t','u']

N=5

def bar(pos):
    pos = int(pos)
    ax.clear()
    if pos+N > len(x): 
        n=len(x)-pos
    else:
        n=N
    X=x[pos:pos+n]
    Y=y[pos:pos+n]
    ax.bar(X,Y,width=0.7,align='edge',color='green',ecolor='black')

    for i,txt in enumerate(X):
        ax.annotate(channels[i], (X[i],Y[i]))

barpos = plt.axes([0.18, 0.05, 0.55, 0.03], facecolor="skyblue")
slider = Slider(barpos, 'Channel', 0, len(x)-N, valinit=0,valstep=1)
slider.on_changed(bar)

bar(0)
plt.show()

This is semi-functional, but there is one bug and three minor modifications I can't seem to figure out.

  1. Currently, when I advance each frame on the slider, the N=5 labels are always 'a','b','c','d','e'. Of course I want the labels to change so that for the second frame, say, the labels are 'b','c','d','e','f'.
  2. I would like to have my y-axis labels fixed as the slider moves, running from 0 to 100 in increments of 20. In the present form the y-axis labels vary as I move the slider. The increment of the y-axis is sometimes 10, sometimes 20, etc. The maximum y-axis label is generally the maximum of all values in y.
  3. How can I control the font size of each label?
fishbacp
  • 1,123
  • 3
  • 14
  • 29

1 Answers1

0

This seems to work although suggestions to improve efficiency would be very much welcomed. The key to addressing #1 and #3 above is to change the annotations to read

ax.annotate(channels[txt-1], (X[i],Y[i]),fontsize=16)

The axes problems are handled by ax.set_yticks and ax.set_ylim

Then we have the following:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

fig,ax=plt.subplots(figsize=(10,6))

fig.suptitle('My Title', fontsize=20)

x=np.arange(1,21)
y=np.random.randint(0,100, len(x))

channels= ['a','b','c','d','e','f','g','h','i','k','l',
'i','j','k','m','n','o','p','q','r','s','t','u']

N=5

def bar(pos):
    pos = int(pos)
    ax.clear()
    if pos+N > len(x): 
        n=len(x)-pos
    else:
        n=N
    X=x[pos:pos+n]
    Y=y[pos:pos+n]
    ax.bar(X,Y,width=0.7,align='center',color='green',ecolor='black')


    ax.yaxis.set_visible(True)
    y_incr = np.arange(0,100,25)
    ax.set_yticks(y_incr)
    ax.set_ylim(top=100)

    for i,txt in enumerate(X):
        ax.annotate(channels[txt-1], (X[i],Y[i]),fontsize=16)

    ax.xaxis.set_ticks([])

barpos = plt.axes([0.18, 0.05, 0.55, 0.03], facecolor="skyblue")
slider = Slider(barpos, 'Channel', 0, len(x)-N, valinit=0,valstep=1)


slider.on_changed(bar)
bar(0)

plt.show()
fishbacp
  • 1,123
  • 3
  • 14
  • 29