2

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!

N. Wad
  • 23
  • 4
  • Please fix the indentation of your code! It looks like you are setting `rcParams` *after* you opened the first figure, which would mean that matplotlib doesn't yet know how big a figure you want and therefore decides to use the default parameters. Try moving your `rcParams` assignments to the top of the script. – Thomas Kühn Feb 13 '19 at 06:50
  • 1
    Ah, that fixed it! Thanks so much Thomas, I feel like an idiot now.. – N. Wad Feb 13 '19 at 07:50
  • No problem. It's easy to get lost in with a tool this complex. – Thomas Kühn Feb 13 '19 at 07:57

2 Answers2

3

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.

Thomas Kühn
  • 9,412
  • 3
  • 47
  • 63
0

Always call the code to set the figure size at the start of For loop i.e. just after the for statement like below. It helped me resolve my issue

for j in range(i+1,count):
        plt.figure(figsize=(10,5));
Nitin G
  • 714
  • 7
  • 31