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.
Related
I have two issues with my python plot that would be grateful if anyone could help me with:
1- I wonder if it is possible in python to have the option for the plots after display to add horizontal or vertical lines, so that these new lines could be added, moved or deleted without the need to run the code again.
to say it more clearly, I am looking for additional features that adding them does not need to change the code and they only enable me to manually draw on the already plotted image.
2- I want to plot a very large image in the real size, So that I need to add the horizontal and vertical slide bars to be able to scroll up/down or left/right in the plot?
I need to combine these two ability for my project, can someone help me with that?
1- You can't physically draw on it, but you can make a plot in matplotlib interactive as follows:
import matplotlib.pyplot as plt
plt.ion() # turns on interactive mode
fig = plt.figure()
ax = fig.add_subplot()
plt.ylim(-10, 10)
plt.xlim(0, 10)
while True:
plt.axhline(float(input("number")))
fig.canvas.draw()
fig.canvas.flush_events() # draws
This program allows you to create horizontal lines based on user input.
I think you can solve 2 with tkinter, but that would be pretty difficult. There might also an easier way. See this stack overflow question for an example of an interactive plot in tkinter. I believe this plot can be made bigger and scrollable, but I am not sure.
I'm new to plotly/plotly express and i'm having a really hard time finding any working example other than the documentation examples for the library (which are really basic and standard).
I have, let's say a scatter plot, in plotly express:
fig = px.scatter(any_random_data)
And i want to add to that plot an image in a fixed (x,y) position, but i don't know (and can't find!) if there is any kind of method for that.
I've seen there is an add_trace() method to add traces to the plot (i guess), is there any similar function for adding images? (Like add_image() or something)
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
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.
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/