Search code examples
pythonmatplotlibplotfontsms-word

matplotlib mathtext font either STIX two or cambria math


I've been trying to make mathematical font consistent between Word(equation) and Matplotlib (plots). In Word-equation, I have options: cambria math, stix two math, dejavu math gyre (i will not use the last one).

In matplotlib, for my plot, i use: plt.rcParams['mathtext.fontset'] = 'stix' (i don't use Tex).

When I compare Word-equation "stix two math" result vs Matplotlib 'stix', they are different.(why?) I also tried this, by pointing directly to the .otf file in my PC, to modify the matlplotlib. If i understand correctly, this only work for the text but not for the mathtext (which is inside '$ equation $'), and i so couldn't not change the mathtext to become consistent with the word-equation.

Any suggestion? Thank you. As long as they're both in the same font, should be ok. But I don't know how to do it.

version and PC: Windows 10, Matplotlib 3.4.1, Python 3.9.13,


Solution

  • Perhaps this will be useful for others that preparing a manuscript using ms word and graph/plot using python (matplotlib).

    First, set the math-font of Ms word. by default is Cambria Math, but we can add other math-font such as stix two, xits, etc. Remember, the font for math and regular text is different. setting default math-font: insert a formula in a .doc file, go to tab equation tools, next to 'converstion', click the arrow, there will be a window named as equation options. select default.

    In matplotlib, it depends on the font that we need to match: The basic is here. From my limited understanding upon solving my own problem, there are a few options:

    1. using matplotlib's mathtext font family: It is the easiest method in matplotlib, however the available mathfont is very limited. note: stix math font matplotlib is somewhat different than if you install the latest stix two math on your system (that is being used in your word processor). example:
        import matplotlib.pyplot as plt
        plt.rcParams['text.usetex'] = False
        plt.rcParams['mathtext.fontset'] = 'stix'  # or other, 'dejavuserif'
        plt.rcParams['font.family'] = 'serif'  # or 'DejaVu Serif'
        plt.rcParams['font.serif'] = ['Times New Roman']  # 'DejaVu Serif' serif' 'Times'
    

    see rcParams for available fonts.

    1. Using a Tex engine. you have to know a little about latex preamble. there are (at least) two options here: 2.a. use pdflatex
        plt.rcParams['font.family'] = 'serif'  # or 'DejaVu Serif'
        plt.rcParams['font.serif'] = ['Times New Roman']  # 'DejaVu Serif' 'serif' 'Times
        plt.rcParams['text.usetex'] = True
        plt.rcParams['text.latex.preamble'] = r'''
        \usepackage{amsmath}
        \usepackage[lcgreekalpha]{stix2}
        '''
    

    This method is a little more straightforward compared to the following method. Still, refer to this answer for further info.

    2.b. use XeLaTeX/LuaLaTeX via the pgf backend, as explained here. example, such that we can use Cambria math:

        import matplotlib.pyplot as plt
        mpl.use("pgf")
        plt.rcParams.update({
        pgf.texsystem: "lualatex",
        font.family: "serif",  # use serif/main font for text elements
        text.usetex: True,     # use inline math for ticks
        pgf.rcfonts: False,    # don't setup fonts from rc parameters
        pgf.preamble: "\n".join([
        r"\usepackage{unicode-math}",   # unicode math setup
        r"\setmainfont{Cambria}",
        r"\setmathfont{Cambria Math}"
        ])
        })
        
        or for example use other font, replace the preamble with this:
        r"\usepackage{unicode-math}",   # unicode math setup
        r"\setmainfont{Stix Two Text}",
        r"\setmathfont{Stix Two Math}[math-style=french]",
    

    with pgf backend, the code works a little different:

    • may not able to preview your plot, unless you export it as pdf and open it in a external pdf reader. There is a workaround for this, but sometimes it doesn't work.
    • creating plot using pgf backend can be problematic, for example if you have "Nan" in one of your data. Matplotlib seems able to solve this (behind) and we can always see the resulting plot, not the case with pgf backend.
    • you may need to change some of your code; for example it may be there's not \mathrm; instead, there's \symup. Please refer to this question.

    with method 2 we have to understand how to set the preamble correctly. example are given above, but for more info, you need to refer to the latex documentation/forum etc.

    So far, method 2.b. provides the best method, as it provides many options for the math text. It uses the unicode math package which consist with a lot of font option. More info is here.