Python & Latex — Les-mathematiques.net The most powerful custom community solution in the world

Python & Latex

Bonsoir;

Le code ci-dessous fonctionnait il y 4/5 ans environ.
Il plante maintenant au niveau du displaystyle.
Python et Pyzo ont été mis à jour plusieurs fois depuis .
Qu'ai-je bien pu oublier ?
Ce code est censé produire l'image ci-jointe que j'avais conservé.
import matplotlib.pyplot as plt
from matplotlib import rc # Pour Latex 

from sympy import *

 
n=6
H = Matrix(n,n,lambda i,j: Rational(1,1+i+j))
LH=latex(H,mat_str = "array")
DH=H.det()
NumDH=str(DH.p)
DenDH=str(DH.q)

rc('text',usetex=True)

plt.figure()
indice=str(n)
plt.text(0.3,0.6,r"$H_{"+indice+"}=$", size=40, color='r', fontweight='bold')
plt.text(0.4,0.3,r"$\displaystyle "+LH+"$", size=50, color='r', fontweight='bold')
plt.text(0.25,0.1,r"$\displaystyle \mathrm{D\'e terminant}=\frac{" + NumDH+"}{" + DenDH + "}$", size=40, color='r', fontweight='bold', bbox=dict(boxstyle='roundtooth, pad=0.6', facecolor='fuchsia',ec='b', alpha=0.3))
plt.show()

Cordialement,

Rescassol118350

Réponses

  • Chez moi, ça marche en supprimant l'accent \' sur le "e" de "Déterminant" ou en remplaçant \mathrm par \hbox.
    Il y aurait sans doute moyen de mettre un "é" à la place du "\'e" mais il faudrait ajouter des codecs, c'est toujours pénible.
  • Bonjour,

    Math Coss, si ça marche chez toi, c'est que le code est correct, donc que c'est probablement une erreur d'installation ou de chemin, mais je ne vois pas quoi.
    Voilà le message d'erreur complet:
    Traceback (most recent call last):
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\mathtext.py", line 2617, in parse
        result = self._expression.parseString(s)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\pyparsing.py", line 1955, in parseString
        raise exc
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\mathtext.py", line 2775, in unknown_symbol
        raise ParseFatalException(s, loc, "Unknown symbol: %s" % c)
    pyparsing.ParseFatalException: Unknown symbol: \displaystyle, found '\'  (at char 0), (line:1, col:1)
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\backends\backend_qt5.py", line 480, in _draw_idle
        self.draw()
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\backends\backend_agg.py", line 407, in draw
        self.figure.draw(self.renderer)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\artist.py", line 41, in draw_wrapper
        return draw(artist, renderer, *args, **kwargs)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\figure.py", line 1863, in draw
        mimage._draw_list_compositing_images(
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\image.py", line 131, in _draw_list_compositing_images
        a.draw(renderer)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\artist.py", line 41, in draw_wrapper
        return draw(artist, renderer, *args, **kwargs)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\cbook\deprecation.py", line 411, in wrapper
        return func(*inner_args, **inner_kwargs)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\axes\_base.py", line 2747, in draw
        mimage._draw_list_compositing_images(renderer, self, artists)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\image.py", line 131, in _draw_list_compositing_images
        a.draw(renderer)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\artist.py", line 41, in draw_wrapper
        return draw(artist, renderer, *args, **kwargs)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\text.py", line 679, in draw
        bbox, info, descent = textobj._get_layout(renderer)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\text.py", line 293, in _get_layout
        w, h, d = renderer.get_text_width_height_descent(
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\backends\backend_agg.py", line 233, in get_text_width_height_descent
        self.mathtext_parser.parse(s, self.dpi, prop)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\mathtext.py", line 3340, in parse
        return self._parse_cached(
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\mathtext.py", line 3364, in _parse_cached
        box = self._parser.parse(s, font_output, fontsize, dpi)
      File "C:\Users\Etienne\.julia\Conda_env\lib\site-packages\matplotlib\mathtext.py", line 2619, in parse
        raise ValueError("\n".join(["",
    ValueError: 
    \displaystyle \left[\begin{array}{cccccc}1 & \frac{1}{2} & \frac{1}{3} & \frac{1}{4} & \frac{1}{5} & \frac{1}{6}\\\frac{1}{2} & \frac{1}{3} & \frac{1}{4} & \frac{1}{5} & \frac{1}{6} & \frac{1}{7}\\\frac{1}{3} & \frac{1}{4} & \frac{1}{5} & \frac{1}{6} & \frac{1}{7} & \frac{1}{8}\\\frac{1}{4} & \frac{1}{5} & \frac{1}{6} & \frac{1}{7} & \frac{1}{8} & \frac{1}{9}\\\frac{1}{5} & \frac{1}{6} & \frac{1}{7} & \frac{1}{8} & \frac{1}{9} & \frac{1}{10}\\\frac{1}{6} & \frac{1}{7} & \frac{1}{8} & \frac{1}{9} & \frac{1}{10} & \frac{1}{11}\end{array}\right]
    ^
    Unknown symbol: \displaystyle, found '\'  (at char 0), (line:1, col:1)
    
    De plus, je ne vois pas pourquoi Python va chercher des chose dans un répertoire Julia.

    Cordialement,

    Rescassol
  • Bonjour,

    Peut-être faut-il mettre 'text.usetex' à True dans les paramètres matplotlib. J'ai un exemple comme ça qui traîne :
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    
    mpl.use('pgf')
    mpl.rcParams.update({
        'pgf.texsystem': 'pdflatex',
        'text.usetex': True,
        'pgf.preamble': ''.join([r'\usepackage[T1]{fontenc}'
                                 r'\usepackage{xcolor}'
                                 r'\usepackage{bm}']),
        })
    
    fig = plt.figure()
    
    (...)
    
  • Bonjour Brian,

    En rajoutant ce que tu dit, j'obtiens maintenant:
    C:\Users\Etienne\Documents\Python\Programmes\TestHilbert01.py:35: UserWarning: Matplotlib is currently using pgf, which is a non-GUI backend, so cannot show the figure.
      plt.show()
    
    Cordialement,

    Rescassol
  • Eh, j'ai donné un exemple pour t'éviter de passer du temps à chercher la syntaxe, mais je n'ai pas dit de tout recopier dans ton code ! PGF, c'est surtout pour utiliser TikZ. Ici, tu t'en cognes. Comme je l'ai indiqué, l'option cruciale dont tu sembles avoir besoin est 'text.usetex' — d'après un message d'erreur que tu as posté.
  • Concernant l'histoire de l'accent (je ne me prononce surtout pas sur le reste), il y a la commande \text{} pour écrire du texte dans un environnement mathématique : \text{Déterminant}
  • Pardon, je n'avais pas remarqué que le code d'origine avait déjà
    rc('text',usetex=True)
    
    Cela doit être une syntaxe un peu plus ancienne que celle que j'ai postée, mais diminue les chances que ma suggestion fonctionne. D'autre part, je n'arrive pas à tester l'exemple chez moi car ça sort :
      File ".../code.py", line 8, in <module>
        H = Matrix(n,n,lambda i,j: Rational(1,1+i+j))
    NameError: name 'Matrix' is not defined
    
    Pas d'expérience avec SymPy...
  • L'erreur précédente était due au nom choisi pour le fichier de test, code.py. En le renommant, pouf, ça marche mieux. Ceci est sans doute imputable à un auteur de bibliothèque Python qui n'a pas compris l'intérêt des imports relatifs... ou a oublié de les utiliser.

    Bref, après avoir examiné le code TeX produit et compilé par matplotlib et procédé à quelques ajustements, je suis arrivé à ça (je charge amsmath pour pouvoir utiliser \text, ainsi que l'a proposé Éric) :
    #! /usr/bin/env python3
    
    import matplotlib.pyplot as plt
    from sympy import *
    
    n = 6
    H = Matrix(n, n, lambda i, j: Rational(1, 1+i+j))
    LH = latex(H, mat_str="array")
    DH = H.det()
    
    plt.rc('text', usetex=True)
    plt.rc('text.latex', preamble=r'\usepackage{amsmath}\usepackage{fixcmex}')
    
    fig = plt.figure()
    ax = plt.Axes(fig, [0, 0, 1, 1])
    ax.set_axis_off()
    fig.add_axes(ax)
    
    plt.text(0.1, 0.6, r"\renewcommand{\arraystretch}{1.2}"
                       r"\setlength{\arraycolsep}{0.4em}"
                       r"$H_{%d} = %s$" % (n, LH), size=50, color='r')
    plt.text(0.1, 0.1,
             r"$\text{Déterminant} = \frac{%d}{%d}$" % (DH.p, DH.q),
             size=40, color='r',
             bbox=dict(boxstyle='roundtooth, pad=0.6', facecolor='fuchsia',
                       edgecolor='b', alpha=0.3))
    fig.set_size_inches(10, 9)
    plt.show()
    
    Edit : utilisation de l'unité em plutôt que cm pour \arraycolsep et légère augmentation de la valeur donnée à \arraystretch.118380
  • Avec ce code, j'ai un problème d'encodage – le "é" n'est pas compris parce que « UnicodeEncodeError: 'ascii' codec can't encode character '\xe9' ».
  • Bonjour,

    Ça ne fonctionne toujours pas.
    Avant de me donner le message d'erreur que j'ai déjà donné, j'ai droit à l'ouverture de la fenêtre ci-jointe sur fond noir.
    Que je clique sur oui ou non ne change rien, matplotlib ouvre une fenêtre noire et sort avec le message d'erreur.

    Cordialement,

    Rescassol118384
  • @Rescassol

    Ton code comme le mien utilise usetex=True pour compiler les trucs de type texte avec LaTeX. Dans ton cas, il trouve MiKTeX. Ce dernier a une fonctionnalité d'installation des packages manquants à la volée ; à mon avis, c'est ça que ta capture d'écran montre. Tu devrais essayer d'installer toi-même les packages utilisés dans mon document avec le MiKTeX package manager ou je-ne-sais-quoi (il te manque peut-être 'fixcmex'). Quant au message d'erreur dont tu parles, je ne vois pas, car mon code n'utilise ni \' en mode maths, ni le backend PGF de matplotlib. Mais chaque problème l'un après l'autre.

    @Math Coss

    Je soupçonne un bug de matplotlib corrigé après la version installée chez toi. La mienne est 3.3.4. D'après le site de matplotlib, usetex supporte les entrées Unicode. La liste des versions a “fix various issues with usetex” au moins pour la version 3.2.2. Si tu regardes ton fichier matplotlib/texmanager.py, tu vas peut-être trouver la même chose que ceci dans la fonction make_tex(). Dans la version du fichier installée sur mon système, il n'y a pas le
    fh.write(s.encode('ascii'))
    
    susceptible de provoquer l'erreur que tu as rapportée, mais il y a ceci :
            Path(texfile).write_text(
                r"""
    %s
    \pagestyle{empty}
    \begin{document}
    %% The empty hbox ensures that a page is printed even for empty inputs, except
    %% when using psfrag which gets confused by it.
    \fontsize{%f}{%f}%%
    \ifdefined\psfrag\else\hbox{}\fi%%
    %s
    \end{document}
    """ % (self._get_preamble(), fontsize, fontsize * 1.25, fontcmd % tex),
                encoding='utf-8')
    
    Et cela permet d'écrire un 'é' sans erreur dans le fichier .tex généré par matplotlib. Donc je suppose que l'erreur doit partir, soit en mettant à jour matplotlib, soit en ajoutant :
    plt.rc('text.latex', unicode=True)
    
    Je précise que je ne peux pas tester cette dernière ligne avec ma version de matplotlib : c'est sans doute une technique obsolète.
  • Bonsoir,

    Finalement, ceci fonctionne et donne l'image ci-jointe:
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    
    from sympy import *
    
    def maxfig():
        mng = plt.get_current_fig_manager()
        mng.window.showMaximized()
    
    n=6
    H = Matrix(n,n,lambda i,j: Rational(1,1+i+j))
    LH=latex(H,mat_str = "array")
    DH=H.det()
    NumDH=str(DH.p)
    DenDH=str(DH.q)
    
    mpl.rcParams.update({'text.usetex': True})
    
    fig=plt.figure(linewidth=10, facecolor = 'gold', edgecolor='red')
    ax = plt.Axes(fig, [0, 0, 1, 1])
    ax.set_axis_off()
    fig.add_axes(ax)
    
    texte1=r'$H_{'+str(n)+'}=$'
    plt.text(0.3,0.6,texte1, size=40, color='b', fontweight='bold')
    
    texte2=r'$\displaystyle '+LH+'$'
    plt.text(0.4,0.6,texte2, size=50, color='b', fontweight='bold')
    
    texte3=r'$\displaystyle \hbox{Déterminant}=\frac{' + NumDH+'}{' + DenDH + '}$'
    plt.text(0.25,0.1,texte3, size=40, color='g', fontweight='bold', bbox=dict(boxstyle='roundtooth, pad=0.6', facecolor='cyan',ec='b', alpha=0.3))
    fig.set_size_inches(10, 9)
    
    plt.show()
    maxfig()
    
    J'ai réinstallé MikTex, Pyzo, et dans la foulée, TexMaker dont il n'est pas question ici.
    J'ai installé aussi Python 3.91, mais suis resté sur Python 3.83, car il y a des problèmes avec les plus récents.
    Par contre, tout est sur fond jaune, j'ai perdu mon fond blanc entouré d'une bande jaune et je ne maîtrise pas le cadrage, je vais chercher.
    J'ai encore une question, à quoi set l'instruction "fig.set_size_inches(10, 9)" ?

    Cordialement,

    Rescassol118516
  • Bonsoir,

    \hbox marche, évidemment, car TeX traite son contenu en mode horizontal (pas en mode maths). Mais ma solution prenait aussi soin d'arranger l'espacement entre les coefficients de la matrice, il me paraît dommage d'avoir jeté ça.

    Concernant le fond jaune, que crois-tu que le « facecolor = 'gold' » que tu as ajouté fait ? Le fig.set_size_inches(10, 9) règle la taille de la figure, bien sûr. C'est sans doute incomptatible avec ton maxfig().
  • Bonsoir,

    Voilà, c'est mieux comme ça:
    mpl.rcParams.update({'text.usetex': True})
    
    fig=plt.figure(linewidth=10, facecolor = 'gold', edgecolor='red')
    # ax = plt.Axes(fig, [0, 0, 1, 1])
    # ax.set_axis_off()
    # fig.add_axes(ax)
    
    plt.title("Matrice de Hilbert d'ordre "+str(n), fontsize=35, color='m', fontweight='bold')
    
    texte1=r'$H_{'+str(n)+'}=$'
    plt.text(0.3,0.6,texte1, size=40, color='b', fontweight='bold')
    
    texte2=r'$\displaystyle '+LH+'$'
    plt.text(0.4,0.6,texte2, size=40, color='b', fontweight='bold')
    
    texte3=r'$\displaystyle \hbox{Déterminant}=\frac{' + NumDH+'}{' + DenDH + '}$'
    plt.text(0.25,0.1,texte3, size=32, color='g', fontweight='bold', bbox=dict(boxstyle='roundtooth, pad=0.6', facecolor='cyan',ec='b', alpha=0.3))
    fig.set_size_inches(10, 9)
    
    plt.show()
    maxfig()
    
    Je crois qu'on peut dire que le problème est résolu, merci Brian et Math Coss.

    Cordialement,

    Rescassol118520
  • Bonsoir,
    Brian a écrit:
    Mais ma solution prenait aussi soin d'arranger l'espacement entre les coefficients de la matrice, il me paraît dommage d'avoir jeté ça.
    Tu as raison, Brian, ça m'avait échappé, j'ai remis ça et j'obtiens la figure ci-jointe.
    Si je met "text" à la place de "hbox", ça plante, même sans le "é".
    Je n'ai plus tout le fond jaune.
    Je te remercie pour tous tes efforts.
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    
    from sympy import *
    
    def maxfig():
        mng = plt.get_current_fig_manager()
        mng.window.showMaximized()
    
    n=6
    H = Matrix(n,n,lambda i,j: Rational(1,1+i+j))
    LH=latex(H,mat_str = "array")
    DH=H.det()
    NumDH=str(DH.p)
    DenDH=str(DH.q)
    
    mpl.rcParams.update({'text.usetex': True})
    
    fig=plt.figure(linewidth=10, facecolor = 'gold', edgecolor='red')
    
    plt.title("Matrice de Hilbert d'ordre "+str(n), fontsize=35, color='m', fontweight='bold')
    
    # texte1=r'$H_{'+str(n)+'}=$'
    # plt.text(0.3,0.6,texte1, size=40, color='b', fontweight='bold')
    #
    # texte2=r'$\displaystyle '+LH+'$'
    # plt.text(0.4,0.6,texte2, size=40, color='b', fontweight='bold')
    
    plt.text(0.3, 0.6, r"\renewcommand{\arraystretch}{1.2}"
                       r"\setlength{\arraycolsep}{0.4em}"
                       r"$H_{%d} = %s$" % (n, LH), size=30, color='r')
    
    texte3=r'$\displaystyle \hbox{Déterminant}=\frac{' + NumDH+'}{' + DenDH + '}$'
    plt.text(0.25,0.1,texte3, size=32, color='g', fontweight='bold', bbox=dict(boxstyle='roundtooth, pad=0.6', facecolor='cyan',ec='b', alpha=0.3))
    
    # plt.text(0.1, 0.1,
    #          r"$\text{Determinant} = \frac{%d}{%d}$" % (DH.p, DH.q),
    #          size=40, color='r',
    #          bbox=dict(boxstyle='roundtooth, pad=0.6',
    #          facecolor='fuchsia',
    #          edgecolor='b', alpha=0.3))
    
    fig.set_size_inches(10, 9)
    
    plt.show()
    maxfig()
    

    Cordialement,

    Rescassol118530
  • Pour un cas comme ça, utiliser \hbox est acceptable, je dirais. \mbox devrait aussi fonctionner et évite des problèmes en cas de \color directement dans le \hbox (\mbox est une commande LaTeX, \hbox une primitive TeX). Si tu veux utiliser \text, il faut charger le package LaTeX amsmath ; mon code le fait. Il charge aussi fixcmex pour que la police mathématique d'extension puisse être mise à l'échelle (je pense que ça ne joue que pour les crochets, ici).

    Sous Linux, tu peux voir les fichiers .tex (et .dvi) produits par matplotlib dans ~/.cache/matplotlib/tex.cache/. Cela m'a permis de remarquer la substitution de polices lorsque fixcmex n'est pas chargé. Mais j'admets que les effets ne sont pas dramatiques ici.
Connectez-vous ou Inscrivez-vous pour répondre.
Success message!