web-dev-qa-db-fra.com

Les graphiques Matplotlib perdent la transparence lors de l'enregistrement au format .ps/.eps

Je ne parviens pas à enregistrer certaines parcelles avec des ellipsoïdes transparents si je tente de les sauvegarder avec des extensions .ps/.eps. 

Voici la parcelle enregistrée en tant que .png: png

Si je choisis de l’enregistrer en tant que fichier .ps/.eps, voici à quoi il ressemble:ps

Comment j’ai pu éviter cela, c’était d’utiliser ImageMagick pour convertir le png original en ps. Le seul problème est que l'image au format png est environ 90k, et devient juste en dessous de 4M après la conversion. Ce n'est pas bon car j'ai beaucoup de ces images, et la compilation de mon document au latex prendra trop de temps. Est-ce que quelqu'un a une solution à cela?

36
astromax

Le problème est que eps ne prend pas en charge les transparences de manière native.

Il y a peu d'options:

  1. pixellisez l'image et intégrez-la dans un fichier eps (comme le suggère @Molly) ou exportez-la au format PDF et convertissez-la à l'aide d'un outil externe (comme gs) (qui repose généralement sur la pixellisation)

  2. 'imite' la transparence, en donnant une couleur qui ressemble à la transparence sur un fond donné.

J'ai discuté de cette bien sûr une fois sur la liste de diffusion matplotlib } _, et j'ai eu la suggestion de rastériser, ce qui n'est pas réalisable car vous obtenez des images pixellisées ou énormes. Et ils ne s’adaptent pas très bien, par exemple, dans une publication.

Personnellement, j’utilise la deuxième approche, et bien que cela ne soit pas idéal, j’ai trouvé cela suffisant. J'ai écrit un petit script python qui implémente l'algorithme à partir de cet article SO pour obtenir une représentation RVB solide d'une couleur avec une transparence.

MODIFIER

Dans le cas spécifique de votre tracé, essayez d'utiliser le mot clé zorder pour ordonner les pièces tracées. Essayez d'utiliser zorder=10 pour l'ellipse bleue, zorder=11 pour le vert et zorder=12 pour les hexbins. 

De cette façon, le bleu devrait être en dessous de tout, puis l'ellipse verte et enfin les hexbins. Et l'intrigue devrait être lisible aussi avec des couleurs unies. Et si vous aimez les nuances de bleu et de vert que vous avez en png, vous pouvez essayer de jouer avec mimic_alpha.py.

EDIT 2

Si vous êtes sûr à 100% que vous devez utiliser eps, voici quelques solutions de contournement qui me viennent à l’esprit (et qui sont nettement plus moches que votre intrigue): 

  1. Tracez simplement les bordures d'ellipse au-dessus des hexbins. 
  2. Déterminez le centre et l’amplitude de chaque hexagone (éventuellement, supprimez toutes les cases de zéro) et créez un nuage de points en utilisant la même carte de couleur que dans hexbin et en ajustant la taille et la forme du marqueur à votre guise. Vous voudrez peut-être redessiner les bordures d'ellipses en plus de cela
23

Une autre alternative serait de les enregistrer au format pdf

savefig('myfigure.pdf')

Cela fonctionne avec pdflatex, si c’était la raison pour laquelle vous deviez utiliser eps et non pas svg.

10
P.R.

J'ai eu le même problème. Pour éviter la pixellisation, vous pouvez enregistrer l'image au format PDF, puis l'exécuter (du moins sur les systèmes Unix) dans un terminal:

pdftops -eps my.pdf my.eps

Ce qui donne un fichier .eps en sortie.

7
Poshpaws

Vous pouvez pixelliser la figure avant de l’enregistrer pour conserver la transparence dans le fichier eps:

ax.set_rasterized(True)
plt.savefig('rasterized_fig.eps')
7
Molly

J'ai résolu ceci en: 1) en ajoutant un set_rasterization_zorder (1) lors de la définition de la zone de figure:

fxsize=16
fysize=8
f = figure(num=None, figsize=(fxsize, fysize), dpi=180, facecolor='w',
edgecolor='k')
plt.subplots_adjust(
left    = (18/25.4)/fxsize, 
bottom  = (13/25.4)/fysize, 
right   = 1 - (8/25.4)/fxsize, 
top     = 1 - (8/25.4)/fysize)
subplots_adjust(hspace=0,wspace=0.1)
#f.suptitle('An overall title', size=20)
gs0 = gridspec.GridSpec(1, 2)

gs11 = gridspec.GridSpecFromSubplotSpec(1, 1, subplot_spec=gs0[0])

ax110 = plt.Subplot(f, gs11[0,0])
f.add_subplot(ax110)

ax110.set_rasterization_zorder(1)

2) un zorder = 0 dans chaque alpha = un nombre quelconque dans le tracé:

ax110.scatter(xs1,ys1  , marker='o', color='gray'  , s=1.5,zorder=0,alpha=0.3)#, label=label_bg)

et 3) enfin un rasterized = True lors de la sauvegarde:

P.savefig(str(PLOTFILENAME)+'.eps', rasterized=True)

Notez que cela peut ne pas fonctionner comme prévu avec le mot clé transparent à savefig car une couleur RGBA avec alpha <1 sur fond transparent sera rendue de la même manière que la couleur RGB avec alpha = 1.

2
Hugo

Comme mentionné ci-dessus, le meilleur et le plus simple choix (si vous ne voulez pas perdre de résolution) est de rasteriser la figure

f = plt.figure()
f.set_rasterized(True)

ax = f.add_subplot(111)

ax.set_rasterized(True)
f.savefig('figure_name.eps',rasterized=True,dpi=300)

De cette façon, vous pouvez également gérer la taille par dpi. En fait, vous pouvez également jouer avec le zorder ci-dessous pour appliquer la pixellisation:

ax.set_rasterization_zorder(0)

Remarque: Il est important de conserver f.set_rasterized (True) lorsque vous utilisez les fonctions plt.subplot et plt.subplot2grid. Sinon, la zone étiquette et coche n'apparaîtra pas dans le fichier .eps

1
Luis DG

Ma solution consiste à exporter le tracé sous forme de fichier .eps, de le charger dans Inkscape, par exemple, puis de le dissocier, de sélectionner l'objet pour lequel je souhaite définir la transparence et de modifier l'opacité du remplissage dans l'onglet "Remplissage et contour" . 

Vous pouvez enregistrer le fichier au format .svg si vous souhaitez l'ajuster ultérieurement, ou exporter l'image pour une publication. 

0
ab-user