SVG rendering issues using iPython inline plots - python

when I use inline plots in iPython (QtConsole), the first plot looks (more or less) fine, but then it gets weirder and weirder. When I plot something several times (so plot, see it displayed, plot again, see output etc.), it looks like it is being overlaid with the skewed previous picture. So after plotting a diagonal line (x=y) 4 times in a row I get something like this
If i right click and export it as svg everything looks good
(Exported PNG picture remains wrecked as the first one).
I guess the problem is similar to https://github.com/ipython/ipython/issues/1866, but I didn't got the upshot of the discussion (it got too technical and complicated for me to follow).
Is there any solution or work around for this issue?
I'm using
python 2.7
matplotlib 1.4.1
IPython 2.1.0
Here is a working example:
%matplotlib inline
% config InlineBackend.figure_format = 'svg'
import matplotlib.pyplot as plt
a=range(10)
fig,ax=plt.subplots()
ax.plot(a,a)
ax.axis('off')
if you remove plt.axis('off') line, weird things happen only outside of the axis box.
P.S. Originally I encountered this problem in connection with drawing graphs with networkx. If I use draw from networkx this problem does not occur. If I use draw_networkx, same as described above happens. That might point to the core of the problem... I'm trying to figure out what line of code makes one work better than the other...

After tinkering around with the draw and draw_networkx functions from networkx module, I found the workaround which makes the difference between draw and draw_networkx in this case.
Adding fig.set_facecolor('w') overlays whatever is in the background, so the new plots are started with a white sheet (but not a blank one, I guess).
So new working example is:
%matplotlib inline
% config InlineBackend.figure_format = 'svg'
import matplotlib.pyplot as plt
a=range(10)
fig,ax=plt.subplots()
fig.set_facecolor('w')
ax.plot(a,a)
ax.axis('off')

Related

matplotlib legend performance issue

I am using Jupyter-notebook with python 3.6.2 and matplotlib to plot some data.
When I plot my data, I want to add a legend to the plot (basically to know which line is which)
However calling plt.legend takes a lot of time (almost as much as the plot itself, which to my understanding should just be instant).
Minimal toy problem that reproduces the issue:
import numpy as np
import matplotlib.pyplot as plt
# Toy useless data (one milion x 4)
my_data = np.random.rand(1000000,4)
plt.plot(my_data)
#plt.legend(['A','C','G','T'])
plt.show()
The data here is just random and useless, but it reproduces my problem:
If I uncomment the plt.legend line, the run takes almost double the time
Why? Shouldn't the legend just look at the plot, see that 4 plots have been made, and draw a box assigning each color to the corresponding string?
Why is a simple legend taking so much time?
Am I missing something?
Replicating the answer by #bnaecker, such that this question is answered:
By default, the legend will be placed in the "best" location, which requires computing how many points from each line are inside a potential legend box. If there are many points, this can take a while. Drawing is much faster when specifying a location other than "best", e.g. plt.legend(loc=3).

Python- Connecting Lines with plot_date in Matplotlib

I am using matplotlib to graph out some data in which takes time over a time, therefore I have to use plot_date in order to plot my lines. But for some reason Plot_Date and Plot have completely different formatting as far as connecting lines.
Here is what It looks like when using plot(x,y)
Using plot(x,y,'bo') or plot_date(x,y,'bo')
Plot_date(x,y) looks like that ^^ too.
and using plot_date(x,y,'bo-')
How do I make it so that the result of plot_date looks like the first picture? I have looked all over the Matplotlib website and couldn't find anything.
Thanks in advance
Upon further investigation I found that in order to display a solid line without dots, I needed to use the line style 'b-', making the code plot_date(x,y,'b-').
If you want to have the markers connected with the lines, you can also use
plt.plot_date(y,x,linestyle='solid')
So the complete code for the beginners would be:
from matplotlib import pyplot as plt
plt.plot_date(y,x,linestyle='solid')
plt.show()
Do not forget you need to have matplotlib installed first. For that you need to open command line and write:
pip install matplotlib

Sloppy SVG generated by matplotlib resulting on poor clipping of datapoint drawing in figures

Figures that I create with matplotlib do not properly clip points to the figure axes when rendered, but instead draw additional points, even though such figures look fine in some viewers.
For example (following an example from the documentation) using
import matplotlib
matplotlib.use('SVG')
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.add_subplot(111)
x, y = 12*np.random.rand(2, 1000)
ax.set(xlim=[2,10])
ax.plot(x, y, 'go') # plot some data in data coordinates
circ = patches.Circle((0.5, 0.5), 0.25, transform=ax.transAxes,
facecolor='yellow', alpha=0.5)
ax.add_patch(circ)
plt.savefig()
I seem, when viewed for example in OS X Preview, to get
but when I view it in other editors, such as iDraw I get a mess (where, weirdly, there is a combination of correct clipping of edge points, failed clipping of points outside the axes, and clipping of the canvass at a point that does not correspond to either the axes or the range of data):
I'm not experienced with SVG, but those I've asked tell me that
I looked at the SVG file and didn't like what I saw. Characters are
flattened, and definition sections are scattered throughout the file
instead of being at the top; some defs are inside graphics constructs.
There's a lot of cruft. It turns out the definition of the clip-path
is at the very end of the svg file -- after all the uses ...
How can I get matplotlob to generate SVG that does not have these issues? I know that I can edit the SVG, but I have no idea how, and doing so defeats the purpose and I hope that it is not necessary to add a "by hand" step to my workflow.
I'm interested in understanding what the cause of the sloppy SVG generated by matplotlib is: whether it's something that can be avoided by coding a bit differently (though not, clearly, by simply checking whether every data point is in range), or whether it's a bug in matplotlib (or perhaps whether it's just a problem with ambiguities in the SVG standard). The goal is getting matplotlob to generate SVG that is not buggy.
This is probably related to a know issue and also comes up in pdfs (matplotlib data accessible outside of xlim range)
See Issues #2488 and #2423 (the later which includes a proposed fix for pdf). It is milestoned for 1.4.

How to make the matplotlib subscript and special characters?

I want to make a subscript for the axis label of my plot plotted using matplotlib. I have the following script snapshot:
import matplotlib.pylab as plt
plt.ylabel(r'$A^{2}$')
I have 2 questions:
In the plot, the subscript "2" seems occupying a whole word length in stead of half, which make the plot a little bit weird. How to make the subscript smaller (both in size and the length span)?
How to display "angstroms" (the length unit of 10^-10m) instead of A?
Thanks!
What version of matplotlib are you using? In my version the superscript seems fine (to me).
Im using python 2.6.5 and matplotlib 1.1.0
Use \AA for angstram --> plt.ylabel("$\AA$").
The circle is a bit small, though.
If it's available to you, try using TeX to render your text.
from matplotlib import rc
rc('text', usetex=True)
#the rest of your plotting code here
This should make your fonts and text look a whole lot better.
For more details on matplotlib's TeX rendering capabilities, look here: http://matplotlib.sourceforge.net/users/usetex.html

matplotlib draw showing nothing

I'm using python's matplotlib to do some contours using contour and contourf functions. They all work fine when using show, but when I try to use draw() inside a method, I get the matplotlib window but not graph. The show() call will be done much later on the code and in a different method, and I would like to show one graph at the moment when it's done with draw(), not having to wait until the much later show(). What I'm doing wrong?
Thanks.
Have you turned interactive mode on using ion()? The following works for me on OSX, using the Tk backend and running from the shell's command line:
import matplotlib.pyplot as plt
plt.ion()
plt.figure()
for i in range(10):
plt.plot([i], [i], 'o')
plt.draw()
raw_input("done >>")
That is, as it does each loop, you see the plot change (i.e., it gets redrawn) as each point is added. Here, btw, if I instead call plt.ioff(), I don't see the figure or any updates.
IIRC ,You should be able call fig.show() multiple times. Also, check out using ipython (ipython -pylab) and http://matplotlib.sourceforge.net/users/shell.html

Categories