I'm experimenting with Bokeh server. I have a document with three figures and I'm trying to update two of them depending on the selection I perform on the third. The number of lines to plot in the two figures changes every time.
If I could use multi_line, this would be trivial: I would change the xs and ys in the data_source of the multi_line.
Alas, I need to use multiple scatter plots because multi_line does not support hover and I need it.
So, what I would like to accomplish is to clear the two plots every time I select something in the third, and display the scatter plots corresponding to the new selection.
There are a few possible workarounds, of course (appending scatter points to have a single GlyphRenderer with all scatter plots together, for example, but this would mean using very clunky ways to send the right hover message...). But if it was possible to just clear and update single figures, everything would be cleaner. I couldn't find anything in the docs, however.
I have read the thread you created on the mailing list and this other thread where Bryan says:
Technically, glyph renderers are stored in the .renderers property of
Plots, but I would not recommend rooting around there by hand.
Specifically the "Continuous Updating" notebook I linked earlier has
an example of updating both the data and appearance of an existing
glyph using python and push_notebook. There is not any easy way to remove glyphs at the moment,
other options would be:
recreate a new plot
set the glyph to be invisble
update the glyphs data
So it seems they are the only solutions at the moment
Related
I am working on a figure where space is constrained and I want to combine my legend using parentheticals as in this picture.
At the moment I just make some parenthesis in my labels for the plot and then edit the figure in Inkscape later on to add the missing markers, but this makes iterating on the plot more expensive in terms of time before having a usable figure. Is there any way to hack matplotlib into doing something similar without having to go through an external program?
I would like to know if there is a way to combined several figures created with matplotlib in one unique figure.
Most of the existing topics are related to multiple plots within one figure. But here, I have several functions which all create one elaborated figure (not just a plot, the figure itself is a multiple plot with texts, title, legends,...)
So instead of just doing the layout of those several figures using a software like Word, is there a way to directly combined all my figures in one unique figure under python ?
Thank you in advance !
The concept of figure in matplotlib does not allow to have a figure inside a figure. The figure is the canvas for other artists, like axes. You may of course add as many axes to a figure as you like. So for example instead of one figure with 4 axes and another figure with 6 axes, you can create a figure with 10 axes.
A good choice may be to use the gridspec, as detailed on the respecive matplotlib page.
After additional researches, it seems my problem has no easy solution within Matplotlib itself. Multiple figures layout needs external post-processing of plots.
For those having the same problem, here is an interesting link :
Publication-quality figures with matplotlib and svgutils
I'm writing a web interface for a database of genes values of some experiments with CGI in Python and I want to draw a graph for the data queried. I'm using matplotlib.pyplot, draw a graph, save it, and perform it on the web page. But usually there are many experiments queried hence there are a lot of values. Sometimes I want to know which experiment does one value belong to because it's a big value, whereas it's hard to identify because the picture is small in size. The names of the experiments are long strings so that it will mess the x axis if I put all the experiment names on the x axis.
So I wonder if there is a way to draw a graph that can interact with users, i.e. if I point my mouse to some part on the graph, there would be one small window appears and tells me the exact value and what is the experiment name here. And the most important is, I can use this function when I put the graph on the web page.
Thank you.
What you want is basically D3.js rendering of your plots. As far as I know, there are currently three great ways of achieving this, all under rapid development:
MPLD3 for creating graphs with Matplotlib and serving them as interactive web graphics (see examples in Jake's blog post).
Plotly where you can either generate the plots directly via Plotly or from Matplotlib figures (e.g. using matplotlylib) and have them served by Plotly.
Bokeh if you do not mind moving away from Matplotlib.
I am writing a bunch of scripts and functions for processing astronomical data. I have a set of galaxies, for which I want to plot some different properties in a 3-panel plot. I have an example of the layout here:
Now, this is not a problem. But sometimes, I want to create this plot just for a single galaxy. In other cases, I want to make a larger plot consisting of subplots that each are made up of the three+pane structure, like this mockup:
For the sake of modularity and reusability of my code, I would like to do something to the effect of just letting my function return a matplotlib.figure.Figure object and then let the caller - function or interactive session - decide whether to show() or savefig the object or embed it in a larger figure. But I cannot seem to find any hints of this in the documentation or elsewhere, it doesn't seem to be something people do that often.
Any suggestions as to what would be the best road to take? I have speculated whether using axes_grid would be the solution, but it doesn't seem quite clean and caller-agnostic to me. Any suggestions?
The best solution is to separate the figure layout logic from the plotting logic. Write your plotting code something like this:
def three_panel_plot(data, ploting_args, ax1, ax2, ax3):
# what you do to plot
So now the code that turns data -> images takes as arguments the data and where it should plot that data too.
If you want to do just one, it's easy, if you want to do a 3x3 grid, you just need to generate the layout and then loop over the axes sets + data.
The way you are suggesting (returning an object out of your plotting routine) would be very hard in matplotlib, the internals are too connected.
I'm trying to refresh some plots that I have within a gui everytime I go once through a fitting procedure. Also, these plots are within a framw which can be resized, so the axes and labels etc need to be redrawn after the resizing. So was wondering if anyone knew how to update the sides of a figure using something like plot.figure.canvas.copy_from_bbox and blit. This appears to only copy and blit the background of the graphing area (where the lines are being drawn) and not to the sides of the graph or figure (where the labels and ticks are). I have been trying to get my graphs to update by trial and error and reading mpl documentation, but so far my code has jst become horrendously complex with things like self.this_plot.canvas_of_plot..etc.etc.. .plot.figure.canvas.copy_from_bbox... which is probably far too convoluted.
I know that my language might be a little off but I've been trying to read through the matplotlb documentation and the differences between Figure, canvas, graph, plot, figure.Figure, etc. are starting to evade me. So my first and foremost question would be:
1 - How do you update the ticks and labels around a matplotlib plot.
and secondly, since I would like to have a better grasp on what the answer to this question,
2 - What is the difference between a plot, figure, canvas, etc. in regards to the area which they cover in the GUI.
Thank you very much for the help.
All this can certainly be rather confusing at first!
To begin with, if you're chaining the ticks, etc, there isn't much point in using blitting. Blitting is just a way to avoid re-drawing everything if only some things are changing. If everything is changing, there's no point in using blitting. Just re-draw the plot.
Basically, you just want fig.canvas.draw() or plt.draw()
At any rate, to answer your first question, in most cases you won't need to update them manually. If you change the axis limits, they'll update themselves. You're running into problems because you're blitting just the inside of the axes instead of redrawing the plot.
As for your second question, a good, detailed overview is the Artist Tutorial of the Matplotlib User's Guide.
In a nutshell, there are two separate layers. One deals with grouping things into the parts that you'll worry about when plotting (e.g. the figure, axes, axis, lines, etc) and another that deals with rendering and drawing in general (the canvas and renderer).
Anything you can see in a matplotlib plot is an Artist. (E.g. text, a line, the axes, and even the figure itself.) An artist a) knows how to draw itself, and b) can contain other artists.
For an artist to draw itself, it uses the renderer (a backend-specific module that you'll almost never touch directly) to draw on a FigureCanvas a.k.a. "canvas" (an abstraction around either a vector-based page or a pixel buffer). To draw everything in a figure, you call canvas.draw().
Because artists can be groups of other artists, there's a hierarchy to things. Basically, something like this (obviously, this varies):
Figure
Axes (0-many) (An axes is basically a plot)
Axis (usually two) (x-axis and y-axis)
ticks
ticklabels
axis label
background patch
title, if present
anything you've plotted, e.g. Line2D's
Hopefully that makes things a touch clearer, anyway.
If you really do want to use blitting to update the tick labels, etc, you'll need to grab and restore the full region including them. This region is a bit tricky to get, because it isn't exactly known until after draw-time (rendering text in matplotlib is more complicated than rendering other things due to latex support, etc). You can do it, and I'll be glad to give an example if it's really what you want, but it's typically not going to yield a speed advantage over just drawing everything. (The exception is if you're only updating one subplot in a figure with lots of subplots.)