web-dev-qa-db-fra.com

Enregistrer un sous-tracé dans matplotlib

Est-il possible d'enregistrer (au format png) un sous-tracé individuel dans une figure matplotlib? Disons que j'ai

import pyplot.matplotlib as plt
ax1 = plt.subplot(121)
ax2 = plt.subplot(122)
ax1.plot([1,2,3],[4,5,6])    
ax2.plot([3,4,5],[7,8,9])

Est-il possible d'enregistrer chacun des deux sous-tracés dans des fichiers différents ou au moins de les copier séparément dans une nouvelle figure pour les enregistrer?

J'utilise la version 1.0.0 de matplotlib sur RHEL 5.

Merci,

Robert

42
Robert Franke

Bien que @Eli soit tout à fait correct qu'il n'est généralement pas nécessaire de le faire, c'est possible. savefig prend un bbox_inches argument qui peut être utilisé pour enregistrer de manière sélective uniquement une partie d'une figure dans une image.

Voici un exemple rapide:

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

# Make an example plot with two subplots...
fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)
ax1.plot(range(10), 'b-')

ax2 = fig.add_subplot(2,1,2)
ax2.plot(range(20), 'r^')

# Save the full figure...
fig.savefig('full_figure.png')

# Save just the portion _inside_ the second axis's boundaries
extent = ax2.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
fig.savefig('ax2_figure.png', bbox_inches=extent)

# Pad the saved area by 10% in the x-direction and 20% in the y-direction
fig.savefig('ax2_figure_expanded.png', bbox_inches=extent.expanded(1.1, 1.2))

Le chiffre complet: Full Example Figure


Zone à l'intérieur la deuxième sous-intrigue: Inside second subplot


Zone autour de la deuxième sous-intrigue rembourrée de 10% dans la direction x et 20% dans la direction y: Full second subplot

69
Joe Kington

En appliquant la fonction full_extent() dans une réponse de @Joe 3 ans plus tard de ici , vous pouvez obtenir exactement ce que l'OP recherchait. Alternativement, vous pouvez utiliser Axes.get_tightbbox() qui donne un cadre de délimitation un peu plus serré

import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from matplotlib.transforms import Bbox

def full_extent(ax, pad=0.0):
    """Get the full extent of an axes, including axes labels, tick labels, and
    titles."""
    # For text objects, we need to draw the figure first, otherwise the extents
    # are undefined.
    ax.figure.canvas.draw()
    items = ax.get_xticklabels() + ax.get_yticklabels() 
#    items += [ax, ax.title, ax.xaxis.label, ax.yaxis.label]
    items += [ax, ax.title]
    bbox = Bbox.union([item.get_window_extent() for item in items])

    return bbox.expanded(1.0 + pad, 1.0 + pad)

# Make an example plot with two subplots...
fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)
ax1.plot(range(10), 'b-')

ax2 = fig.add_subplot(2,1,2)
ax2.plot(range(20), 'r^')

# Save the full figure...
fig.savefig('full_figure.png')

# Save just the portion _inside_ the second axis's boundaries
extent = full_extent(ax2).transformed(fig.dpi_scale_trans.inverted())
# Alternatively,
# extent = ax.get_tightbbox(fig.canvas.renderer).transformed(fig.dpi_scale_trans.inverted())
fig.savefig('ax2_figure.png', bbox_inches=extent)

Je posterais une photo mais je manque de points de réputation

20
Matt Gibson