question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Consider vendoring the Felipa font with mplhep

See original GitHub issue

As mplhep already vendors a few fonts in the installation what are people’s (@andrzejnovak) thoughts on additionally vendoring a cursive font (Felipa)? Most of the default cursive fonts from matplotlib are not found in any of the Ubuntu PPAs that deal with fonts (to my knowledge).

An example of this causing an issue is with the following example.py script

import numpy as np
import matplotlib.pyplot as plt
import mplhep


def make_plot(title=None):
    fig, ax = plt.subplots()
    x = np.linspace(0, 10, 101)
    y = np.square(x)
    ax.plot(x, y)
    ax.semilogy()

    ax.set_xlabel("$x$")
    ax.set_ylabel("$x^2$")
    if title is not None:
        ax.set_title(title)

    return fig, ax


def main():
    image_types = ["pdf", "png"]
    fig, ax = make_plot("Default matplotlib settings")

    for type in image_types:
        fig.savefig(f"default.{type}")

    plt.style.use(mplhep.style.ATLAS)
    fig, ax = make_plot("mplhep ATLAS style")
    for type in image_types:
        fig.savefig(f"ATLAS_style.{type}")

    plt.style.use(mplhep.style.CMS)
    fig, ax = make_plot("mplhep CMS style")
    for type in image_types:
        fig.savefig(f"CMS_style.{type}")


if __name__ == "__main__":
    main()

if we include it in the following Dockerfile

FROM ubuntu:20.04

RUN apt-get update -y && \
    apt-get install -y \
        fontconfig \
        fonts-dejavu \
        fonts-freefont-ttf \
        python3 \
        python3-dev \
        python3-pip \
        python3-venv \
        vim \
        wget && \
        apt-get -y autoclean && \
        apt-get -y autoremove && \
        rm -rf /var/lib/apt/lists/*

RUN python3 -m pip install --upgrade --no-cache-dir pip setuptools wheel && \
    python3 -m pip install --no-cache-dir mplhep && \
    python3 -m pip list

# Create user "docker"
RUN useradd -m docker && \
    cp /root/.bashrc /home/docker/
ENV HOME /home/docker

WORKDIR /code

COPY example.py example.py

# give non-root user docker ownership of files
RUN chown -R --from=root docker /home/docker && \
    chown -R --from=root docker /code
USER docker

# Create font list cache and config dir
RUN python3 -c "import matplotlib.pyplot"

then both ATLAS and CMS styles will give the following warnings when running

$ docker run --rm -v $PWD:$PWD -w $PWD mplhep-issue:failing-example /bin/bash -c "python3 /code/example.py"
findfont: Font family ['cursive'] not found. Falling back to DejaVu Sans.
'texgyreheros-regular.otf' can not be subsetted into a Type 3 font. The entire font will be embedded in the output.
findfont: Font family ['cursive'] not found. Falling back to DejaVu Sans.
'texgyreheros-regular.otf' can not be subsetted into a Type 3 font. The entire font will be embedded in the output.

This is happening as no cursive font in matplotlib’s default cursive font family can be found. This can be fixed by installing the Felipa font from Google Fonts as seen in the following Dockerfile

FROM ubuntu:20.04

RUN apt-get update -y && \
    apt-get install -y \
        fontconfig \
        fonts-dejavu \
        fonts-freefont-ttf \
        python3 \
        python3-dev \
        python3-pip \
        python3-venv \
        vim \
        wget && \
        apt-get -y autoclean && \
        apt-get -y autoremove && \
        rm -rf /var/lib/apt/lists/*

RUN python3 -m pip install --upgrade --no-cache-dir pip setuptools wheel && \
    python3 -m pip install --no-cache-dir mplhep && \
    python3 -m pip list

# Create user "docker"
RUN useradd -m docker && \
    cp /root/.bashrc /home/docker/
ENV HOME /home/docker

# felipa provides a cursive font
RUN mkdir -p "${HOME}/.local/share/fonts/truetype/felipa" && \
    wget --no-clobber "https://github.com/google/fonts/blob/master/ofl/felipa/Felipa-Regular.ttf?raw=true" -O "${HOME}/.local/share/fonts/truetype/felipa/Felipa-Regular.ttf" && \
    ln -s "${HOME}/.local/share/fonts/truetype/felipa" /usr/share/fonts/truetype/felipa && \
    fc-cache --force --verbose

WORKDIR /code

COPY example.py example.py

# give non-root user docker ownership of files
RUN chown -R --from=root docker /home/docker && \
    chown -R --from=root docker /code
USER docker

# Create font list cache and config dir
RUN python3 -c "import matplotlib.pyplot"

which when built and run then (mostly) works

$ docker run --rm -v $PWD:$PWD -w $PWD mplhep-issue:working-example /bin/bash -c "python3 /code/example.py"
'texgyreheros-regular.otf' can not be subsetted into a Type 3 font. The entire font will be embedded in the output.
'texgyreheros-regular.otf' can not be subsetted into a Type 3 font. The entire font will be embedded in the output.

For the Felipa font

These fonts are licensed under the Open Font License.

You can use them freely in your products & projects - print or digital, commercial or otherwise. However, you can’t sell the fonts on their own.

it seems that it should be permissilbe to vendor Felipa with mplhep, and that this could reduce a lot of warnings people might have. Thoughts?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:16 (16 by maintainers)

github_iconTop GitHub Comments

2reactions
andrzejnovakcommented, Jan 11, 2021

Ok, thanks a lot for finding that @kratsg. This seems to be a good comparison of Math/TeX fonts https://tex.stackexchange.com/questions/425098/which-opentype-math-fonts-are-available and it looks like the DejaVU Math is mostly as good as any here. I would support adding this to all styles that have custom mathtext.

I think #241 should be done either way.

1reaction
kratsgcommented, Jan 11, 2021

Ok, this issue is because of mathtext.cal (for calligraphic settings) which we should probably set to TeX Gyre Pagella everywhere.

Playing around more with the docker image

>>> matplotlib.font_manager.findSystemFonts()
['/usr/share/fonts/truetype/freefont/FreeSerifItalic.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf', '/usr/share/fonts/truetype/freefont/FreeSansBoldOblique.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSerif-Italic.ttf', '/usr/share/fonts/truetype/freefont/FreeSerifBold.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed-Bold.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSans-ExtraLight.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuMathTeXGyre.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSerif-BoldItalic.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSerifCondensed-BoldItalic.ttf', '/usr/share/fonts/truetype/freefont/FreeSansOblique.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSerifCondensed-Italic.ttf', '/usr/share/fonts/truetype/freefont/FreeMonoBoldOblique.ttf', '/usr/share/fonts/truetype/freefont/FreeSans.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSerifCondensed.ttf', '/usr/share/fonts/truetype/freefont/FreeMono.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed-BoldOblique.ttf', '/usr/share/fonts/truetype/freefont/FreeSerifBoldItalic.ttf', '/usr/share/fonts/truetype/freefont/FreeSerif.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf', '/usr/share/fonts/truetype/freefont/FreeMonoOblique.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Oblique.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSans-BoldOblique.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed-Oblique.ttf', '/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSerifCondensed-Bold.ttf', '/usr/share/fonts/truetype/freefont/FreeSansBold.ttf', '/usr/share/fonts/truetype/dejavu/DejaVuSansMono-BoldOblique.ttf']
>>> matplotlib.font_manager.findfont('Free Sans')
findfont: Font family ['Free Sans'] not found. Falling back to DejaVu Sans.
'/usr/local/lib/python3.8/dist-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf'
>>> matplotlib.font_manager.findfont('FreeSans')
'/usr/share/fonts/truetype/freefont/FreeSans.ttf'
>>> matplotlib.font_manager.findfont('ITCBookman')
findfont: Font family ['ITCBookman'] not found. Falling back to DejaVu Sans.
'/usr/local/lib/python3.8/dist-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf'

you can see these errors come up. And digging further, using the initialized font manager with true-type fonts which I think are the ones used for pdfs anyway

>>> sorted(set([f.name for f in matplotlib.font_manager.fontManager.ttflist]))
['DejaVu Math TeX Gyre', 'DejaVu Sans', 'DejaVu Sans Display', 'DejaVu Sans Mono', 'DejaVu Serif', 'DejaVu Serif Display', 'FreeMono', 'FreeSans', 'FreeSerif', 'STIXGeneral', 'STIXNonUnicode', 'STIXSizeFiveSym', 'STIXSizeFourSym', 'STIXSizeOneSym', 'STIXSizeThreeSym', 'STIXSizeTwoSym', 'cmb10', 'cmex10', 'cmmi10', 'cmr10', 'cmss10', 'cmsy10', 'cmtt10']

there’s certainly not a lot of good default options here. E.G.

>>> matplotlib.font_manager.fontManager.findfont('DejaVu Math TeX Gyre')
'/usr/share/fonts/truetype/dejavu/DejaVuMathTeXGyre.ttf'

In the example code above, I tried to play around with some other cursive fonts

    print("\nATLAS_ITCZapfChanceryy")
    plt.style.use(mplhep.style.ATLAS)
    plt.rcParams.update({"mathtext.cal": "ITC Zapf Chancery"})
    print(f'mathtext.fontset for ATLAS style: {plt.rcParams["mathtext.fontset"]}')
    fig, ax = make_plot("mplhep ATLAS style")

    for type in image_types:
        fig.savefig(f"ATLAS.{type}")

    print("\nATLAS_ZapfChancery")
    plt.style.use(mplhep.style.ATLAS)
    plt.rcParams.update({"mathtext.cal": "Zapf Chancery"})
    print(f'mathtext.fontset for ATLAS style: {plt.rcParams["mathtext.fontset"]}')
    fig, ax = make_plot("mplhep ATLAS style")

    for type in image_types:
        fig.savefig(f"ATLAS.{type}")

    print("\nATLAS_ITCBookman")
    plt.style.use(mplhep.style.ATLAS)
    plt.rcParams.update({"mathtext.cal": "ITC Bookman"})
    print(f'mathtext.fontset for ATLAS style: {plt.rcParams["mathtext.fontset"]}')
    fig, ax = make_plot("mplhep ATLAS style")

    for type in image_types:
        fig.savefig(f"ATLAS.{type}")

    print("\nATLAS_TeXGyrePagella")
    plt.style.use(mplhep.style.ATLAS)
    plt.rcParams.update({"mathtext.cal": "TeX Gyre Pagella"})
    print(f'mathtext.fontset for ATLAS style: {plt.rcParams["mathtext.fontset"]}')
    fig, ax = make_plot("mplhep ATLAS style")

but these were giving similar errors anyway. So I added this block instead

    print("\nATLAS_MathTeXGyre")
    plt.style.use(mplhep.style.ATLAS)
    plt.rcParams.update({"mathtext.cal": "DejaVu Math TeX Gyre"})
    print(f'mathtext.fontset for ATLAS style: {plt.rcParams["mathtext.fontset"]}')
    fig, ax = make_plot("mplhep ATLAS style")

    for type in image_types:
        fig.savefig(f"ATLAS.{type}")

which runs fine with this output

ATLAS_MathTeXGyre
mathtext.fontset for ATLAS style: custom

so there’s not really a good default calligraphic font to rely on from what I understand.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Felipa - Google Fonts
Felipa is a carefully written calligraphic font based on a traditional Italian chancery cursive, though reinterpreted with a contemporary feeling.
Read more >
mplhep - bytemeta
Consider vendoring the Felipa font with mplhep ... Make software development more efficient, Also welcome to join our telegram.
Read more >
temsilci itiraz Sorun nedir felipa font - i3er.org
kanama İşitme engelli hatırlama Consider vendoring the Felipa font with mplhep · Issue #240 · scikit-hep/mplhep · GitHub ...
Read more >
mplhep - githubmemory
Fix negative ylim warning · Problems with axis sizing for mplhep v0.2.10+ · Add custom Font Manager to download fonts · Consider vendoring...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found