How to make Matplotlib figures interactive in a Flask application? - python

I am trying to display spectrograms in a Flask application. I use matplotlib for creating the spectrograms and mpld3 for displaying them in an HTML file with the default toolbar.
The problem is that I am not able to zoom into the same region for each spectrogram at the same time.
This is a screenshot of default figure
This is another screenshot that I took after zooming in a little bit on a left top one.
As you can see, all of the y-axes have been changed with the same scale as the left top ones. However, the x-axes of the right top, the left bottom, and the right bottom haven't been changed at all. So what I want to do is to compare those guys with the same scale.
Does anyone have any suggestion such as a better idea to make it possible or maybe the solution for the problem?

Related

Position of y-axis on the right side Python panel (holoviz)

how can I change the position of the y-axis labels to the right side? The standard is of course on the left side, but I want to have it on the right side.
I can’t find anything in the holoviz panel documentation to it.
I tried to derive it from the position settings of the legend. So, I thought p.y_axis_label_text_align = 'right’ could be right. However, it does not work.
Can anybody help me out or has a Python panel example where the y-axis is located on the right side of the chart tile? Thanks in advance.
The answer depends on the package you are using.
Holoviews
If your figure is created with holoviews, please cheack out the holoviews documentation for axis-positions.
In gerneal
.opts(xaxis='top', yaxis='right')
does the trick.
bokeh
If you are using the the figure of bokeh.plotting, then
p = figure(..., y_axis_location="right", ...)
moves the one y-axis to the right.
In case you want to add a new axis, the twin-axis example shows how to add a LinearAxis.

Fix x_axis and fill under curve Bokeh

I am trying to configure my Bokeh plots in Python such that they look a bit nicer. For example, is there a way to fix the maximum zoom out? Such that Bokeh cannot zoom out more than what is specified by the x-axis? E.g. look at bokeh example, and especially "Datetime axes". I would like to fix the axis size so that you cannot zoom out more than the initial x axis is wide.
Another question; is there a way to fill an area under a curve in a specified color? Like in the figure USDSEK. I can provide code, but I don't think it's necessary for the problem at hand.
UPDATED for 2019:
Bokeh now supports "directed areas" (which can also be stacked) see e.g.
https://docs.bokeh.org/en/latest/docs/gallery/stacked_area.html

matplotlib shows different figure than saves from the show() window

I plot rather complex data with matplotlib's imshow(), so I prefer to first visually inspect if it is all right, before saving. So I usually call plt.show(), see if it is fine, and then manually save it with a GUI dialog in the show() window. And everything was always fine, but recently I started getting a weird thing. When I save the figure I get a very wrong picture, though it looks perfectly fine in the matplotlib's interactive window.
If I zoom to a specific location and then save what I see, I get a fine figure.
So, this is the correct one (a small area of the picture, saved with zooming first):
And this one is a zoom into approximately the same area of the figure, after I saved it all:
For some reason pixels in the second one are much bigger! That is vary bad for me - as you can see, it looses a lot of details in there.
Unfortunately, my code is quite complicated and I wasn't able to reproduce it with some randomly generated data. This problem appeared after I started to plot two triangles of the picture separately: I read my two huge data files with np.loadtxt(), get np.triu(data1) and np.tril(data2), mask zeroes, NAs, -inf and +inf and then plot them on the same axes with plt.imshow(data, interpolation='none', origin='lower', extent=extent). I do lot's of other different things to make it nicer, but I guess it doesn't matter, because it all worked like a charm before.
Please, let me know, if you need to know anything else specific from my code, that could be relevant to this problem.
When you save a figure in png/jpg you are forced to rasterize it, convert it to a finite number of pixels. If you want to keep the full resolution, you have a few options:
Use a very high dpi parameter, like 900. Saving the plot will be slow, and many image viewers will take some time to open it, but the information is there and you can always crop it.
Save the image data, the exact numbers you used to make the plot. Whenever you need to inspect it, load it in Matplotlib in interactive mode, navigate to your desired corner, and save it.
Use SVG: it is a vector graphics format, so you are not limited to pixels.
Here is how to use SVG:
import matplotlib
matplotlib.use('SVG')
import matplotlib.pyplot as plt
# Generate the image
plt.imshow(image, interpolation='none')
plt.savefig('output_image')
Edit:
To save a true SVG you need to use the SVG backend from the beginning, which is unfortunately, incompatible with interactive mode. Some backends, like GTKCairo seem to allow both, but the result is still rasterized, not a true SVG.
This may be a bug in matplotlib, at least, to the best of my knowledge, it is not documented.

Matplotlib zooming work in conjunction with wxPython ScrolledWindow

I've got a Matplotlib canvas (FigureCanvasWxAgg) that I'm displaying inside of a wx.ScrolledWindow. The problem is that I'd like to have the default zooming and panning functionality of Matplotlib work in conjunction with the ScrolledWindow, so that when the user zooms the image within the canvas, the ScrolledWindow should become larger to accommodate for the zooming (scrollbars become smaller). Similarly for panning, I'd like the default matplotlib panning tool to work in conjunction with our ScrolledWindow, so that when the user pans the image on the canvas, the ScrolledWindow's scrollbars should move accordingly.
I've been searching for a while now and have not seen anyone even mention if this is possible. Could anyone point me in the right direction?
Thank you for any help/tips.
The problem is that the default Zoom and Pan don't resize the figure, they just change the limits and redraw the plot.
What you want is the Zoom to resize (keeping the same limits) and the Pan to work as in a normal Scrolled window. I have never tried this, fig.set_size_inches(w,h) should do the trick.

How do I control where an R plot is displayed, using python and rpy2?

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.

Categories