Skip to content

[Bug]: Pickle round-tripping a figure incorrectly restores its original DPI instead of a DPI explicitly changed via Figure.set_dpi(). #32053

Description

@RippleTester

Bug summary

Pickle round-tripping a figure incorrectly restores its original DPI instead of a DPI explicitly changed via Figure.set_dpi().

Code for reproduction

import pickle
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(5, 3), dpi=100)
ax.plot([0, 1, 2, 3], [0, 1, 4, 9], label="quadratic")
ax.set_title("DPI round trip")
ax.legend()

print("Original DPI:", fig.get_dpi())
fig.set_dpi(150)
print("DPI after public set_dpi(150):", fig.get_dpi())

restored = pickle.loads(pickle.dumps(fig))
print("DPI after pickle round trip:", restored.get_dpi())
print("Line count:", len(restored.axes[0].lines))

plt.close(fig)
plt.close(restored)

Actual outcome

Original DPI: 100
DPI after public set_dpi(150): 150
DPI after pickle round trip: 100
Line count: 1

Expected outcome

The explicitly configured DPI should be preserved across pickle round-tripping:

Original DPI: 100
DPI after public set_dpi(150): 150
DPI after pickle round trip: 150
Line count: 1

Additional information

This regression was introduced by PR #23476.

The new code replaces the current DPI with _original_dpi whenever that state entry exists. This correctly discards a transient DPI change made for a canvas device-pixel ratio, but _original_dpi is established independently of later public calls to Figure.set_dpi(). Consequently, a figure intentionally changed from 100 to 150 DPI is serialized with 100 DPI instead of 150 DPI, causing a loss of public figure state.

Operating system

Linux

Matplotlib Version

3.11.0

Matplotlib Backend

agg

Python version

3.11.13

Jupyter version

N/A

Installation

N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions