'matplotlib savefig() size control

I wrote a function that took a dataframe generated from Pandas and produce a heatmap:

def drawHeatMap(df, city, province, collector, classtype, color, titleposy):
    try:
        thePlot = pl.matshow(df.values, cmap='PuBuGn')
        pl.colorbar(thePlot, orientation='vertical')
        aTitle = (classtype + ' Composition Changes Over Time in ' + city + 
                ', ' + province + '\n' + collector + ' collector. ' + 'rs100')
        pl.title(aTitle, x=0.5, y=titleposy, style='oblique', weight='bold')
        pl.xlabel('Collection Time')
        pl.xticks(range(len(df.columns)), df.columns, rotation=90)
        pl.yticks(range(len(df.index)), df.index)
        fileName = (classtype + '-' + city + '-' 
                + province + '-' + collector + '.png')
        pl.savefig(fileName)
    except ZeroDivisionError:
        errorMessage = ('No Data Avaiable for ' + city + ', ' + province + 
                ' with ' + collector + ' collector.')
        print errorMessage

The problem I am having is, savefig() would save figures with the axis and graphics trimmed. I have to use show(), maximize the graph and manually save the figure with the GUI button myself.

How can I fix my function so savefig() would save the graphs properly? I tried to put a line like this before pl.savefig() to control my figure:

       pl.figure(figsize=....) 

but I end up producing some empty graphs. What is the proper way to write a matplotlib function that give me full control on saving the figure?

Updated with Example of a problem figure: enter image description here



Solution 1:[1]

I added plt.tight_layout() before savefig(), and it solved the trimming issue I had. Maybe it will help yours as well.

EDIT: I also set the figure size at the begining rcParams['figure.figsize'] = 40, 12(you can set your own width and height)

Solution 2:[2]

From the documentation, you can add a dpi argument to set the resolution.

savefig('foo.png', dpi=199)

Solution 3:[3]

Short:
You just need to call pl.figure(figsize=...) before you call the pl.colorbar (and all the other stuff)

Explanation:
pl.figure creates a new figure (with given size), on which all pl.* methods will act in the following.
So pl.savefig just saves the last created figure, which is empty if you created a new one in the preceeding line.

Solution 4:[4]

before calling pl.savefig(fileName) do plt.tight_layout()

Solution 5:[5]

The command pl.figure() makes a new matplotlib figure. The figure size is set at instantiation. You do want to set the figure size, but you already have a figure. So you were on the right track, but try this instead:

def drawHeatMap(df, city, province, collector, classtype, color, titleposy):
    try:
        fig = pl.figure(figsize=(....))
        ax = fig.add_subplot(111)
        ax.matshow(df.values, cmap='PuBuGn')
        pl.colorbar()
        aTitle = classtype + ' Composition Changes Over Time in ' + city + ', ' + province + '\n' + collector + ' collector. ' + 'rs100'
        ax.set_title(aTitle, x=0.5, y=titleposy, style='oblique', weight='bold')
        ax.set_xlabel('Collection Time')
        ax.set_xticks(range(len(df.columns)), df.columns, rotation=90)
        ax.set_yticks(range(len(df.index)), df.index)
        fileName = classtype + '-' + city + '-' + province + '-' + collector + '.png'
        fig.savefig(fileName)
    except ZeroDivisionError:
        errorMessage = 'No Data Available for ' + city + ', ' + province + ' with ' + collector + ' collector.'
        print errorMessage

Solution 6:[6]

you can use the dpi parameter to set The resolution in dots per inch in savefig method. so you can control the figure size. for example, if you this code :

import pandas as pd
import matplotlib.pyplot as plt


df = pd.DataFrame({ 
    'ser1' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] , 
    'ser2' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
    })

df.plot()
plt.savefig("100.png" , dpi = 100)
plt.savefig("300.png" , dpi = 300)

100.png will be :

100.png

300.png will be :

300.png

Solution 7:[7]

To save figure on desired size

figure = plt.gcf()
figure.set_size_inches(width/100, height/100)
plt.axis('off')
plt.plot(x, y, color='black', linewidth=1)
plt.gca().set_position([0, 0, 1, 1])  
plt.savefig("image.png", dpi=100)

Solution 8:[8]

You need to use the set_size_inches function and the dpi parameter in savefig together to define the saved figure size in pixels.

  1. set the figure width and height in inches through plt.gcf().set_size_inches(10, 5).
  2. define the dpi while saving the figure plt.savefig('filename.png', dpi=100). dpi means "dot per inch".
  3. The saved figure width will be 1000(10x100) and the height will be 500(5x100). The saved figure size will be 1000x500 in pixels.

Sample code piece:

import matplotlib.pyplot as plt


def fig_size():
    plt.plot(range(0, 10), range(0, 10))
    plt.gcf().set_size_inches(10, 5)
    plt.savefig('charts/fig_size.png', dpi=200)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 hitzg
Solution 3 sodd
Solution 4 Kumail Haider
Solution 5 G-Nugget
Solution 6
Solution 7 Zorro
Solution 8