I've got a problem with saving figures with matplotlib and the pgf-backend.
If I have a plot in which the axis limits (e.g. X: [20,70]; Y: [0,-50]) are much lower than the datapoints with the highest X- and Y-values (lowest datapoint: [0,0]; highest datapoint: [150000,-200000]) there's always the following error:
File "<>", line 816, in exportGraphs2
File "C:\Python26\lib\site-packages\matplotlib\pyplot.py", line 561, in savefig
return fig.savefig(*args, **kwargs)
File "C:\Python26\lib\site-packages\matplotlib\figure.py", line 1421, in savefig
self.canvas.print_figure(*args, **kwargs)
File "C:\Python26\lib\site-packages\matplotlib\backend_bases.py", line 2220, in print_figure
**kwargs)
File "C:\Python26\lib\site-packages\matplotlib\backends\backend_pgf.py", line 882, in print_pdf
self._print_pdf_to_fh(fh, *args, **kwargs)
File "C:\Python26\lib\site-packages\matplotlib\backends\backend_pgf.py", line 858, in _print_pdf_to_fh
check_output(cmdargs, stderr=subprocess.STDOUT, cwd=tmpdir)
File "C:\Python26\lib\site-packages\matplotlib\compat\subprocess.py", line 69, in _check_output
raise subprocess.CalledProcessError(retcode, cmd, output=output)
TypeError
:
__init__() got an unexpected keyword argument 'output'
However, if the axis limits are larger or slightly smaller than the largest values of the datapoints everything works fine.
Does anyone have an idea what the problem might be?
Edit:
Here is a part of my code. Since it's quite complex due to reading data from QTIPlot it's just a short snippet.
import matplotlib as mpl
import sys
sys.path.append("..")
mpl.use('pgf')
latex_preamble = {"text.usetex": True,
"pgf.rcfonts": False,
"pgf.preamble": [r"\usepackage{cmbright}",
r"\usepackage{siunitx}",
r"\usepackage{fontspec}",
r"\setmainfont{Calibri}",
r"\usepackage[utf8x]{inputenc}",
r"\usepackage{textgreek}"]}
mpl.rcParams.update(latex_preamble)
import matplotlib.pyplot as plt
mpl.rcParams.update({'font.size': 24})
x = [186691.98079420399, 94747.037718184903, 43238.854190494698, 19067.6709222838, 8804.8960840724703, 4616.3273881164196, 2784.39307777148, 1924.44569810138, 1421.6244001381001, 1044.0988528353901, 738.32026028954704, 499.78345554987698, 325.91902800532, 208.07599600125701, 136.48397798235101, 97.188999849599597, 77.189874321047498, 66.814364230185305, 61.930218121218097, 58.897007608510897, 57.004014967900098, 55.406903357827098, 54.041568494235101, 52.802043730081699, 51.759023715688997, 50.777510655714799, 49.815484593681198, 48.961058456802903, 48.191611656054903, 47.4882902162026, 46.848714837688902, 46.190288085990197, 45.3774348340838, 44.4693505256935, 43.434754403205901, 42.220754480990998, 40.854413497723201, 39.357546952524302, 37.878908712040399, 36.491255819384499, 35.284755433638502, 34.2610953105862, 33.420298363499299, 32.766550165311301, 32.298722787726398, 31.9724893134679, 31.733745041689001, 31.560804411243499, 31.4680666775029]
y = [-225457.06785031699, -151654.317412915, -93620.558383412499, -53880.168115145199, -30116.624926982, -16905.4587130902, -9712.6193383353802, -5810.69026270625, -3678.9706880631902, -2475.8794835536701, -1751.8371788254599, -1253.7787633139801, -901.12220338703003, -643.67630154638596, -454.56954062206199, -318.51086928594498, -223.35257106637999, -156.97451642102101, -112.89935316650001, -82.655897872917393, -61.638224025861199, -46.766272864377299, -36.093957934023599, -28.313379974280299, -22.4321281711178, -17.961980555220599, -14.556781594439601, -11.97682273137, -10.061208825108, -8.6707057874908102, -7.6773295770935901, -7.0721051618041599, -6.7628705905120299, -6.6605343376401303, -6.69407747810377, -6.8113923612978997, -6.8702914807042204, -6.8388590566887899, -6.5692275645203999, -6.1065237236783396, -5.5035760007258503, -4.79953162532468, -4.0671542575787001, -3.3690652676737902, -2.7612664707248298, -2.2359507233406499, -1.77482078896039, -1.44286837047643, -1.1560624817337399]
fig, ax1 = plt.subplots(figsize=(16,12))
p, = ax1.plot(x, y) # really, x and y would be arrays of doubles which are read from QTIPlot
ax1.set_xlabel(unicode("Z'"))
ax1.set_ylabel(unicode("Z''"))
ax1.set_xlim(20,70)
ax1.set_ylim(0,-50)
ax1.set_aspect('equal', adjustable='box')
ax1.tick_params(axis='y', direction = 'out')
ax1.tick_params(axis='x', direction = 'out')
ax1.yaxis.tick_left()
ax1.xaxis.tick_bottom()
plt.savefig("figure.pdf")
Related
I have been trying to animate a polar plot in which I have a one degree wide wedge sweep all the way around the plot in a circle. I tried using the code below, but for some reason, it gives me the error AttributeError: 'NoneType' object has no attribute 'canvas'. I was trying to initialize the wedge as a rectangle patch that starts off on the right side of the plot and increases in x (angle), so I thought I should update the x-coordinate in the animate function, but for some reason, whenever I return patch (the rectangle) from animation, it gives me an error. Any tips? Thanks!
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.patches import Rectangle
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
_, rlim = ax.get_ylim()
patch = Rectangle((0,0), np.radians(1), rlim)
def init():
ax.add_patch(patch)
return patch,
def animate(i):
patch.set_xy((np.radians(i), 0))
return patch,
ani = animation.FuncAnimation(fig, animate, frames=360, interval=30, blit=True)
plt.show()
Error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib64/python3.6/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/usr/lib64/python3.6/tkinter/__init__.py", line 749, in callit
func(*args)
File "/usr/lib64/python3.6/site-packages/matplotlib/backends/_backend_tk.py", line 114, in _on_timer
TimerBase._on_timer(self)
File "/usr/lib64/python3.6/site-packages/matplotlib/backend_bases.py", line 1187, in _on_timer
ret = func(*args, **kwargs)
File "/usr/lib64/python3.6/site-packages/matplotlib/animation.py", line 1449, in _step
still_going = Animation._step(self, *args)
File "/usr/lib64/python3.6/site-packages/matplotlib/animation.py", line 1169, in _step
self._draw_next_frame(framedata, self._blit)
File "/usr/lib64/python3.6/site-packages/matplotlib/animation.py", line 1189, in _draw_next_frame
self._post_draw(framedata, blit)
File "/usr/lib64/python3.6/site-packages/matplotlib/animation.py", line 1212, in _post_draw
self._blit_draw(self._drawn_artists, self._blit_cache)
File "/usr/lib64/python3.6/site-packages/matplotlib/animation.py", line 1229, in _blit_draw
bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.bbox)
AttributeError: 'NoneType' object has no attribute 'canvas'
I'm trying to make a 3d scatterplot with fading points over time, similar to this question. However, when I apply the colormap to the data, then the face of the marker changes color but the edge remains solid.
I've tried using the edgecolors='None', edgecolor='none' kwargs, the marker='o' kwarg as per this example, and the edgecolor='face' kwarg. I've also tried using post creation methods such as scat3D.set_edgecolor("None") etc. The first attempts throw an error, and the latter have no effect.
Error from setting kwargs:
Traceback (most recent call last):
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/animation.py", line 230, in saving
yield self
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/animation.py", line 1156, in save
writer.grab_frame(**savefig_kwargs)
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/animation.py", line 384, in grab_frame
dpi=self.dpi, **savefig_kwargs)
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/figure.py", line 2180, in savefig
self.canvas.print_figure(fname, **kwargs)
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/backends/backend_qt5agg.py", line 88, in print_figure
super().print_figure(*args, **kwargs)
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/backend_bases.py", line 2082, in print_figure
**kwargs)
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py", line 442, in print_raw
FigureCanvasAgg.draw(self)
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py", line 388, in draw
self.figure.draw(self.renderer)
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/artist.py", line 38, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/figure.py", line 1709, in draw
renderer, self, artists, self.suppressComposite)
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/image.py", line 135, in _draw_list_compositing_images
a.draw(renderer)
File "/home/max/.local/lib/python3.6/site-packages/matplotlib/artist.py", line 38, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/home/max/.local/lib/python3.6/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 292, in draw
reverse=True)):
File "/home/max/.local/lib/python3.6/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 291, in <lambda>
key=lambda col: col.do_3d_projection(renderer),
File "/home/max/.local/lib/python3.6/site-packages/mpl_toolkits/mplot3d/art3d.py", line 545, in do_3d_projection
ecs = (_zalpha(self._edgecolor3d, vzs) if self._depthshade else
File "/home/max/.local/lib/python3.6/site-packages/mpl_toolkits/mplot3d/art3d.py", line 847, in _zalpha
rgba = np.broadcast_to(mcolors.to_rgba_array(colors), (len(zs), 4))
File "<__array_function__ internals>", line 6, in broadcast_to
File "/home/max/.local/lib/python3.6/site-packages/numpy/lib/stride_tricks.py", line 182, in broadcast_to
return _broadcast_to(array, shape, subok=subok, readonly=True)
File "/home/max/.local/lib/python3.6/site-packages/numpy/lib/stride_tricks.py", line 127, in _broadcast_to
op_flags=['readonly'], itershape=shape, order='C')
ValueError: operands could not be broadcast together with remapped shapes [original->remapped]: (0,4) and requested shape (100,4)
(There's a during the handling the above exception another occured error after that, but my post was flagged as spam so I didn't include it)
Here's the code without the error (adding a kwarg listed above causes the error):
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.patches as mpatches
total = 10
num_whatever = 100
to_plot = [np.random.rand(num_whatever, 3) for i in range(total)]
colors = np.linspace(0, 1, num_whatever)
fig = plt.figure()
ax3d = Axes3D(fig)
scat3D = ax3d.scatter([],[],[], s=10, cmap="Blues", vmin=0, vmax=1)
scat3D.set_cmap("Blues") # cmap argument above is ignored, so set it manually
ttl = ax3d.text2D(0.05, 0.95, "", transform=ax3d.transAxes)
def update_plot(i):
print( i, to_plot[i].shape)
ttl.set_text('PCA on 3 components at step = {}'.format(i*20))
scat3D._offsets3d = np.transpose(to_plot[i])
scat3D.set_array(colors)
return scat3D,
def init():
scat3D.set_offsets([[],[],[]])
plt.style.use('ggplot')
ani = animation.FuncAnimation(fig, update_plot, init_func=init,
blit=False, interval=300, frames=range(total))
ani.save("ani.gif", writer="imagemagick")
plt.show()
Here's the plot with the marker edges not hidden:
Plot
You can see that the faded points still have the marker edges not colormapped. I would expect that setting edgecolor would be unnecessary in the first place, since the 2d animation clearly doesn't need it. But why would adding that kwarg cause me to get a operands could not be broadcast togeather error? I don't have any array with shape (0, 4), so it's not clear where this is coming from.
The problem is that if c (as the color argument) is not specified, it is not a priori clear if a colormapping should happen or not. This leads to some internal confusion about which arguments to obey to. But we can specify c as an empty list to get around that.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D
total = 10
num_whatever = 100
to_plot = [np.random.rand(num_whatever, 3) for i in range(total)]
colors = np.linspace(0, 1, num_whatever)
fig = plt.figure()
ax3d = Axes3D(fig)
scat3D = ax3d.scatter([], [], [], s=10, c=[], cmap="Blues", vmin=0, vmax=1,
depthshade=False)
ttl = ax3d.text2D(0.05, 0.95, "", transform=ax3d.transAxes)
def update_plot(i):
print( i, to_plot[i].shape)
ttl.set_text('PCA on 3 components at step = {}'.format(i*20))
scat3D._offsets3d = np.transpose(to_plot[i])
scat3D.set_array(colors)
return scat3D,
def init():
scat3D.set_offsets([[],[],[]])
plt.style.use('ggplot')
ani = animation.FuncAnimation(fig, update_plot, init_func=init,
blit=False, interval=300, frames=range(total))
ani.save("ani.gif", writer="imagemagick")
plt.show()
I have the following code snippet to illustrate the issue:
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import time
import random
# Mock categories
categories = ["cat1", "cat2", "cat3", "cat4"]
counter = 0
# Plot
x_data = []
y_data = []
plt.ion()
fig = plt.figure()
subplt = fig.add_subplot(312)
subplt_line, = subplt.plot(x_data, y_data, 'b.')
while True:
time.sleep(0.1) # simulate some delay that occurs in the actual application
x_data.append(counter)
subplt_line.set_xdata(x_data)
counter += 1
# y_data.append(random.randrange(1, 15)) # This works fine (except the scaling)
y_data.append(random.choice(categories)) # This will end in an exception
subplt_line.set_ydata(y_data)
# Update the plot
fig.canvas.draw()
fig.canvas.flush_events()
It will end in an exception like this:
Traceback (most recent call last):
File "test.py", line 36, in <module>
fig.canvas.draw()
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/backends/backend_tkagg.py", line 12, in draw
super(FigureCanvasTkAgg, self).draw()
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/backends/backend_agg.py", line 437, in draw
self.figure.draw(self.renderer)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/artist.py", line 55, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/figure.py", line 1493, in draw
renderer, self, artists, self.suppressComposite)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/image.py", line 141, in _draw_list_compositing_images
a.draw(renderer)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/artist.py", line 55, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/axes/_base.py", line 2635, in draw
mimage._draw_list_compositing_images(renderer, self, artists)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/image.py", line 141, in _draw_list_compositing_images
a.draw(renderer)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/artist.py", line 55, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/lines.py", line 738, in draw
self.recache()
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/lines.py", line 656, in recache
yconv = self.convert_yunits(self._yorig)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/artist.py", line 200, in convert_yunits
return ax.yaxis.convert_units(y)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/axis.py", line 1526, in convert_units
ret = self.converter.convert(x, self.units, self)
File "/anaconda3/envs/xxx/lib/python2.7/site-packages/matplotlib/category.py", line 65, in convert
unit.update(values)
AttributeError: 'NoneType' object has no attribute 'update'
I seems like the combination of categorcal y data and the interactivity is causing this. When using numerical values it works fine, and when using the non-interactive feature it works well even with the categorical axis.
Another issue is be the automatic scaling of the y axis. New values added via set_y_data() dot seem to trigger this.
The plot will visualize analysis done on an endless stream of data and is used like a dashboard - therefore the plot should update with each iteration of the loop.
I couldn't run your code using the while loop, but I would suggest using FuncAnimation to create self-updating graphs anyway (there are plenty of examples on SO and online).
I believe your problem is with the initialization of the Line2D object. When you're passing any empty y-array, matplotlib seem to assume you're going to use numerical and not categorical values. Initializing the line with a string as a y-value seem to do the trick. You'll have to adjust the code so that the first point created makes sense for your data, but that should only be a minor annoyance.
For the scaling of the axis, matplotlib adds each category to a new integer value, so you need only to count how many categories you have in your data to know what is the extent of the axes.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
import random
# Mock categories
categories = ["cat1", "cat2", "cat3", "cat4"]
counter = 0
# Plot
x_data = [0]
y_data = ['cat1']
fig = plt.figure()
subplt = fig.add_subplot(312)
subplt_line, = subplt.plot(x_data, y_data, 'b.-')
debug_text = fig.text(0, 1, "TEXT", va='top') # for debugging
def init():
subplt_line.set_data([0],['cat1'])
def animate(num, ax):
new_x, new_y = num, random.choice(categories)
debug_text.set_text('{:d} {:s}'.format(num, new_y))
x, y = subplt_line.get_data()
x = np.append(x, new_x)
y = np.append(y, new_y)
subplt_line.set_data(x,y)
ax.set_xlim(min(x),max(x))
ax.set_ylim(0,len(np.unique(y))-1)
return subplt_line,debug_text
ani = animation.FuncAnimation(fig, animate, fargs=[subplt], init_func=init, frames=20, blit=False, repeat=False)
plt.show()
I encountered a strange issue with the seaborn library. When generating barplot for data with ranging from very low to very high values, e.g.:
job duration type
0 1 83066.639344 A
1 2 820.700000 B
it fails with:
ValueError: cannot convert float NaN to integer
This looks like a bug in matplotlib and a duplicate of "pyplot.savefig fails with ValueError: cannot convert float NaN to integer". The latter has not been fixed yet. Is there a workaround for it?
Here's the minimal working example to reproduce the issue:
#!/usr/bin/env python3
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
d = {'job': [1, 2]),
'duration': [83066.639344, 820.700000],
'type': ['A', 'B']}
df = pd.DataFrame(d)
plot = sns.catplot(x="duration", y="job", data=df, hue='type',
color="b", kind="bar", height=3, aspect=4)
ax = plot.axes.flat[0]
for p in plt.gca().patches:
ax.text(p.get_width(),
p.get_y() + p.get_height() / 2,
p.get_width())
plot.savefig("barplot.png")
Some observations:
The problem does not occur when I do not differentiate between 'type' (no use ofhue='type').
Here's the full stacktrace:
posx and posy should be finite values
posx and posy should be finite values
/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/numpy/core/fromnumeric.py:83: RuntimeWarning: invalid value encountered in reduce
return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
posx and posy should be finite values
posx and posy should be finite values
posx and posy should be finite values
Traceback (most recent call last):
File "/Users/dzieciou/projects/example/gocd/reproduce.py", line 31, in <module>
plot.savefig("barplot.png")
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/seaborn/axisgrid.py", line 37, in savefig
self.fig.savefig(*args, **kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/figure.py", line 2094, in savefig
self.canvas.print_figure(fname, **kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/backend_bases.py", line 2075, in print_figure
**kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py", line 510, in print_png
FigureCanvasAgg.draw(self)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py", line 402, in draw
self.figure.draw(self.renderer)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/artist.py", line 50, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/figure.py", line 1649, in draw
renderer, self, artists, self.suppressComposite)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/image.py", line 138, in _draw_list_compositing_images
a.draw(renderer)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/artist.py", line 50, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 2610, in draw
mimage._draw_list_compositing_images(renderer, self, artists)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/image.py", line 138, in _draw_list_compositing_images
a.draw(renderer)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/artist.py", line 50, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 1185, in draw
ticks_to_draw = self._update_ticks(renderer)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 1023, in _update_ticks
tick_tups = list(self.iter_ticks()) # iter_ticks calls the locator
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 967, in iter_ticks
majorLocs = self.major.locator()
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/ticker.py", line 1985, in __call__
return self.tick_values(vmin, vmax)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/ticker.py", line 1993, in tick_values
locs = self._raw_ticks(vmin, vmax)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/ticker.py", line 1932, in _raw_ticks
nbins = np.clip(self.axis.get_tick_space(),
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 2543, in get_tick_space
return int(np.floor(length / size))
ValueError: cannot convert float NaN to integer
Note that this is neither really a bug, nor is it related to the linked bug, which is indeed fixed.
One could argue that there should be a better error message when plotting text at nan coordinates though.
Before looking at the error, it seems you have another problem in your code, which is that you set the x coordinate of the text to the width of the bar. They are usually unrelated and you might have meant to use p.get_x() instead.
Now two options:
1. Don't position text at invalid coordinates.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
d = {'job': list(range(1, 3)),
'duration': [83066.639344, 820.700000],
'type': ['A', 'B']}
df = pd.DataFrame(d)
plot = sns.catplot(x="duration", y="job", data=df, hue='type',
color="b", kind="bar", height=3, aspect=4)
ax = plot.axes.flat[0]
for p in plt.gca().patches:
height = np.nan_to_num(p.get_height(), 0)
ax.text(p.get_x(), p.get_y() + height/2., "My text")
plot.savefig("barplot.png")
plt.show()
2. Don't use bbox_inches="tight".
If you want to keep your code as it is, you may workaround this by not setting the bbox_inches="tight" options in seaborn's savefig.
plot.savefig("barplot.png", bbox_inches=None)
Or use matplotlib's savefig option
plot.fig.savefig("barplot.png")
My problem is following:
I'm taking a data from files and want to make an animation of four plots at the same time: two colourbars and two lines.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anim
import sys
begin = float(sys.argv[1])
end = float(sys.argv[2])
dataCl = np.loadtxt("file1.txt")
dataSS = np.loadtxt("file2.txt")
datajSR = np.loadtxt("file3.txt")
ibegin = 0
iend = 0
for i in range(len(dataCl[:,0])):
if np.abs(dataCl[i,0] - begin) < 1e-9:
ibegin = i
iend = i
while abs(dataCl[i,0] - end) >= 1e-9:
iend = iend + 1
i = i + 1
break
fig = plt.figure()
f, axarr = plt.subplots(2, 2)
temp = np.zeros((10,10))
Qs = axarr[0,0].imshow(temp,cmap = plt.cm.OrRd)
El = axarr[0,1].imshow(temp,cmap = plt.cm.OrRd)
SS, = axarr[1,0].plot([],[])
jSR, = axarr[1,1].plot([],[])
def init():
Qs.set_array(temp)
El.set_array(temp)
SS.set_data([],[])
jSR.set_data([],[])
return Qs,El,SS,jSR,
def animate(i):
a = 0
b = 0
dataQ = np.zeros((10,10))
dataE = np.zeros((10,10))
for j in range(100):
if b >= 10:
a = a + 1
b = 0
dataQ[a][b] = dataCl[i,2*j + 1]
dataE[a][b] = dataCl[i,2*(j+1)]
b = b + 1
Qs.set_array(dataQ)
El.set_array(dataE)
SS.set_data(dataSS[ibegin:ibegin+i,0],dataSS[ibegin:ibegin+i,1])
jSR.set_data(datajSR[ibegin:ibegin+i,0],datajSR[ibegin:ibegin+i,1])
return Qs,El,SS,jSR,
ani = anim.FuncAnimation(fig, animate, init_func = init, frames = iend-ibegin,interval=25, blit=True)
plt.show()
After running it shows these messages:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1413, in __call__
return self.func(*args)
File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 236, in resize
self.show()
File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 239, in draw
FigureCanvasAgg.draw(self)
File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_agg.py", line 421, in draw
self.figure.draw(self.renderer)
File "/usr/lib/pymodules/python2.7/matplotlib/artist.py", line 55, in draw_wrapper
draw(artist, renderer, *args, **kwargs)
File "/usr/lib/pymodules/python2.7/matplotlib/figure.py", line 904, in draw
self.canvas.draw_event(renderer)
File "/usr/lib/pymodules/python2.7/matplotlib/backend_bases.py", line 1544, in draw_event
self.callbacks.process(s, event)
File "/usr/lib/pymodules/python2.7/matplotlib/cbook.py", line 262, in process
proxy(*args, **kwargs)
File "/usr/lib/pymodules/python2.7/matplotlib/cbook.py", line 192, in __call__
return mtd(*args, **kwargs)
File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 273, in _end_redraw
self._post_draw(None, self._blit)
File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 220, in _post_draw
self._blit_draw(self._drawn_artists, self._blit_cache)
File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 235, in _blit_draw
a.axes.draw_artist(a)
File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 2008, in draw_artist
assert self._cachedRenderer is not None
AssertionError
I cannot find a mistake in my code ;(
The error message might be backend and platform specific. As the error message seems to point to the blitting mechanism, you might want to try setting blit=False in FuncAnimation. Also, you might try some other backend to see if the problem persists. (Knowing your platform and matplotlib version might also help.)
Update: If setting blit=False, trying another backend, and updating matplotlib does not help, then a few suggestions:
Try to see manually if you code works with the initial data (init(); animate(0); fig.savefig("/tmp/test.png")) - if it throws an error, there is a static plotting problem to fix.
Now you initialize the plot twice (first in the code, then in init), you can take one away (e.g. do not define init_func)
Initializing the plots with [],[] leaves the scale uninitialized. You should probably use set_ylim, set_xlim with the plots and vmin, vmax keywords with the imshow images when you initialize them. (This could possibly have something to do with the exception you get!)