BackGround
I'm making this software right plot data as boxplots and scatter plots. To make the graph more informative and clear I wanted the user to be able to drag-create a textbox on top of the figure if they wanted to add notes. This way when people share the figure it can be explained through these notes.
Current Approach and Problem
I have used annotate function to create a textbox in the upper right corner of the screen to tell the user how many data points have been used, but there are of few problems with this approach.
This is the code I used to create a text box to tell the user how many data pts there are.
self.axes.text(.98, .98, 'Number of Data Points: {}'.format(len(self.cleanedY)),
verticalalignment='top', horizontalalignment='right',
transform=self.axes.transAxes,
color='black', fontsize=9.5)
Extensive input that would have to be asked of the user. This includes the position coordinates, the actual text box, type of alignment.
The only way I know how to collect this info would be to create a Qdialog window prompting for all these inputs, which would be too cumbersome.
User doesn't have much control over being able to freely position the textbox and would have to know exact decimals to position the text box on the figure.
This is incredibly inefficient and inflexible. I want a way for the user to EASILY create these notes on the plot figure.
TLDR: Is there any way to develop a simple drag and create textbox option on a plot figure?
I'm not sure if this is what your looking for, but i found this similar example online. It doesn't allow for user to create a textbox, but adds annotations to the figure and allows you to move them around.
here's the link
http://scipy-cookbook.readthedocs.io/items/Matplotlib_Drag_n_Drop_Text_Example.html
Related
What I'm looking to do is have a pair of 3D figures side by side.
In matplotlib, I was able to create these subplots like so:
ax1 = fig.add_subplot(121, projection='3d')
I'm trying to use Mayavi for my 3D plotting here, because it solves some other problems I'm having, but I can't seem to find a way to plot two figures side-by-side.
Is this even possible?
Every mayavi actor has position/origin/orientation attributes, which you can set to move them to different parts of the scene. You can also add multiple axes and tailor both the ranges over which they display and the labels output. Using a combination of these, you can solve your question; but no, I don't know of a simple "subplot" mechanism.
Other possible alternatives
mlab.screenshot() on separate scenes and combine them in a custom view.
use the canvas frontend inside your own screen widgets, with each side-by-side widget showing a different scene.
So I don't really have any code to show as it's a very large script I have currently. Having said that I will try and add a simple example shortly.
Basically lets say I have two frames in wxpython, each containing a single panel with a matplotlib canvas. Lets call these canvases graph1 and graph2.
So I know how to plot directly into graph1, using standard methods.
I was wondering if there is any way I could change the location of graph1 into that of graph2, i.e. move the plot to the second frame (window).
Basically I am trying to implement a full screen option for the user, which upon clicking a graph will maximise it into the second frame. I am hoping I can do this just by changing the references rather than re-drawing etc. as I want it to keep the original state of the graph when it maximises.
I have been looking for a way to be able to select which series are visible on a plot, after a plot is created.
I need this as i often have plots with many series. they are too many to plot at the same time, and i need to quickly and interactively select which series are visible. Ideally there will be a window with a list of series in the plot and checkboxes, where the series with the checked checkbox is visible.
Does anyone know if this has been already implemented somewhere?, if not then can someone guide me of how can i do it myself?
Thanks!
Omar
It all depends on how much effort you are willing to do and what the exact requirements are, but you can bet it has already been implemented somewhere :-)
If the aim is mainly to not clutter the image, it may be sufficient to use the built-in capabilities; you can find relevant code in the matplotlib examples library:
http://matplotlib.org/examples/event_handling/legend_picking.html
http://matplotlib.org/examples/widgets/check_buttons.html
If you really want to have a UI, so you can guard the performance by limiting the amount of plots / data, you would typically use a GUI toolbox such as GTK, QT or WX. Look here for some articles and example code:
http://eli.thegreenplace.net/2009/05/23/more-pyqt-plotting-demos/
A list with checkboxes will be fine if you have a few plots or less, but for more plots a popup menu would probably be better. I am not sure whether either of these is possible with matplotlib though.
The way I implemented this once was to use a slider to select the plot from a list - basically you use the slider to set the index of the series that should be shown. I had a few hundred series per dataset, so it was a good way to quickly glance through them.
My code for setting this up was roughly like this:
fig = pyplot.figure()
slax = self.fig.add_axes((0.1,0.05,0.35,0.05))
sl = matplotlib.widgets.Slider(slax, "Trace #", 0, len(plotlist), valinit=0.0)
def update_trace():
ax.clear()
tracenum = int(np.floor(sl.val))
ax.plot(plotlist[tracenum])
fig.canvas.draw()
sl.on_changed(update_trace)
ax = self.fig.add_axes((0.6, 0.2, 0.35, 0.7))
fig.add_subplot(axes=self.traceax)
update_trace()
Here's an example:
Now that plot.ly has opened sourced their libraries, it is a really good choice for interactive plots in python. See for example: https://plot.ly/python/legend/#legend-names. You can click on the legend traces and select/deselect traces.
If you want to embed in an Ipython/Jupyter Notebook, that is also straightforward: https://plot.ly/ipython-notebooks/gallery/
I'm writing a program in Python. The first thing that happens is a window is displayed (I'm using wxPython) that has some buttons and text. When the user performs some actions, a plot is displayed in its own window. This plot is made with R, using rpy2. The problem is that the plot usually pops up on top of the main window, so the user has to move the plot to see the main window again. This is a big problem for the user, because he's lazy and good-for-nothing. He wants the plot to simply appear somewhere else, so he can see the main window and the plot at the same time, without having to lift a finger.
Two potential solutions to my problem are:
(1) display the plot within a wxPython frame (which I think I could control the location of), or
(2) be able to specify where on the screen the plot window appears.
I can't figure out how to do either.
Plot to a graphics file using jpeg(), png() or another device, then display that file on your wxWidget.
There are few lines about this in the documentation:
http://rpy.sourceforge.net/rpy2/doc-2.2/html/graphics.html
By default R plots to the "interactive" plotting device (X11). Specifying a non-interactive file-based device (jpeg, png, pdf - pdf being probably easier if rescaling or zooming is wished).
There is a very experimental feature in rpy2-2.2.0dev that would let one implement relatively easily new devices (e.g., plot into matplotlib canvases, or wxWindows panels), but unfortunately this is not complete, not documented, and probably not fully working.
I while ago, I was comparing the output of two functions using python and matplotlib. The result was as good as simple, since plotting with matplotlib is quite easy: I just plotted two arrays with different markers. Piece of cake.
Now I find myself with the same problem, but now I have a lot of pair of curves to compare. I initially tried plotting everything with different colors and markers. This did not satisfy me since the ranges of each curve are not quite the same. In addition to this, I quickly ran out of colors and markers that were sufficiently different to identify (RGBCMYK, after that, custom colors resemble any of the previous ones).
I also tried subplotting each pair of curves, obtaining a window with many plots. Too crowded.
I tried one window per plot, too many windows.
So I was just wondering if there is any existing widget or if you have any suggestion (or a different idea) to accomplish this:
I want to see a pair of curves and then select easily the next one, with a slidebar, button, mouse scroll, or any other widget or event. By changing curves, the previous one should disappear, the legend should change and its axis as well.
Well I managed to do it with an event handler for mouse clicks. I will change it for something more useful, but I post my solution anyway.
import matplotlib.pyplot as plt
figure = plt.figure()
# plotting
plt.plot([1,2,3],[10,20,30],'bo-')
plt.grid()
plt.legend()
def on_press(event):
print 'you pressed', event.button, event.xdata, event.ydata
event.canvas.figure.clear()
# select new curves to plot, in this example [1,2,3] [0,0,0]
event.canvas.figure.gca().plot([1,2,3],[0,0,0], 'ro-')
event.canvas.figure.gca().grid()
event.canvas.figure.gca().legend()
event.canvas.draw()
figure.canvas.mpl_connect('button_press_event', on_press)
Sounds like you want to embed matplotlib in an application. There are some resources available for that:
user interface examples
Embedding in WX
I really like using traits. If you follow the tutorial Writing a graphical application for scientific programming , you should be able to do what you want. The tutorial shows how to interact with a matplotlib graph using graphical user interface.