Search code examples
pythonmatplotliblatex

Error in using siunitx with Matplotlib/Python


I'm producing a big report with lot's of figures with some LateX content, and to maintain layout coherence I use a predefined mplstyle file with the following related definitions:

# FONT 
font.family: serif
font.size: 9.0
font.serif: Palatino
font.sans-serif: DejaVu Sans
font.weight: normal
#font.stretch: normal

# LATEX 
text.usetex: True 

However, I ran into a specific figure where I need to use LateX siunitx. Here is a stripped down version of my code, that includes the solution for this tex.stackexchange question:

import matplotlib.pyplot as plt
import pandas as pd
import matplotlib as mpl
import seaborn as sns


def get_binarized_categories(categories=['None', 'Low', 'Medium', 'Med +', 'High', 'Very High'],
                             bins=[-0.01, 0.000001, 0.10, 0.20, 0.30, 0.666, 1]):

    criteria_str = 'C'
    label_cats = []
    special_cats = ['None', 'Low', 'Very High']
    for i, cat in enumerate(categories):
        if cat not in special_cats:
            bin_low, bin_high = bins[i], bins[i+1]
            label = f'${bin_low:9.3f}\\leqslant\\Delta {criteria_str}<{bin_high:9.3f}$'
        elif cat == 'None':
            label = f'$\\Delta {criteria_str}=0$'
        elif cat == 'Low':
            bin_low, bin_high = bins[i], bins[i+1]
            sc_notation = f'{bin_low:.2e}'
            sc_notation = f'$\\num{{{bin_low}}}$'
            label = f'${sc_notation}\\leqslant\\Delta {criteria_str}<{bin_high:9.3f}$'
        elif cat == 'Very High':
            label = f'$\\Delta {criteria_str}\\geqslant{{{bins[-2]:9.3f}}}$'
        label_cats.append(label)
    return categories, bins, label_cats

# These are the defaults that I use with every figure to maintain layout coherence
sns.set_theme(style="whitegrid")
plt.style.use('./python.mplstyle')
palette = sns.color_palette("deep", n_colors=11)
sns.set_palette(palette, n_colors=11)
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
    "font.family": "serif",
    "font.size": 9.0,
    "font.serif": "Palatino",
    "font.sans-serif": "DejaVu Sans",
    "font.weight": "normal",
    "pgf.preamble": "\n".join([  # plots will use this preamble
        r"\usepackage[utf8]{inputenc}",
        r"\usepackage[T1]{fontenc}",
        r"\usepackage[detect-all,locale=UK]{siunitx}",
    ])
}
mpl.rcParams.update(pgf_with_latex)

fig, ax = plt.subplots(2, 3, constrained_layout=True)
df = pd.DataFrame({'diff': [0, 0.00001, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]})
categories, bins, label_cats = get_binarized_categories()
df = df.assign(slope=pd.cut(df['diff'], bins=bins, precision=6, labels=categories))
for id, (ax, category) in enumerate(zip(fig.axes, categories)):
    up_str = f'{label_cats[id]}'
    ax.text(.5, 1.01, up_str, horizontalalignment='center', transform=ax.transAxes, fontsize='small')

fig.savefig('test_latex.pdf', bbox_inches='tight')

However, upon running this code, I get the following errors: enter image description here

This exact code runs perfectly fine when I do not try to use siunitx (and consequently 'pgf'). Any idea on how I might fix this?


Solution

  • The problem is unrelated to siunitx. The latex error messages reports the control sequence \leqslant to be undefined, so you either need to replace it with something else or load a package which defines it, e.g.

    \usepackage{MnSymbol}