Vitaliy
Vitaliy

Reputation: 137

pyplot.subplots: different behavior in python and jupyter notebook

While taking part in kaggle competition, i got some weird problem. Basically, I am trying to convert vector representation of am image to png file. It worked perfectly in iPython, code below:

def drawing_to_np_prepare_data(drawing):
    drawing = eval(drawing)
    fig, ax = plt.subplots()
    plt.close(fig)
    print('[debug] ax=',ax)
    for x,y in drawing:
        ax.plot(x, y, marker='.')
        ax.axis('off')
    fig.canvas.draw()

    # Convert images to numpy array
    np_drawing = np.array(fig.canvas.renderer._renderer)

    print('[debug] fig_size=',fig.get_size_inches())
    print('[debug] dpi=',fig.dpi)

    print('[debug] shape=',np_drawing.shape)
    print('[debug] size=',np_drawing.size)
    print('[debug] shape=',np_drawing.shape)

    im = cv2.cvtColor(np_drawing.astype(np.uint8), cv2.COLOR_BGR2RGB)

    # compress
    compressed_array = io.BytesIO()
    np.savez_compressed(compressed_array, im)
    compressed_array.seek(0)
    print('[debug] size=',np_drawing.shape)
    return compressed_array 

The result shows:

[debug] ax=AxesSubplot(0.125,0.125;0.775x0.755)
[debug] fig_size= [6. 4.]
[debug] dpi= 72.0
[debug] np_drawing.size= 497664
[debug] shape= (288, 432, 4)
[debug] size= 1880

which satisfy my needs: i am getting an image with compressed size < 2Kb

However, when I run this code in python from CLI, I am getting quite different result:

[debug] ax=AxesSubplot(0.125,0.11;0.775x0.77)
[debug] fig_size= [6.4 4.8]
[debug] dpi= 100.0
[debug] np_drawing.size= 1228800
[debug] shape= (480, 640, 4)
[debug] size= 13096

as you can see, figure size, dpi, axes are different and as a result, size at the end are also different.

I can pass arguments to subplots:

plt.subplots(figsize=(6.,4.), dpi=72)

which corrects parameters except axes (and size, I guess because of different axes):

[debug] ax=AxesSubplot(0.125,0.11;0.775x0.77)
[debug] fig_size= [6. 4.]
[debug] dpi= 72.0
[debug] np_drawing.size= 497664
[debug] shape= (288, 432, 4)
[debug] size= 8214

Note: I've checked library versions and they are the same.

So, multiple questions arise:

  1. Why subplots give different axes, shape and resolution?

  2. How to correct axes?

  3. How to get the same behaviors in python?

I want to understand the what is going on. Thanks!

Upvotes: 0

Views: 975

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339580

To get the exact same settings in a script as in your notebook, open a notebook, run

%matplotlib inline
%config InlineBackend.rc

It'll print a dictionary of rcParams.

{'figure.figsize': (6.0, 4.0),
 'figure.facecolor': (1, 1, 1, 0),
 'figure.edgecolor': (1, 1, 1, 0),
 'font.size': 10,
 'figure.dpi': 72,
 'figure.subplot.bottom': 0.125}

Copy those to your python file as

newrc = {'figure.figsize': (6.0, 4.0),
         'figure.facecolor': (1, 1, 1, 0),
         'figure.edgecolor': (1, 1, 1, 0),
         'font.size': 10,
         'figure.dpi': 72,
         'figure.subplot.bottom': 0.125}

import matplotlib.pyplot as plt
plt.rcParams.update(newrc)

Then do your plots.

Whether or not this actually solves the problem of different renderer sizes cannot be tested because the question does not contain a runnable example.

Upvotes: 2

Related Questions