3

I am using matplotlib to create a graph for my thesis. I am using the following code:

import numpy as np
import numpy as np
import matplotlib as mpl
mpl.use('pgf')

fig_width_pt = 390  # Get this from LaTeX using \showthe\columnwidth
inches_per_pt = 1.0/72.27               # Convert pt to inch
golden_mean = (np.sqrt(5)-1.0)/2.0         # Aesthetic ratio
fig_width = fig_width_pt*inches_per_pt  # width in inches
fig_height = fig_width*golden_mean      # height in inches
fig_size =  [fig_width,fig_height]

pgf_with_latex = {                      # setup matplotlib to use latex for output
    "pgf.texsystem": "pdflatex",        # change this if using xetex or lautex
    "text.usetex": True,                # use LaTeX to write all text
    "font.family": "serif",
    "font.serif": [],                   # blank entries should cause plots to inherit fonts from the document
    "font.sans-serif": [],
    "font.monospace": [],
    "axes.labelsize": 10,               # LaTeX default is 10pt font.
    "text.fontsize": 10,
    "legend.fontsize": 8,               # Make the legend/label fonts a little smaller
    "xtick.labelsize": 8,
    "ytick.labelsize": 8,
    "figure.figsize": fig_size,
    'axes.linewidth': .5,
    'lines.linewidth': .5,
    'patch.linewidth': .5,
    "pgf.preamble": [
        r"\usepackage[utf8x]{inputenc}",    # use utf8 fonts becasue your computer can handle it :)
        ]
    }
mpl.rcParams.update(pgf_with_latex)

import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import colorsys

def savefig(filename):
    plt.savefig('{}.pgf'.format(filename))
    plt.savefig('{}.pdf'.format(filename))

# setup
title = 'Clustering after salting out'
ylabel = '% of total colloids'
xlabel = 'Cluster size'
xticklabels = ('1','2','3','4','5','6','7','5+')
legend = ['10min', '20min','30min']

# read data from files
# skipped this part for legibility

# calculations with data, skipped for legibility

# plot it in a bar plot
N = len(ys[0])

ind = np.arange(0, N+1, 1.2)  # the x locations for the groups
width = 0.35       # the width of the bars

# generate colours
hsv_colours = [(x*1.0/N, 0.8, 0.8) for x in range(N)]
rgb_colours = map(lambda x: colorsys.hsv_to_rgb(*x), hsv_colours)

fig, ax = plt.subplots()
rects = [ax.bar([x+i*width for x in ind], y, width, color=rgb_colours[i], yerr=errors_percentage[i]) for i,y in enumerate(ys)]

# add some info
ax.set_ylabel(ylabel)
ax.set_xlabel(xlabel)
ax.set_title(title)
ax.set_xticks(ind+width)
ax.set_xticklabels(xticklabels)
ax.axis([0,7,0,60])
ax.legend(rects, legend)

savefig('tpm_cluster_statistics')

The output produced looks like this: Result of python code

As you can see, the last bar of the bar plot is not totally filled. Do I need some other setting to get it working? The goal is to create a PGF file for inclusion in a LaTex document. The PDF file is just for previewing. The partially filled bar is both in the PDF and in the PGF file. Any help is greatly appreciated!

Edit: In reply to tcaswell: this is a minimum working example that you can try on your computer:

import numpy as np
import numpy as np
import matplotlib as mpl
mpl.use('pgf')

pgf_with_latex = {                      # setup matplotlib to use latex for output
    "pgf.texsystem": "pdflatex",        # change this if using xetex or lautex
    "text.usetex": True,                # use LaTeX to write all text
    }
mpl.rcParams.update(pgf_with_latex)

import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import colorsys

def savefig(filename):
    plt.savefig('{}.pgf'.format(filename))
    plt.savefig('{}.pdf'.format(filename))

# setup
title = 'Title'
ylabel = 'x'
xlabel = 'y'
xticklabels = ('1','2','3','4','5','6','7','8')
legend = ['1', '2','3']

#data
ys = [[51.63593099345628, 28.911362284354553, 12.135633551457465, 4.521118381915526, 1.189767995240928, 0.7138607971445567, 0.41641879833432477, 0.4759071980963712], [46.66359871145882, 21.445006902899216, 14.496088357109988, 7.363092498849516, 4.1417395306028535, 3.313391624482283, 0.0, 2.577082374597331], [52.642595499738356, 22.39665096807954, 12.087912087912088, 7.744636316064887, 2.3547880690737837, 1.5698587127158554, 0.3663003663003663, 0.837257980115123]]

# plot it in a bar plot
N = len(ys[0])

ind = np.arange(0, N+1, 1.2)  # the x locations for the groups
width = 0.35       # the width of the bars

fig, ax = plt.subplots()
rects = [ax.bar([x+i*width for x in ind], y, width) for i,y in enumerate(ys)]

# add some info
ax.set_ylabel(ylabel)
ax.set_xlabel(xlabel)
ax.set_title(title)
ax.set_xticks(ind+width)
ax.set_xticklabels(xticklabels)
ax.axis([0,7,0,60])
ax.legend(rects, legend)

savefig('tpm_cluster_statistics')

Then the result looks like this: minimal working example

But when I remove these lines:

mpl.use('pgf')

pgf_with_latex = {                      # setup matplotlib to use latex for output
    "pgf.texsystem": "pdflatex",        # change this if using xetex or lautex
    "text.usetex": True,                # use LaTeX to write all text
    }
mpl.rcParams.update(pgf_with_latex)

And just show the output using plt.show(), the result does look correct.

rbnvrw
  • 347
  • 3
  • 15
  • See what happens if you add some dummy data to plot one more bar, except it's zero height and no error bars. Does your Cluster size 6 30 minute bar get filled then? – MattDMo May 08 '14 at 21:19
  • Thanks for your answer. I used this data: `data = [[old_data0, 0.],[old_data1, 0.],[old_data2, 0.]] and errors = [[old_errors0, 0.],[old_errors1, 0.],[old_errors2, 0.]]`, but I don't see a difference... – rbnvrw May 08 '14 at 21:30
  • what version of mpl? Can you reduce this to the _minimal_ amount of code required to reproduce this (synthetic data, strip out the labels + fancy formatting) – tacaswell May 08 '14 at 21:44
  • and this smells like a bug in the pgf backend. – tacaswell May 08 '14 at 21:45
  • @tcaswell: I have updated the question with a minimal example and the lines that are causing the problem. I have matplotlib 1.3.1 installed on a Windows 7 machine. – rbnvrw May 09 '14 at 07:10
  • We have different ideas of minimal;) Does `usetex` matter? Does it depend on your _exact_ data? Does it depend on the fact that you call `bar` in a loop? Does adjusting your xlimit matter? Does replacing the xticks matter? – tacaswell May 09 '14 at 13:27

1 Answers1

0

I don't know what really causes it, but switching to just PDF output without the mpl.use('pgf') fixes the issue. For now I'll just stick to PDF, which is fine too. Thanks for all the help!

rbnvrw
  • 347
  • 3
  • 15