Search code examples
pythonmatplotlibsizefigure

Matplotlib: First Plot created in loop is not saved with the specified 'figsize' in rcParams


I have read similar of similar issues with Jupyter Notebooks such as in: Matplotlib figsize not respected

My function generates and saves plots using a for loop. The first plot generated is always smaller and lacks the formatting of the others. If I run the function twice, the issue is fixed.

I have tried to specify a specific backend: matplotlib.use('Agg'), but that has had no effect.

        fig, ax = plt.subplots()
        #Format xlabel and grid
        plt.xlabel('Date', weight = 'bold')
        plt.grid(alpha = 2.0)
        #Clear legend
        legendList = legendList[0:0]
        #Format data to required units and set axis label
        for i in range(len(plotData.columns)):
            plt.ylabel(splitUnits + ' ' + '[' + units + ']', weight = 'bold')
            #Plot each data column on axis
            ax = self.formatAxis(ax)
            ax.plot(plotData.iloc[:,i], formatList[i], linewidth=2, markersize=2)

            #Set Legend and remove brackets from array
            legendList.append(str(plotData.iloc[:,[i]].columns.values[-1]).lstrip('(').rstrip(')')) 

        plt.legend(loc='upper right', labels=legendList)

        #Resize graph and set resolution
        plt.rcParams['figure.figsize'] = (12, 7)        #Width and height of graph 12,7
        dpi = 250    #108 previously
        plt.rcParams['figure.dpi'] = dpi

        plt.rcParams['figure.figsize'] = (12, 7)
        #Format y-axis grid and ticks and legend format
        ax.grid(which='minor', alpha=0.4)     #...alpha controls gridline opacity
        ax.margins(y=0.85)
        ymin = ax.get_yticks()[0]
        ymax = ax.get_ylim()[-1]
        step = ax.get_yticks()[1] - ax.get_yticks()[0]
        y_minor = np.arange(ymin, ymax, step/5)
        ax.set_yticks(y_minor, minor=True)
        ax.set_ylim([ymin, ymax])

        #Import Logo, and insert in graph
        self.manageDir('working')
        im = image.imread('logo4.png')
        fig.figimage(im, 280, 1360, zorder=1)     #130, 580 represent logo placement in graph
        plt.close('all')

        fig.savefig('Plot ' + str(plotNo) + '.png', bbox_inches='tight', pad_inches=0.3)

'PlotData' is a dataframe where all the values are plotted on the same axis and is then saved. The first image saved to the file seems to use the default figure size settings, but all the other plots saved use the specified (12, 7) setting. If anyone has any ideas or would like any information, please let me know! Thanks!


Solution

  • The figure settings stored in rcParams are read at the moment that plt.figure() or plt.subplots() is called. Therefore, in order for your settings in rcParams to work correctly, you have to move these assignments to before you create your figures. Best would be to move all rcParams assignments to the beginning of your script.

    Alternatively, you can change the figure size and resolution retrospectively by using the commands fig.set_size_inches() and fig.set_dpi(), respectively.