Matplotlib - remove RectangleSelector widget from the plot - python

I am creating a visual PyQt5 application which creates and shows Matplotlib plots. I want to be able to select some points on the plot with a mouse. I use RectangleSelector widget for it. The problem is, the drawn rectangle stays on plot after I release the mouse. Using interactive=False makes the rectangle invisible, but it is still there and breaks plot auto scale when I try to change the data to display on the plot. Here is the example with interactive=True :
After I load some other data to plot:
Is there any way to remove the RectangleSelector from the plot? Or at least to make ax.autoscale() ignore it?

You can use the "escape" key to clear the current shape. This can be redefined in the argument state_modifier_keys. For details see here.

A other way of doing it would be to this:
rectangle = RectangleSelector(...)
for artist in rectangle :
artist.set_visible(False)
rectangle.update()
this is what is done when the escape button is pressed and it will remove the current rectangle selector from your graph.

Not sure if you've resolved this yet.
I use this
def line_select_callback(self, eclick, erelease):
# At the beginning
toggle_selector.RS.set_active(False)
toggle_selector.RS.to_draw.set_visible(False)
toggle_selector.RS.update()
#....line_select_callback code....
# Last line of method/function
toggle_selector.RS.set_active(True)

Related

How can I use spacebar to close Matplotlib/Pyplot plots?

In Close a matplotlib figure using keyboard I learned that you can add keybinds to various matplotlib commands, including key.quit which exits the plot.
The keybinds can be assigned via:
plt.rcParams["keymap.quit"] = ['ctrl+w', 'cmd+w', 'q']
However, when I add space or spacebar to the list, space doesn't work. I know that list is defaults, so either I'm not modifying them at all or I have the name for spacebar wrong.
Does anyone know how to do this?
There is a paucity of documentation on exactly what the key mappings are for this functionality, but you can find out with this code snippet:
>>> from matplotlib import pyplot as plt
>>> fig = plt.figure()
>>> fig.canvas.mpl_connect('key_press_event', lambda evt: print(repr(evt.key)))
8
Then
>>> plt.show()
will open an empty plot window. Pressing keys in the window will print to your terminal the associated keymap code.
When pressing the space bar I get:
' '
Confirmed that setting plt.rcParams['keymap.quit'].append(' ') works--pressing the space bar closes the window.

How do I remove the little red line marking the initial value of the amplitude in my slider?

I am using a matplotlib.widgets slider and it's working perfectly but there is a little red line that marks the initial value of the slider that I would like to remove. I checked the documentation for the Slider function and there was a mention of something called a vline or hline which I think is what I'm looking to remove but it doesn't say anywhere how to remove that line. Here is what I'm referring to.
And here is the code I have for showing the slider:
amp_slider = Slider(ax=axamp, label='Amplitude', valmin=0, valmax=10, valinit=init_amplitude, orientation='vertical')
This worked for me:
amp_slider.hline._linewidth = 0
To find it, I just printed the elements of some_slider.hline.__dict__.keys(). For a horizontal slider (default), it would be the vline that needs to be adjusted.

Python Matplotlib MouseEvent xy vs. xydata

I am working on a project to make a mouse click interactive pixel map (created with pyplot) using Python 3.4 and Matplotlib 1.4.3. I am using the matplotlib.backend_bases.MouseEvent class to make my figure interactive. I'm just getting started, and so far I have:
# Define an on_click() function that will print event data upon mouseclick
def on_click(event):
"""Print event data on mouseclick"""
print(event)
When I click on the figure, here's the kind of output I get:
MPL MouseEvent: xy=(289,265) xydata=(24.5956632653,21.9489795918) button=1 dblclick=False inaxes=Axes(0.141923,0.1;0.603077x0.8)
Can anyone tell me what the xy part means? It's a 50x50 pixel map, so the xydata is the pixel position of the mouse click.
It is the position from left and bottom of canvas, respectively.
Here is the documentation:
the following attributes
x- x position - pixels from left of canvas
y- y position - pixels from bottom of canvas
canvas- the FigureCanvas instance generating the event

setting tickslabel in matplotlib disables mouse cursor position

Whenever I plot something in matplotlib, moving the mouse over the plot shows at the bottom the x and y position of the cursor. This is very convenient when exploring data.
Now, If I set the ticklabels to something else, the x position of the cursor at the bottom of the plot is empty, while the gui keeps track of the y position. Is there a way to keep getting the x position?
This is a simple example of this happening:
import numpy as np
fig, ax = plt.subplots()
x=np.linspace(0,np.pi)
y=np.sin(x)
ax.plot(x,y)
ax.set_xticks([0,np.pi/2,np.pi])
ax.set_xticklabels(['0','pi/2','pi'])
plt.show()
No, there is no easy way to do this.
When you set the labels with a list of strings you set the xaxis.major_formatter to be FixedFormatter (doc) which has some peculiar behavior to make it work (it always returns '', unless you give it a third argument which given when it labels the x-axis, but not otherwise). The marking of where the cursor is is generated using the major_formatter and when you call a FixedFormatter it returns '', which is what is displayed.
If you really want this, you have to write your own call back, see Color values in imshow for matplotlib? for a starting point. (or subclass axes and re-implement format_coord (around line 2903 in axes.py in current matplotlib master branch)

Using matplotlib, how do I whiten the background of the axis label?

Is there a way to whiten out the background of the axis label so that when it crosses the axis line itself, the latter does not run through it?
For example, this script (the best I managed so far)
#!/usr/bin/python
import matplotlib.pyplot as plt
xx=[1,2,3]
yy=[2,3,4]
dy=[0.1,0.2,0.05]
fig=plt.figure()
ax=fig.add_subplot(111)
ax.errorbar(xx,yy,dy,fmt='ro-',ms=6,elinewidth=4)
ax.set_xlim([0.,3.4])
ax.set_ylim([0.,4.4])
ax.set_xlabel(r'$T/t$',fontsize=16)
ax.set_ylabel(r'$S(\mathbf{Q})L^{1+\eta}$',fontsize=16)
# position the axis labels
ax.xaxis.set_label_coords(1,0)
ax.yaxis.set_label_coords(0.1,0.93)
ax.yaxis.get_label().set_rotation('horizontal')
ax.yaxis.get_label().set_backgroundcolor('w')
#ax.yaxis.get_label().set_zorder(222) #doesn't do the trick
plt.show()
produces almost what I'm looking for, but still the y-axis runs over the label: .
By default, the left spine has a zorder of 2.5. For some reason this seems to cause problems; maybe there's something in the code which only works if they're integral? Anyway, if you add
ax.spines['left'].set_zorder(2)
or more generally
ax.spines['left'].set_zorder(ax.yaxis.get_label().get_zorder()-1)
before the show, it should work. Also, set_ylabel returns the ylab object itself, so if you use "ylab = ax.set_ylabel(stuff)" you can avoid all the ax.yaxis.get_label() calls later.
Does this link help you?
http://matplotlib.sourceforge.net/faq/howto_faq.html#automatically-make-room-for-tick-labels
You can simply shift the y-axis to the right to allows some space for the $S(\mathbf{Q})L^{1+\eta}$ mark be fully placed before the axis line.

Categories

Resources