2017-06-20 3 views
4

J'essaye de tracer un heatmap avec seaborn et l'exporter vers pgf pour l'importer facilement dans Latex. Cela fonctionne plus ou moins, la seule chose qui me dérange est que la barre pour les couleurs est exportée en tant que png supplémentaire.Exportation heatmap seaborn à pleine pgf

Donc, si je lance l'exportation vers PGF je reçois les éléments suivants:

  • test.pgf
  • test img0.png

C'est sans aucun doute comme non souhaitable .png n'est pas mise à l'échelle bien. Certains MWE:

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

df = pd.DataFrame.from_csv("test.csv", sep=',') 

sns.set('paper', 'white', rc={'font.size': 10, 'axes.labelsize': 10, 'legend.fontsize': 8, 'axes.titlesize': 10, 
           'xtick.labelsize': 8, 
           'ytick.labelsize': 8, "pgf.rcfonts": False}) 
plt.rc('font', **{'family': 'serif', 'serif': ['Times']}) 
plt.rc('text', usetex=True) 
fig = plt.figure() 
ax = sns.heatmap(df, linewidths=.5) 
fig.savefig('test.pdf') 
fig.savefig('test.pgf') 

Et le contenu de test.csv:

0,1,2,3,4 
1,1,1,1,1 
2,2,2,2,2 
3,3,3,3,3 

Quelqu'un at-il une solution pour inclure la barre de couleur dans la sortie de PGF?

+1

J'ai testé votre code sur seaborn 0.7.0 et matplotlib 1.5.1 dans python 2.7 et python 3.5. Exécution de la sortie de pgf à travers le latex m'a donné une belle figure avec colourbar. Pouvez-vous inclure votre sortie dans la question? – Daan

+0

Je suppose que le code fonctionne bien. Mais le problème avec OP est qu'ils veulent inclure 'test-img0.png' dans la sortie de pgf et non dans un fichier png séparé. – ImportanceOfBeingErnest

+0

Je suis allé un peu trop vite là-bas, merci de me l'indiquer @ImportanceOfBeingErnest! – Daan

Répondre

3

J'ai découvert quelques particularités dans les bibliothèques qui exportent vers pgf/tikz. D'abord, dans matplotlib, le quadmesh (c'est-à-dire le heatmap) est exporté correctement vers pgf, mais la barre de couleurs est exportée en tant que png (ce que l'op rencontré).

J'ai essayé la même chose avec la bibliothèque matplotlib2tikz. dans ce cas, le quadmesh est exporté en tant que png, mais la palette de couleurs peut être exportée correctement. Toutefois, si vous supprimez la carte thermique, par exemple en traçant la palette de couleurs dans un Axes distinct et en effaçant les axes de la carte thermique, la barre de couleurs est exportée en tant que png. Donc, si vous combinez la sortie de deux exportations, vous pouvez les avoir toutes les deux.

Le heatmap:

import matplotlib.pyplot as plt 
import pandas as pd 
import seaborn as sns 
df = pd.DataFrame.from_csv("test.csv", sep=',') 

sns.set('paper', 'white', 
     rc={'font.size': 10, 'axes.labelsize': 10, 
      'legend.fontsize': 8, 'axes.titlesize': 10, 
      'xtick.labelsize': 8,'ytick.labelsize': 8, 
      "pgf.rcfonts": False, 
      }) 
plt.rc('font', **{'family': 'serif', 'serif': ['Times']}) 
plt.rc('text', usetex=True) 
fig, ax = plt.subplots(figsize=(6,6)) 
ax = sns.heatmap(df, linewidths=.5, ax=ax, cbar=False) 
fig.savefig('heatmap_nocbar.pgf') 

Notez que je supprime le tracé du colorbar avec cbar=False

ensuite obtenir le colorbar:

import matplotlib.pyplot as plt 
import pandas as pd 
import seaborn as sns 
from matplotlib2tikz import save as tikz_save 

df = pd.DataFrame.from_csv("test.csv", sep=',') 

sns.set('paper', 'white', 
     rc={'font.size': 10, 'axes.labelsize': 10, 
      'legend.fontsize': 8, 'axes.titlesize': 10, 
      'xtick.labelsize': 8,'ytick.labelsize': 8, 
      "pgf.rcfonts": False, 
      }) 
plt.rc('font', **{'family': 'serif', 'serif': ['Times']}) 
plt.rc('text', usetex=True) 
fig, ax = plt.subplots() 
ax = sns.heatmap(df, linewidths=.5, ax=ax,) 
tikz_save('colormap.tex', figure=fig, strict=True) 

La solution nécessite maintenant un travail sale. Je suis conscient que ce n'est vraiment pas une bonne pratique, mais c'est la seule façon que j'ai pu trouver.

Dans le fichier colormap.tex, vous devez supprimer toutes les lignes à l'exception de celles requises pour la palette de couleurs.

Les débuts de colormap.tex:

\begin{tikzpicture} 

\begin{axis}[ 

... % definition of axis: delete these lines 

colorbar, 
colormap={mymap}{[1pt] 
... 

Alors que vous obtenez ceci:

\begin{tikzpicture} 

\begin{axis}[ 
hide axis, 
colorbar, 
colormap={mymap}{[1pt] 
... 

A la fin du fichier, supprimez tout entre la fermeture des crochets et \end{axis}:

] 
... %delete these lines 
\end{axis} 

Cette modification du fichier peut être automatisée, I inclus un exemple dans le code sur github

Dans votre fichier TeX principal, vous pouvez ajouter ces deux figures

\input{heatmap_nocbar.pgf} 
\input{colorbar.tex} 

Si vous voulez un exemple de travail complet et les résultats complets, je mets tout de cette réponse sur github.

Ceci est probablement loin d'être une réponse parfaite pour vous, mais je manque des compétences python pour plonger plus profondément dans les backends de matplotlib et matplotlib2tikz pour donner un meilleur exemple.

+0

Je pensais que ce ne serait pas facile. Je vais essayer votre solution. Fusionner les fichiers automatiquement serait certainement une amélioration si. – Patrick

+0

J'ai écrit un extrait de code rapide pour extraire les lignes de colorbar.tex, @Patrick. Vous pouvez le trouver dans le repo github (lien en réponse) – Daan