python bokeh saving issue and label disappear, and display problem - python

As I am aiming to plot the data into the plot, I encounter 2 problems.
(1) For the Bokeh function, while I am plotting 4 pictures in a row and adding the save as the SVG. Then the browser is shown as figure1. Moreover, as I comment out the code below, it work definitely right as I thought. It's weird.
p1.output_backend = "svg"
export_svgs(p1, filename="./number_like_comment/fig/{}.svg".format(action_str))
(2) For the second question, after I save those files, I realized that the "Label" I put in the plot also disappear. (as figure3).
Thanks so much for reading through. This question bother me quite a long time.

I guess that the data (on the x-axis) starts at 0, and on a logaxis for some reason the svg renderer doesn't like that and refuses to draw the entire line. The canvas renderer (used for the interactive plots) only refuses to draw the line-segment going from or to 0.
If you want to keep the logarithmic axis, you can either remove the 0 values or replace them by something which can be displayed in a logarithmic scale (e.g. 0.1) and then fixate the x-axis.

Related

Jupyter: Seaborn pairplot difficult to set graph dimensions for?

I was trying to create a bivariate scatterplot of each variable against every other that are in a dataframe, and I found sns.pairplot() was exactly what I needed.
However, no matter what I do (and I have tried all of the advice found in this question), the plots keep coming out too spread out, as well as in general too big. In the picture below, only the first two rows and four columns out of 12 variables display on my entire screen.
I have found out that my use of
%config InlineBackend.figure_format = 'svg'
to create non-blurry graphs on my high-ppi screen is partially at blame, as without it, I instead get this graph, which fits perfectly on my screen, but is now too small and I would prefer to scroll slightly around while having a bigger pic.
(note: the additional options below have no effect)
How can I make the grid of plots customizable in its overall size as well as spacing? As it stands, no options work, and one graphics backend (the default one) produces too small graphs, while the 'svg' backend produces too large ones.
EDIT: Editing sns.set(rc={'figure.figsize':(x,y)}) or the height/ aspect options improve nothing: the former produces no change, while the latter two change how big the individual plots are (with height=1 making them indecipherable), but the overall "grid" is still as bulky and overly large as before.
Essentially you are asking how to display the figure in its original size in a jupyter notebook.
That translates into how to add scrollbars if it exceeds the room it's given by the layout of the output cell.
I think for the horizontal direction this can be done as follows. However for the vertical direction this does not seem to work.
%matplotlib inline
# Cell2
from IPython.display import display, HTML
CSS = """div.output_area img {max-width:None !important;max-height: None !important";}"""
display(HTML('<style>{}</style>'.format(CSS)))
# Cell3
import matplotlib.pyplot as plt
fig, ax = plt.subplots(ncols=8, figsize=(20,10))

matplotlib plot line with color controlled by a third variable, ask for better solution

I know there are several questions about this in stackoverflow, but the current solution still has some problems.
I am following the solution provided by http://nbviewer.ipython.org/github/dpsanders/matplotlib-examples/blob/master/colorline.ipynb using LineCollection.
Actually it works. But when I save the figure into PDF file. After zooming in, it looks not very good. The size of PDF file is hundreds of times of simply plot without changing color. I understand why it looks like this. Is there any idea to plot the color-line smoother?

How to sit the size for seaborn pairplot chart?

I am trying to draw an sns.pairplot with one value in x_axis but multiple values in y_axis
This is what I got. All the figure in one row. Does Anyone know how I can get a bigger plot? or in multiple columns?
The chart is here:
As per the comment to your question, the reason that the plot is small, is because it does not fit into the Jupyter Notebook output cell. Try right clicking and opening in a new tab or saving it to a file.
If you want display the figure within a Notebook, you can make several calls to sns.pairplot with a subset of columns each time. You could also use sns.FaceGrid with plt.scatter for more granular control over what is plotted where.

How to prevent Matplotlib from clipping away my axis labels?

I'm preparing some plots for a scientific paper, which need to be wide and short in order to fit into the page limit. However, when I save them as pdf, the x axis labels are missing, because (I think) they're outside the bounding box.
Putting the following into an iPython notebook reproduces the problem.
%pylab inline
pylab.rcParams['figure.figsize'] = (8.0, 2.0)
plot([1,5,2,4,6,2,1])
xlabel("$x$")
ylabel("$y$")
savefig("test.pdf")
The resulting pdf file looks like this:
How can I change the bounding box of the pdf file? Ideally I'd like a solution that "does it properly", i.e. automatically adjusts the size so that everything fits neatly, including getting rid of that unnecessary space to the left and right - but I'm in a hurry, so I'll settle for any way to change the bounding box, and I'll guess numbers until it looks right if I have to.
After a spot of Googling, I found an answer: you can give bbox_inches='tight' to the savefig command and it will automatically adjust the bounding box to the size of the contents:
%pylab inline
pylab.rcParams['figure.figsize'] = (8.0, 2.0)
plot([1,5,2,4,6,2,1])
xlabel("$x$")
ylabel("$y$")
savefig("test.pdf",bbox_inches='tight')
Those are some tight inches, I guess.
Note that this is slightly different from Ffisegydd's answer, since it adjusts the bounding box to the plot, rather than changing the plot to fit the bounding box. (But both are fine for my purposes.)
You can use plt.tight_layout() to have matplotlib adjust the layout of your plot. tight_layout() will automatically adjust the dimensions, and can also be used when you have (for example) overlapping labels/ticks/etc.
%pylab inline
pylab.rcParams['figure.figsize'] = (8.0, 2.0)
plot([1,5,2,4,6,2,1])
xlabel("$x$")
ylabel("$y$")
tight_layout()
savefig("test.pdf")
Here is a .png of the output (can't upload pdfs to SO but I've checked it and it works the same way for a pdf).
If you are preparing the plot for a scientific paper, I suggest to do the 'clipping' by yourself,
using
plt.subplots_adjust(left,right,bottom,top,..)
after the creation of the figure and before saving it. If you are running from an ipython console you can also call subplots_adjust after the generation of the figure, and tune the margins by trial and error. Some backends (I think at least the Qt backend) also expose a GUI for this feature.
Doing this by hand takes time, but most times provides a more precise result, especially with Latex rendering in my experience.
This is the only option whenever you have to stack vertically or horizontally two figures (with a package like subfigure for example), as tight_layout will not guarantee the same margins in the two figures, and the axis will result misaligned in the paper.
This is a nice link on using matplotlib for publications, covering for example how to set the figure width to match the journal column width.

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