Skip to content

Commit

Permalink
Fix saving to pdf and aspect_ratios
Browse files Browse the repository at this point in the history
fixes #885
  • Loading branch information
has2k1 committed Nov 5, 2024
1 parent 5646c8d commit d459a89
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 30 deletions.
3 changes: 3 additions & 0 deletions doc/changelog.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ title: Changelog
- In quarto documents make the output `retina` even if the `fig-format` is
`png`.

- Fixed bug where you could not save as pdf if also specifying the
`aspect_ratio`. ({{< issue 885 >}})

## v0.14.0
(2024-10-28)

Expand Down
7 changes: 7 additions & 0 deletions plotnine/_mpl/_plot_side_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ class WHSpaceParts:
wspace: float # mpl.subplotpars.wspace
hspace: float # mpl.subplotpars.hspace

@property
def aspect_ratio(self) -> float:
"""
Aspect ratio of the panels
"""
return (self.h * self.H) / (self.w * self.W)


@dataclass
class _side_spaces(ABC):
Expand Down
47 changes: 17 additions & 30 deletions plotnine/_mpl/_plotnine_tight_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from __future__ import annotations

import typing
from copy import deepcopy
from dataclasses import dataclass

from ._plot_side_space import LRTBSpaces, WHSpaceParts, calculate_panel_spacing
Expand Down Expand Up @@ -56,6 +55,7 @@ class TightParams:
All parameters computed for the plotnine tight layout engine
"""

facet: facet
sides: LRTBSpaces
gullies: WHSpaceParts

Expand All @@ -69,32 +69,26 @@ def __post_init__(self):
hspace=self.gullies.hspace,
)

def to_aspect_ratio(
self, facet: facet, ratio: float, parts: WHSpaceParts
) -> TightParams:
"""
Modify TightParams to get a given aspect ratio
"""
current_ratio = (parts.h * parts.H) / (parts.w * parts.W)
increase_aspect_ratio = ratio > current_ratio
if increase_aspect_ratio: # Taller panel
return self._reduce_width(facet, ratio, parts)
else:
return self._reduce_height(facet, ratio, parts)

def _reduce_height(
self, facet: facet, ratio: float, parts: WHSpaceParts
) -> TightParams:
if (ratio := self.facet._aspect_ratio()) is not None:
current_ratio = self.gullies.aspect_ratio
if ratio > current_ratio:
# Increase aspect ratio, taller panels
self._reduce_width(ratio)
elif ratio < current_ratio:
# Increase aspect ratio, wider panels
self._reduce_height(ratio)

def _reduce_height(self, ratio: float):
"""
Reduce the height of axes to get the aspect ratio
"""
self = deepcopy(self)
parts = self.gullies

# New height w.r.t figure height
h1 = ratio * parts.w * (parts.W / parts.H)

# Half of the total vertical reduction w.r.t figure height
dh = (parts.h - h1) * facet.nrow / 2
dh = (parts.h - h1) * self.facet.nrow / 2

# Reduce plot area height
self.params.top -= dh
Expand All @@ -104,21 +98,18 @@ def _reduce_height(
# Add more vertical plot margin
self.sides.t.plot_margin += dh
self.sides.b.plot_margin += dh
return self

def _reduce_width(
self, facet: facet, ratio: float, parts: WHSpaceParts
) -> TightParams:
def _reduce_width(self, ratio: float):
"""
Reduce the width of axes to get the aspect ratio
"""
self = deepcopy(self)
parts = self.gullies

# New width w.r.t figure width
w1 = (parts.h * parts.H) / (ratio * parts.W)

# Half of the total horizontal reduction w.r.t figure width
dw = (parts.w - w1) * facet.ncol / 2
dw = (parts.w - w1) * self.facet.ncol / 2

# Reduce width
self.params.left += dw
Expand All @@ -128,7 +119,6 @@ def _reduce_width(
# Add more horizontal margin
self.sides.l.plot_margin += dw
self.sides.r.plot_margin += dw
return self


def get_plotnine_tight_layout(pack: LayoutPack) -> TightParams:
Expand All @@ -137,10 +127,7 @@ def get_plotnine_tight_layout(pack: LayoutPack) -> TightParams:
"""
sides = LRTBSpaces(pack)
gullies = calculate_panel_spacing(pack, sides)
tight_params = TightParams(sides, gullies)
ratio = pack.facet._aspect_ratio()
if ratio is not None:
tight_params = tight_params.to_aspect_ratio(pack.facet, ratio, gullies)
tight_params = TightParams(pack.facet, sides, gullies)
return tight_params


Expand Down

0 comments on commit d459a89

Please sign in to comment.