3

I am using Matplotlib (with 'tkAgg' backend) to display an image from a sequence of images.

I have a Slider widget setup to allow me to scroll through the image sequence - moving the slider changes which image is being displayed.

I also have an mpl_connect set to listen for key_relese_events specifically from the left and right arrow keys which calls the same on_change() method to either advance to the next image or show the previous image.

Both of these are working fine independent of eachother: when the program opens the slider is set to show to first image in the stack. I can then move the slider back and forth to show different images as well as press right or left to move back or forth by one image.

My only qualm/question is that when I use the arrow keys to advance images the slider value doesn't change at all. So if you advance say 20 images forward by pressing right arrow 20 times, the correct image will be displayed and the plot titles change appropriately however the slider still shows the initial value or whatever value it was at when you pressed the arrow keys.

Is there any way to set the value of the Slider widget and have the screen update to show the correct value. I believe (yet to fully test it) that you can access the value of the slider as myslider.val - however setting that value seems to have no link to what is being displayed graphically even after calling matplotlib.pyplot.draw()

TL;DR Is there a way to have the Slider value that is displayed in the figure be tied to a local variable so that when that variable changes (new image being displayed) the Slider will change accordingly?

This is really only for aesthetic value as I previously mentioned that both of my controls for advancing the images work independent of eachother

Here are some snippets of my code (in no particular order) cut form my source. I hope its clear enough what the functions are doing-

def on_change(val): """ This function updates the LEEM image based on the slider value, val This function is also called to update the image when an arrow key release is detected """ global curimg curimg = energy_to_filenumber(round(val, 1)) img = all_dat[0:imheight-1, 0:imwidth-1, curimg] leemax.set_title("LEEM Image: " + str(elist[ int(energy_to_filenumber(round(val, 1)))]) + ' eV') leemax.imshow(img, cmap=cm.Greys_r) pylab.draw() def arrow_key_image_control(event): """ This function takes an event from an mpl_connection and listens for key release events specifically from the keyboard arrow keys (left/right) and uses this input to advance/reverse to the next/previous image. """ global curimg minindex = 0 maxindex = all_dat.shape[2] - 1 if event.key == 'left': if curimg - 1 >= minindex: curimg -= 1 on_change(filenumber_to_energy(curimg)) else: pass elif event.key == 'right': if curimg + 1 <= maxindex: curimg += 1 on_change(filenumber_to_energy(curimg)) else: pass else: pass sld_ax = fig.add_axes([0.2, 0.025, 0.75, 0.02]) imsld = Slider(sld_ax, "Electron Energy", elist[0], elist[len(elist)-1], elist[0], valfmt='%1.1f') imsld.on_changed(on_change) id2 = fig.canvas.mpl_connect('key_release_event', arrow_key_image_control) 
4
  • 2
    The (sadly) undocumented set_val method on the Slider object will set it's value and update the screen (or so it looks from skimming the code). If you interested, mpl is always open to improvements and a PR adding a docstring to set_val would be greatly appreciated! Commented Jan 11, 2015 at 0:41
  • Aha! I figured there had to be some way to accomplish that. Whats a PR? sorry I'm new to this - pull request? Commented Jan 11, 2015 at 0:46
  • Yes, pull request, see matplotlib.org/devel/gitwash/git_development.html. In short, fork mpl on github, clone to your machine, make a new branch, hack-commit-loop, push to github, open pull request, code review, then merge to main-line. Commented Jan 11, 2015 at 0:50
  • Also, if the workflow documentation does not make sense that should be fixed too. Commented Jan 11, 2015 at 0:59

1 Answer 1

3

Thanks to @tcaswell for the comment with the solution

There is an undocumented method in the Slider class slider.set_val() which accomplishes exactly what I needed - it sets the slider values to a given value and then updates the figure containing the slider so the change is visible.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.