Add labels to real-time signal plotting with Vispy - python

I am not familiar enough with Vispy. I did adapt this example for my use case, but I don't know how to modify it further to include the missing features.
I am trying to plot in real-time N-channels of data at the same scale. Using pyqtgraph, the interface looks like this:
And with vispy:
My goal is to match both backends, step by step. The difference for now are:
The order in Vispy is reversed (plot at the top on Vispy is the plot at the bottom on pyqtgraph)
Lack channel names
Lack Y-axis label
Lack X-Axis and X-Axis label
Lack of headroom top/bottom
I do not know how to solve any of those, how to further improve this backend. Any tips, guidance towards the correct, best function to use for this would be very helpful.
I was looking into visual.text, but the positioning seemed difficult. I did not know how to match the label in front of one of the plot.

Related

How to draw a plot by using python

I am implementing the Fastdtw algorithm to find the optimal path to align two time-series data. I hope to output a plot like this:
However, I've never tried such kind of plot before. I guess maybe I need to use the imshow() function in matplotlib, but I don't know how to draw the extra trajectory in the plot.
I wish somebody coould give a similar example about drawing like such style. I will modify the parameters by myself.

Creating a packed bubble / scatter plot in python (jitter based on size to avoid overlapping)

I have come across a number of plots (end of page) that are very similar to scatter / swarm plots which jitter the y-axis in order avoid overlapping dots / bubbles.
How can I get the y values (ideally in an array) based on a given set of x and z values (dot sizes)?
I found the python circlify library but it's not quite what I am looking for.
Example of what I am trying to create
EDIT: For this project I need to be able to output the x, y and z values so that they can be plotted in the user's tool of choice. Therefore I am more interested in solutions that generate the y-coords rather than the actual plot.
Answer:
What you describe in your text is known as a swarm plot (or beeswarm plot) and there are python implementations of these (esp see seaborn), but also, eg, in R. That is, these plots allow adjustment of the y-position of each data point so they don't overlap, but otherwise are closely packed.
Seaborn swarm plot:
Discussion:
But the plots that you show aren't standard swarm plots (which almost always have the weird looking "arms"), but instead seem to be driven by some type of physics engine which allows for motion along x as well as y, which produces the well packed structures you see in the plots (eg, like a water drop on a spiders web).
That is, in the plot above, by imagining moving points only along the vertical axis so that it packs better, you can see that, for the most part, you can't really do it. (Honestly, maybe the data shown could be packed a bit better, but not dramatically so -- eg, the first arm from the left couldn't be improved, and if any of them could, it's only by moving one or two points inward). Instead, to get the plot like you show, you'll need some motion in x, like would be given by some type of physics engine, which hopefully is holding x close to its original value, but also allows for some variation. But that's a trade-off that needs to be decided on a data level, not a programming level.
For example, here's a plotting library, RAWGraphs, which produces a compact beeswarm plot like the Politico graphs in the question:
But critically, they give the warning:
"It’s important to keep in mind that a Beeswarm plot uses forces to avoid collision between the single elements of the visual model. While this helps to see all the circles in the visualization, it also creates some cases where circles are not placed in the exact position they should be on the linear scale of the X Axis."
Or, similarly, in notes from this this D3 package: "Other implementations use force layout, but the force layout simulation naturally tries to reach its equilibrium by pushing data points along both axes, which can be disruptive to the ordering of the data." And here's a nice demo based on D3 force layout where sliders adjust the relative forces pulling the points to their correct values.
Therefore, this plot is a compromise between a swarm plot and a violin plot (which shows a smoothed average for the distribution envelope), but both of those plots give an honest representation of the data, and in these plots, these closely packed plots representation comes at a cost of a misrepresentation of the x-position of the individual data points. Their advantage seems to be that you can color and click on the individual points (where, if you wanted you could give the actual x-data, although that's not done in the linked plots).
Seaborn violin plot:
Personally, I'm really hesitant to misrepresent the data in some unknown way (that's the outcome of a physics engine calculation but not obvious to the reader). Maybe a better compromise would be a violin filled with non-circular patches, or something like a Raincloud plot.
I created an Observable notebook to calculate the y values of a beeswarm plot with variable-sized circles. The image below gives an example of the results.
If you need to use the JavaScript code in a script, it should be straightforward to copy and paste the code for the AccurateBeeswarm class.
The algorithm simply places the points one by one, as close as possible to the x=0 line while avoiding overlaps. There are also options to add a little randomness to improve the appearance. x values are never altered; this is the one big advantage of this approach over force-directed algorithms such as the one used by RAWGraphs.

Highlighting many ranges on an axis of a Bokeh plot?

I have a scatter plot of data and would like to highlight certain ranges of the x-axis. When the number ranges to highlight are relatively small, using BoxAnnotation works well. However, I'm trying to make many adjacent highlightings (with different opacity). With many adjacent BoxAnnotations, zoomed out, the boxes slightly overlap, creating lines. Additionally, thousands of BoxAnnotations takes a long time to generate and does not run smoothly when interacting with the plot.
To be more specific about my case, I have some temporal data and a predictive model detecting the probability of some event occurring in the data. I want each segment to be highlighted with an opacity given by the probability that an event is occurring at that point in time. However, my current BoxAnnotation approach results in artificial lines from overlap of boxes when zoomed out (they disappear when zooming in on a region), and slow responsiveness of the interactive plot.
Is there a way to accomplish something similar to this without the artifacts and with a smoother experience?
Current method:
source = ColumnDataSource(data=data_frame)
figure_ = figure(x_axis_label='Time', y_axis_label='Intensity')
for index in range(data_frame.shape[0] - 1):
figure_.add_layout(
BoxAnnotation(left=data_frame['time'].values[index], right=data_frame['time'].values[index + 1],
fill_alpha=data_frame['prediction'].values[index], fill_color='red', line_alpha=0)
)
figure_.circle(x='time', y='intensity', source=source)
show(figure_)
Example of artificial lines when there are too many small adjacent BoxAnnotations:
When zooming on the x-axis, the lines disappear:
There's probably not any way to salvage this exact approach. The artifacts are due to the functioning of the underlying raster HTML canvas, and here's not anything that can be one about that. And any slowness is due to the fact that this kind of use of BoxAnnotation (with so very many individual instances) is not at all what was envisioned, and it is simply not optimized to show hundreds of instances the way e.g. scatter glyphs are. You are trying to use box annotations to construct a sort of translucent heat map, and that is not a good fit for it, for the reasons above.
You could potentially overcome slowness by using a single rect or vbar glyph that draws all the boxes at once in a vectorized way. But that won't alleviate the compositing issues.
Your best bet is to create a semi-transparent "heatmap" image overlay yourself with a tool or code that can afford better control over the details of rasterization and compositing. I can't really advise you on how to do that in any detail. The Datashader library might be useful for this.

Plotting distribution from sampled data in python

I have two sets of sampled points in 2d space[x ,y], each set represents one class. When I plot all points, it's mess and one can't see anything on it. I need somehow plot distribution of each set (if it's possible on same canvas with different colours, then better). Does anybody know about some good library for it?
Matplotlib is a very good library for that task. You can plot histograms, scatter plots and lot of other things. You just have to know what you want and then you can probably do it with that. I use that for similar tasks a lot.
[UPDATE]
As I said, you can do that with matplotlib. Here is an example from their gallery: http://matplotlib.org/examples/pylab_examples/scatter_hist.html
It's not so pretty as with the answer in the comment of #lejlot, but still correct.

python matplotlib blit to axes or sides of the figure?

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.)

Categories

Resources