I'm trying to handle some events to perform user interactions with embedded subplots into a Tkinter frame. Like in this example
Works fine with "key_press_event" and "button_press_event", but does not work with "pick_event".
I modified that example from the link, just adding the following piece of code after the mpl_connect calling:
def on_button_press(event):
print('you pressed mouse button')
canvas.mpl_connect('button_press_event', on_button_press)
def on_pick(event):
print('you picked:',event.artist)
canvas.mpl_connect('pick_event', on_pick)
Why "pick_event" doesn't work into embedded graphs? And how do get it to work?
My configurations detailed:
Windows 10
Python 3.5 (conda version)
Matplotlib 1.5.3 installed via pip
Thanks in advance!
Well, I solved it...
Most events we just need to use mpl_connect method to the magic happen. My mistake is that I didn't notice that we need to say explictly that our plot is "pickable" putting a argument picker=True to only triggers the event if clicked exacly into the artist, and picker=x where x is an integer that is the pixel tolerance for the trigger. So beyond the changes I inserted for pick in the question, we should replace
a.plot(t, s) for a.plot(t, s,picker=True) or a.plot(t, s,picker=10), e.g.
Related
X = np.arange(20)
y = np.log(X**2)
# set title in Chinese
plt.title('你好')
sns.set_style({'axes.facecolor':'red','font.sans-serif':['SimSun']})
sns.lineplot(X,y,color="blue")
When I run this code first time in Jupyter,the title can be shown correctly, that means the font.sans-serif property worked well, but the backgroundcolor is not red.
But when I run the same code again for the second time, the axes.facecolor property works,the backgroundcolor changes to be red.
That makes me confused, why did this happend? And is there any other property like this?
According to the seaborn style aesthetics configuration tutorial, local style control should be done with (for instance):
with sns.axes_style("darkgrid"):
sns.lineplot(X,y,color="blue")
For global settings, use sns.set_style(...) before any plotting statement in order to it to be taken into account. This is why you have to launch it twice in Jupyter to take effect. Dedicating a cell to it right after the import could be a better solution.
I am trying to make a interactive function where I can control the input with 2 widgets for the same variable. I Trying this because I want to have the option to slider the values (for a quick view) and also pick one specific (typing one value). I tried this linking the widgets with the ipywidget.jslink. I guessed once the widgets where linked I could input the values in any of them to pass to the variable. However, it is not what happens: below, only the values I set in the Slider updates the function (in other words, typing a value in the widget doesn't update the output). Why doesn't jslink work? In this link I found that substituting ipw.jslink for traitlets.linkworks fine.
import ipywidgets as ipw
from IPython.display import display
def f(x):
return x**2
a=ipw.IntSlider(min=-10,max=20,step=1,value=10)
b=ipw.IntText(min=-10,max=20,step=1,value=10)
ipw.jslink((a,'value'),(b,'value'))
wid=ipw.interactive(f, x=a)
display(wid,b)
If the issue is the Python objects not updating on the backend, it is probably because you are using jslink instead of link [ref]. Otherwise, I think this is an old issue with a previous version. I recreated with captured output and both the slider and Text call the function f(x):
from IPython.display import display
output = ipw.Output()
#output.capture()
def f(x):
print(x**2)
return x**2
a=ipw.IntSlider(min=-10,max=20,step=1,value=10)
b=ipw.IntText(min=-10,max=20,step=1,value=10)
ipw.jslink((a,'value'),(b,'value'))
wid=ipw.interactive(f, x=a)
display(wid,b)
display(output)
I'm working with matplotlib plotting and use ioff() to switch interactive mode off to suppress the automatic opening of the plotting window on figrue creation. I want to have full control over the figure and only see it when explicitely using the show() command.
Now apparently the built-in commands to clear figures and axes do not work properly anymore.
Example:
import numpy as np
import matplotlib.pyplot as mpp
class PlotTest:
def __init__(self,nx=1,ny=1):
# Switch off interactive mode:
mpp.ioff()
# Create Figure and Axes:
self.createFigure(nx, ny)
def createFigure(self,nx=1,ny=1):
self.fig, self.axes = mpp.subplots(nx,ny)
if nx*ny == 1:
self.axes = np.array([self.axes])
def linePlot(self):
X = np.linspace(0,20,21)
Y = np.random.rand(21)
self.axes[0].plot(X,Y)
P = PlotTest()
P.linePlot()
P.fig.show()
Now I was thinking I could use P.fig.clear() any time to simply clear P.fig, but apparently that's not the case.
Writing P.fig.clear() directly into the script and execute it together it works and all I see is an empty figure. However that's rather pointless as I never get to see the actual plot like that.
Doing P.fig.clear() manually in the console does not do anything, regardless if the plot window is open or not, all other possible commands fail as well:
P.fig.clf()
P.axes[0].clear()
P.axes[0].cla()
mpp.clf()
mpp.cla()
mpp.close(P.fig)
Wrapping the command into a class method doesn't work either:
def clearFig(self):
self.fig.clear()
EDIT ================
After a clear() fig.axes is empty, yet show() still shows the old plot with the axes still being plotted.
/EDIT ================
Is it because I switched off interactive mode?
If you add a call to plt.draw() after P.fig.clear() it clears the figure. From the docs,
This is used in interactive mode to update a figure that has been altered, but not automatically re-drawn. This should be only rarely needed, but there may be ways to modify the state of a figure with out marking it as stale. Please report these cases as bugs.
I guess this is not a bug as you have switched off interactive mode so it is now your responsibility to explicitly redraw when you want to.
You can also use P.fig.canvas.draw_idle() which could be wrapper in the class as clearFigure method.
I am using the IPython module in a Jupyter Notebook.
I am using the display module to display buttons.
from ipywidgets import widgets
import IPython.display as dsply
def click_reset(b):
print("reset domains button")
restoreDomains()
resetButton = widgets.Button(description="Reset Domains")
resetButton.on_click(click_reset)
dsply.display(resetButton)
This works fine, but I am trying to find a way to programatically hide certain buttons. Based off the execution of my other code, I want certain buttons to be removed from the UI. Is there anything like hide(resetButton) that I can use?
You can hide a widget using
resetButton.layout.visibility = 'hidden'
to let the widget still consume space, or
resetButton.layout.display = 'none'
to let the widget not consume space anymore.
The top-level attribute resetButton.visible = False is not longer supported.
When I use #SergeyGornostaev's answer, I still have a residual cross showing up on the left side of the cell output. I found the following command removes the widget all together:
resetButton.close()
You can hide every widget by setting it's property visible to False
resetButton.visible = False
I'm trying to use matplotlib for chart visualizations, but it is very annoying to look for a window each time I run the project. Is there any way to force it to be on top of other windows? I use OSX 10.8 and PyCharm IDE and already tried
from pylab import get_current_fig_manager()
get_current_fig_manager().window.raise_()
Which fails with
AttributeError: 'FigureManagerMac' object has no attribute 'window'
I'd appreciate any other ideas.
you're call to window.raise_() is from PyQT.
Indeed, you can raise the window in this way but you need to:
set PyQT4 as your backend before you do any other business with matplotlib
And
import matplotlib
matplotlib.use('Qt4Agg')
Either you fix you import statement (remove the brackets) or save yourself the import and access the window through the figure
with
window = fig.canvas.manager.window
Only then you can call window.raise_() and the window will be in front of pycharm.
This works for me from IPython:
from pylab import get_current_fig_manager
fm = get_current_fig_manager()
fm.show()
I haven't found a case in which show() doesn't work by itself, though.
[cphlewis] had a great answer. I found myself doing this so often that I def a little function to pop all my windows up to the surface:
def pop_all():
#bring all the figures hiding in the background to the foreground
all_figures=[manager.canvas.figure for manager in matplotlib.\
_pylab_helpers.Gcf.get_all_fig_managers()]
[fig.canvas.manager.show() for fig in all_figures]
return len(all_figures)