garrettj403 / SciencePlots

Matplotlib styles for scientific plotting
MIT License
6.96k stars 700 forks source link

How can I ensure that my figure size is consistent with the "figsize" passed in plt.subplot? #114

Closed yzbyx closed 4 months ago

yzbyx commented 5 months ago

Environment

System: Windows-10-10.0.22631-SP0
Python: 3.10.11 (tags/v3.10.11:7d4cc5a, Apr  5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
SciencePlots: 2.1.1
Matplotlib: 3.8.0
LaTeX distro: (Error reported due to lack of latex)

Affected styles

['science','no-latex']

Describe the issue here

The relavent code is here below:

import matplotlib.pyplot as plt
import seaborn as sns
sns.reset_orig()

import scienceplots

plt.style.use(['science','no-latex'])

matplotlib.rcParams['axes.unicode_minus'] = False
plt.rc('font',family='Times New Roman')
mm = 1 / 25.4
fontsize = 10
_width = 70 * mm
_ratio = 5 / 7
figsize = (_width, _width * _ratio)

fig, ax = plt.subplots(1, 2, figsize=figsize)

fig.subplots_adjust(wspace=0.3, bottom=0.22, top=0.95, right=0.88, left=0.1)

fig.savefig(r"E:\test.tif", dpi=500, pil_kwargs={"compression": "tiff_lzw"})

This problem usually occurs when figure has long axis number labels, figure seems to be readjusted.

However, when I use seaborn or pure matplotlib, the issue doesn't happen.

How can we replicate it? What have you tried? Please, add a reproducible example

Here is an example that can be successfully reproduced:

from PIL import Image
import numpy as np

import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns

sns.reset_orig()

import scienceplots
plt.style.use(['science','no-latex'])

matplotlib.rcParams['axes.unicode_minus'] = False
plt.rc('font',family='Times New Roman')
mm = 1 / 25.4
fontsize = 10
_width = 70 * mm
_ratio = 5 / 7
figsize = (_width, _width * _ratio)
#%%
data_x = np.linspace(0, 10, 100)
data_y = data_x ** 2
path = r"E:\PyProject\car-following-model-test\tests\cf_model_hysteresis"
#%%
fig, ax = plt.subplots(1, 2, figsize=figsize)
ax[0].plot(data_x, data_y)
fig.subplots_adjust(wspace=0.3, bottom=0.22, top=0.95, right=0.88, left=0.1)
print(fig)
fig.savefig(fr"{path}\test.tif", dpi=500, pil_kwargs={"compression": "tiff_lzw"})

im = np.array(Image.open(fr"{path}\test.tif"))
im.shape
#%%
sns.reset_orig()
fig, ax = plt.subplots(1, 2, figsize=figsize)
ax[0].plot(data_x, data_y)
fig.subplots_adjust(wspace=0.3, bottom=0.22, top=0.95, right=0.88, left=0.1)
print(fig)
fig.savefig(r"E:\PyProject\car-following-model-test\tests\cf_model_hysteresis\test_ori.tif", dpi=500, pil_kwargs={"compression": "tiff_lzw"})

im = np.array(Image.open(fr"{path}\test_ori.tif"))
im.shape
#%%

Extra info

The results of the above program:

Figure(275.591x196.85) (879, 1296, 4)

Figure(275.591x196.85) (984, 1377, 4)

echedey-ls commented 4 months ago

I see the problem. The science style does changes the layout of the figure via:

# Always save as 'tight'
savefig.bbox : tight

This script yields the same sizes

# %%
from PIL import Image
import numpy as np

import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns

sns.reset_orig()

import scienceplots
plt.style.use(['science','no-latex'])

matplotlib.rcParams['axes.unicode_minus'] = False
plt.rc('font',family='Times New Roman')
mm = 1 / 25.4
fontsize = 10
_width = 70 * mm
_ratio = 5 / 7
figsize = (_width, _width * _ratio)
#%%
data_x = np.linspace(0, 10, 100)
data_y = data_x ** 2
path = r"."
#%%
matplotlib.rcParams["savefig.bbox"] = matplotlib.rcParamsDefault["savefig.bbox"]
fig, ax = plt.subplots(1, 2, figsize=figsize)
ax[0].plot(data_x, data_y)
fig.subplots_adjust(wspace=0.3, bottom=0.22, top=0.95, right=0.88, left=0.1)
print(fig)
fig.savefig(fr"{path}\test.tif", dpi=500, pil_kwargs={"compression": "tiff_lzw"})

im = np.array(Image.open(fr"{path}\test.tif"))
im.shape
#%%
sns.reset_orig()
fig, ax = plt.subplots(1, 2, figsize=figsize)
ax[0].plot(data_x, data_y)
fig.subplots_adjust(wspace=0.3, bottom=0.22, top=0.95, right=0.88, left=0.1)
print(fig)
fig.savefig(fr"{path}\test_ori.tif", dpi=500, pil_kwargs={"compression": "tiff_lzw"})

im = np.array(Image.open(fr"{path}\test_ori.tif"))
im.shape
#%%

I don't think this is a bug that needs to be resolved; the science: savefig.bbox setting is there to reduce unused space in a paper. I'm closing this then, although you have raised a fair point regarding this package. I will write it down in the docs I'm preparing.

yzbyx commented 4 months ago

Thank you very much for the method you provided! This package has saved me a lot of work.