plotnine 0.15.3__py3-none-any.whl → 0.16.0a2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. plotnine/_mpl/gridspec.py +50 -6
  2. plotnine/_mpl/layout_manager/__init__.py +2 -5
  3. plotnine/_mpl/layout_manager/_composition_layout_items.py +98 -0
  4. plotnine/_mpl/layout_manager/_composition_side_space.py +461 -0
  5. plotnine/_mpl/layout_manager/_engine.py +19 -58
  6. plotnine/_mpl/layout_manager/_grid.py +94 -0
  7. plotnine/_mpl/layout_manager/_layout_tree.py +402 -817
  8. plotnine/_mpl/layout_manager/{_layout_items.py → _plot_layout_items.py} +55 -278
  9. plotnine/_mpl/layout_manager/{_spaces.py → _plot_side_space.py} +111 -291
  10. plotnine/_mpl/layout_manager/_side_space.py +176 -0
  11. plotnine/_mpl/utils.py +259 -1
  12. plotnine/_utils/__init__.py +23 -3
  13. plotnine/_utils/context.py +9 -13
  14. plotnine/_utils/dataclasses.py +24 -0
  15. plotnine/_utils/ipython.py +4 -1
  16. plotnine/animation.py +13 -12
  17. plotnine/composition/__init__.py +6 -0
  18. plotnine/composition/_beside.py +13 -11
  19. plotnine/composition/_compose.py +263 -99
  20. plotnine/composition/_plot_annotation.py +75 -0
  21. plotnine/composition/_plot_layout.py +143 -0
  22. plotnine/composition/_plot_spacer.py +1 -1
  23. plotnine/composition/_stack.py +13 -11
  24. plotnine/composition/_types.py +28 -0
  25. plotnine/composition/_wrap.py +60 -0
  26. plotnine/facets/facet.py +9 -12
  27. plotnine/facets/facet_grid.py +2 -2
  28. plotnine/facets/facet_wrap.py +1 -1
  29. plotnine/geoms/geom.py +2 -2
  30. plotnine/geoms/geom_map.py +4 -5
  31. plotnine/geoms/geom_path.py +8 -7
  32. plotnine/geoms/geom_rug.py +6 -10
  33. plotnine/geoms/geom_text.py +5 -5
  34. plotnine/ggplot.py +63 -9
  35. plotnine/guides/guide.py +24 -6
  36. plotnine/guides/guide_colorbar.py +88 -46
  37. plotnine/guides/guide_legend.py +47 -20
  38. plotnine/guides/guides.py +2 -2
  39. plotnine/iapi.py +17 -1
  40. plotnine/scales/scale.py +1 -1
  41. plotnine/stats/binning.py +15 -43
  42. plotnine/stats/smoothers.py +7 -3
  43. plotnine/stats/stat.py +2 -2
  44. plotnine/stats/stat_density_2d.py +10 -6
  45. plotnine/stats/stat_pointdensity.py +8 -1
  46. plotnine/stats/stat_qq.py +5 -5
  47. plotnine/stats/stat_qq_line.py +6 -1
  48. plotnine/stats/stat_sina.py +19 -20
  49. plotnine/stats/stat_summary.py +4 -2
  50. plotnine/stats/stat_summary_bin.py +7 -1
  51. plotnine/themes/elements/element_line.py +2 -0
  52. plotnine/themes/elements/element_text.py +12 -1
  53. plotnine/themes/theme.py +18 -24
  54. plotnine/themes/themeable.py +17 -3
  55. plotnine/typing.py +9 -2
  56. {plotnine-0.15.3.dist-info → plotnine-0.16.0a2.dist-info}/METADATA +3 -3
  57. {plotnine-0.15.3.dist-info → plotnine-0.16.0a2.dist-info}/RECORD +60 -52
  58. {plotnine-0.15.3.dist-info → plotnine-0.16.0a2.dist-info}/WHEEL +1 -1
  59. plotnine/composition/_plotspec.py +0 -50
  60. {plotnine-0.15.3.dist-info → plotnine-0.16.0a2.dist-info}/licenses/LICENSE +0 -0
  61. {plotnine-0.15.3.dist-info → plotnine-0.16.0a2.dist-info}/top_level.txt +0 -0
@@ -11,116 +11,32 @@ such cases as when left or right margin are affected by xlabel.
11
11
 
12
12
  from __future__ import annotations
13
13
 
14
- from abc import ABC
15
- from dataclasses import dataclass, field, fields
14
+ from copy import copy
16
15
  from functools import cached_property
17
- from typing import TYPE_CHECKING, cast
16
+ from typing import TYPE_CHECKING
18
17
 
19
18
  from plotnine.exceptions import PlotnineError
20
19
  from plotnine.facets import facet_grid, facet_null, facet_wrap
21
20
 
22
- from ._layout_items import LayoutItems
21
+ from ._plot_layout_items import PlotLayoutItems
22
+ from ._side_space import GridSpecParams, _side_space
23
23
 
24
24
  if TYPE_CHECKING:
25
- from dataclasses import Field
26
- from typing import Generator
27
-
28
25
  from plotnine import ggplot
29
26
  from plotnine._mpl.gridspec import p9GridSpec
30
27
  from plotnine.iapi import outside_legend
31
- from plotnine.typing import Side
32
-
33
- # Note
34
- # Margins around the plot are specified in figure coordinates
35
- # We interpret that value to be a fraction of the width. So along
36
- # the vertical direction we multiply by W/H to get equal space
37
- # in both directions
38
-
39
-
40
- @dataclass
41
- class GridSpecParams:
42
- """
43
- Gridspec Parameters
44
- """
45
-
46
- left: float
47
- right: float
48
- top: float
49
- bottom: float
50
- wspace: float
51
- hspace: float
52
-
53
- @property
54
- def valid(self) -> bool:
55
- """
56
- Return True if the params will create a non-empty area
57
- """
58
- return self.top - self.bottom > 0 and self.right - self.left > 0
59
28
 
60
29
 
61
- @dataclass
62
- class _side_spaces(ABC):
30
+ class _plot_side_space(_side_space):
63
31
  """
64
- Base class to for spaces
65
-
66
- A *_space class does the book keeping for all the artists that may
67
- fall on that side of the panels. The same name may appear in multiple
68
- side classes (e.g. legend).
69
-
70
- The amount of space for each artist is computed in figure coordinates.
32
+ Base class for the side space around a plot
71
33
  """
72
34
 
73
- items: LayoutItems
74
-
75
- def __post_init__(self):
76
- self.side: Side = cast("Side", self.__class__.__name__[:-7])
77
- """
78
- Side of the panel(s) that this class applies to
79
- """
35
+ def __init__(self, items: PlotLayoutItems):
36
+ self.items = items
37
+ self.gridspec = items.plot._gridspec
80
38
  self._calculate()
81
39
 
82
- def _calculate(self):
83
- """
84
- Calculate the space taken up by each artist
85
- """
86
-
87
- @property
88
- def total(self) -> float:
89
- """
90
- Total space
91
- """
92
- return sum(getattr(self, f.name) for f in fields(self)[1:])
93
-
94
- def sum_upto(self, item: str) -> float:
95
- """
96
- Sum of space upto but not including item
97
-
98
- Sums from the edge of the figure i.e. the "plot_margin".
99
- """
100
-
101
- def _fields_upto(item: str) -> Generator[Field, None, None]:
102
- for f in fields(self)[1:]:
103
- if f.name == item:
104
- break
105
- yield f
106
-
107
- return sum(getattr(self, f.name) for f in _fields_upto(item))
108
-
109
- def sum_incl(self, item: str) -> float:
110
- """
111
- Sum of space upto and including the item
112
-
113
- Sums from the edge of the figure i.e. the "plot_margin".
114
- """
115
-
116
- def _fields_upto(item: str) -> Generator[Field, None, None]:
117
- for f in fields(self)[1:]:
118
- yield f
119
- if f.name == item:
120
- break
121
-
122
- return sum(getattr(self, f.name) for f in _fields_upto(item))
123
-
124
40
  @cached_property
125
41
  def _legend_size(self) -> tuple[float, float]:
126
42
  """
@@ -134,7 +50,7 @@ class _side_spaces(ABC):
134
50
  return (0, 0)
135
51
 
136
52
  ol: outside_legend = getattr(self.items.legends, self.side)
137
- return self.items.calc.size(ol.box)
53
+ return self.items.geometry.size(ol.box)
138
54
 
139
55
  @cached_property
140
56
  def legend_width(self) -> float:
@@ -150,62 +66,6 @@ class _side_spaces(ABC):
150
66
  """
151
67
  return self._legend_size[1]
152
68
 
153
- @cached_property
154
- def gs(self) -> p9GridSpec:
155
- """
156
- The gridspec of the plot
157
- """
158
- return self.items.plot._gridspec
159
-
160
- @property
161
- def offset(self) -> float:
162
- """
163
- Distance in figure dimensions from the edge of the figure
164
-
165
- Derived classes should override this method
166
-
167
- The space/margin and size consumed by artists is in figure dimensions
168
- but the exact position is relative to the position of the GridSpec
169
- within the figure. The offset accounts for the position of the
170
- GridSpec and allows us to accurately place artists using figure
171
- coordinates.
172
-
173
- Example of an offset
174
-
175
- Figure
176
- ----------------------------------------
177
- | |
178
- | Plot GridSpec |
179
- | -------------------------- |
180
- | offset | | |
181
- |<------->| X | |
182
- | | Panels GridSpec | |
183
- | | -------------------- | |
184
- | | | | | |
185
- | | | | | |
186
- | | | | | |
187
- | | | | | |
188
- | | -------------------- | |
189
- | | | |
190
- | -------------------------- |
191
- | |
192
- ----------------------------------------
193
- """
194
- return 0
195
-
196
- def to_figure_space(self, rel_value: float) -> float:
197
- """
198
- Convert value relative to the gridspec to one in figure space
199
-
200
- The result is meant to be used with transFigure transforms.
201
-
202
- Parameters
203
- ----------
204
- rel_value :
205
- Position relative to the position of the gridspec
206
- """
207
- return self.offset + rel_value
208
-
209
69
  @property
210
70
  def has_tag(self) -> bool:
211
71
  """
@@ -282,8 +142,7 @@ class _side_spaces(ABC):
282
142
  raise PlotnineError("Side has no axis title") from err
283
143
 
284
144
 
285
- @dataclass
286
- class left_spaces(_side_spaces):
145
+ class left_space(_plot_side_space):
287
146
  """
288
147
  Space in the figure for artists on the left of the panel area
289
148
 
@@ -355,7 +214,7 @@ class left_spaces(_side_spaces):
355
214
 
356
215
  def _calculate(self):
357
216
  theme = self.items.plot.theme
358
- calc = self.items.calc
217
+ geometry = self.items.geometry
359
218
  items = self.items
360
219
 
361
220
  self.plot_margin = theme.getp("plot_margin_left")
@@ -363,7 +222,7 @@ class left_spaces(_side_spaces):
363
222
  if self.has_tag and items.plot_tag:
364
223
  m = theme.get_margin("plot_tag").fig
365
224
  self.plot_tag_margin_left = m.l
366
- self.plot_tag = calc.width(items.plot_tag)
225
+ self.plot_tag = geometry.width(items.plot_tag)
367
226
  self.plot_tag_margin_right = m.r
368
227
 
369
228
  if items.legends and items.legends.left:
@@ -373,7 +232,7 @@ class left_spaces(_side_spaces):
373
232
  if items.axis_title_y:
374
233
  m = theme.get_margin("axis_title_y").fig
375
234
  self.axis_title_y_margin_left = m.l
376
- self.axis_title_y = calc.width(items.axis_title_y)
235
+ self.axis_title_y = geometry.width(items.axis_title_y)
377
236
  self.axis_title_y_margin_right = m.r
378
237
 
379
238
  # Account for the space consumed by the axis
@@ -407,7 +266,7 @@ class left_spaces(_side_spaces):
407
266
  (0, 0)----------------
408
267
 
409
268
  """
410
- return self.gs.bbox_relative.x0
269
+ return self.gridspec.bbox_relative.x0
411
270
 
412
271
  def x1(self, item: str) -> float:
413
272
  """
@@ -454,8 +313,7 @@ class left_spaces(_side_spaces):
454
313
  )
455
314
 
456
315
 
457
- @dataclass
458
- class right_spaces(_side_spaces):
316
+ class right_space(_plot_side_space):
459
317
  """
460
318
  Space in the figure for artists on the right of the panel area
461
319
 
@@ -475,14 +333,14 @@ class right_spaces(_side_spaces):
475
333
  def _calculate(self):
476
334
  items = self.items
477
335
  theme = self.items.plot.theme
478
- calc = self.items.calc
336
+ geometry = self.items.geometry
479
337
 
480
338
  self.plot_margin = theme.getp("plot_margin_right")
481
339
 
482
340
  if self.has_tag and items.plot_tag:
483
341
  m = theme.get_margin("plot_tag").fig
484
342
  self.plot_tag_margin_right = m.r
485
- self.plot_tag = calc.width(items.plot_tag)
343
+ self.plot_tag = geometry.width(items.plot_tag)
486
344
  self.plot_tag_margin_left = m.l
487
345
 
488
346
  if items.legends and items.legends.right:
@@ -513,7 +371,7 @@ class right_spaces(_side_spaces):
513
371
  (0, 0)---------------
514
372
 
515
373
  """
516
- return self.gs.bbox_relative.x1 - 1
374
+ return self.gridspec.bbox_relative.x1 - 1
517
375
 
518
376
  def x1(self, item: str) -> float:
519
377
  """
@@ -560,8 +418,7 @@ class right_spaces(_side_spaces):
560
418
  )
561
419
 
562
420
 
563
- @dataclass
564
- class top_spaces(_side_spaces):
421
+ class top_space(_plot_side_space):
565
422
  """
566
423
  Space in the figure for artists above the panel area
567
424
 
@@ -587,7 +444,7 @@ class top_spaces(_side_spaces):
587
444
  def _calculate(self):
588
445
  items = self.items
589
446
  theme = self.items.plot.theme
590
- calc = self.items.calc
447
+ geometry = self.items.geometry
591
448
  W, H = theme.getp("figure_size")
592
449
  F = W / H
593
450
 
@@ -596,19 +453,19 @@ class top_spaces(_side_spaces):
596
453
  if self.has_tag and items.plot_tag:
597
454
  m = theme.get_margin("plot_tag").fig
598
455
  self.plot_tag_margin_top = m.t
599
- self.plot_tag = calc.height(items.plot_tag)
456
+ self.plot_tag = geometry.height(items.plot_tag)
600
457
  self.plot_tag_margin_bottom = m.b
601
458
 
602
459
  if items.plot_title:
603
460
  m = theme.get_margin("plot_title").fig
604
461
  self.plot_title_margin_top = m.t * F
605
- self.plot_title = calc.height(items.plot_title)
462
+ self.plot_title = geometry.height(items.plot_title)
606
463
  self.plot_title_margin_bottom = m.b * F
607
464
 
608
465
  if items.plot_subtitle:
609
466
  m = theme.get_margin("plot_subtitle").fig
610
467
  self.plot_subtitle_margin_top = m.t * F
611
- self.plot_subtitle = calc.height(items.plot_subtitle)
468
+ self.plot_subtitle = geometry.height(items.plot_subtitle)
612
469
  self.plot_subtitle_margin_bottom = m.b * F
613
470
 
614
471
  if items.legends and items.legends.top:
@@ -642,7 +499,7 @@ class top_spaces(_side_spaces):
642
499
  | |
643
500
  (0, 0)----------------
644
501
  """
645
- return self.gs.bbox_relative.y1 - 1
502
+ return self.gridspec.bbox_relative.y1 - 1
646
503
 
647
504
  def y1(self, item: str) -> float:
648
505
  """
@@ -689,8 +546,7 @@ class top_spaces(_side_spaces):
689
546
  )
690
547
 
691
548
 
692
- @dataclass
693
- class bottom_spaces(_side_spaces):
549
+ class bottom_space(_plot_side_space):
694
550
  """
695
551
  Space in the figure for artists below the panel area
696
552
 
@@ -728,7 +584,7 @@ class bottom_spaces(_side_spaces):
728
584
  def _calculate(self):
729
585
  items = self.items
730
586
  theme = self.items.plot.theme
731
- calc = self.items.calc
587
+ geometry = self.items.geometry
732
588
  W, H = theme.getp("figure_size")
733
589
  F = W / H
734
590
 
@@ -737,13 +593,13 @@ class bottom_spaces(_side_spaces):
737
593
  if self.has_tag and items.plot_tag:
738
594
  m = theme.get_margin("plot_tag").fig
739
595
  self.plot_tag_margin_bottom = m.b
740
- self.plot_tag = calc.height(items.plot_tag)
596
+ self.plot_tag = geometry.height(items.plot_tag)
741
597
  self.plot_tag_margin_top = m.t
742
598
 
743
599
  if items.plot_caption:
744
600
  m = theme.get_margin("plot_caption").fig
745
601
  self.plot_caption_margin_bottom = m.b * F
746
- self.plot_caption = calc.height(items.plot_caption)
602
+ self.plot_caption = geometry.height(items.plot_caption)
747
603
  self.plot_caption_margin_top = m.t * F
748
604
 
749
605
  if items.legends and items.legends.bottom:
@@ -753,7 +609,7 @@ class bottom_spaces(_side_spaces):
753
609
  if items.axis_title_x:
754
610
  m = theme.get_margin("axis_title_x").fig
755
611
  self.axis_title_x_margin_bottom = m.b * F
756
- self.axis_title_x = calc.height(items.axis_title_x)
612
+ self.axis_title_x = geometry.height(items.axis_title_x)
757
613
  self.axis_title_x_margin_top = m.t * F
758
614
 
759
615
  # Account for the space consumed by the axis
@@ -789,7 +645,7 @@ class bottom_spaces(_side_spaces):
789
645
  | v |
790
646
  (0, 0)----------------
791
647
  """
792
- return self.gs.bbox_relative.y0
648
+ return self.gridspec.bbox_relative.y0
793
649
 
794
650
  def y1(self, item: str) -> float:
795
651
  """
@@ -836,8 +692,7 @@ class bottom_spaces(_side_spaces):
836
692
  )
837
693
 
838
694
 
839
- @dataclass
840
- class LayoutSpaces:
695
+ class PlotSideSpaces:
841
696
  """
842
697
  Compute the all the spaces required in the layout
843
698
 
@@ -853,56 +708,67 @@ class LayoutSpaces:
853
708
  them in their final positions.
854
709
  """
855
710
 
856
- plot: ggplot
857
-
858
- l: left_spaces = field(init=False)
859
- """All subspaces to the left of the panels"""
860
-
861
- r: right_spaces = field(init=False)
862
- """All subspaces to the right of the panels"""
863
-
864
- t: top_spaces = field(init=False)
865
- """All subspaces above the top of the panels"""
866
-
867
- b: bottom_spaces = field(init=False)
868
- """All subspaces below the bottom of the panels"""
869
-
870
- W: float = field(init=False, default=0)
711
+ W: float
871
712
  """Figure Width [inches]"""
872
713
 
873
- H: float = field(init=False, default=0)
714
+ H: float
874
715
  """Figure Height [inches]"""
875
716
 
876
- w: float = field(init=False, default=0)
717
+ w: float
877
718
  """Axes width w.r.t figure in [0, 1]"""
878
719
 
879
- h: float = field(init=False, default=0)
720
+ h: float
880
721
  """Axes height w.r.t figure in [0, 1]"""
881
722
 
882
- sh: float = field(init=False, default=0)
723
+ sh: float
883
724
  """horizontal spacing btn panels w.r.t figure"""
884
725
 
885
- sw: float = field(init=False, default=0)
726
+ sw: float
886
727
  """vertical spacing btn panels w.r.t figure"""
887
728
 
888
- gsparams: GridSpecParams = field(init=False, repr=False)
889
- """Grid spacing btn panels w.r.t figure"""
729
+ def __init__(self, plot: ggplot):
730
+ self.plot = plot
731
+ self.gridspec = plot._gridspec
732
+ self.sub_gridspec = plot._sub_gridspec
733
+ self.items = PlotLayoutItems(plot)
734
+
735
+ self.l = left_space(self.items)
736
+ """All subspaces to the left of the panels"""
737
+
738
+ self.r = right_space(self.items)
739
+ """All subspaces to the right of the panels"""
890
740
 
891
- def __post_init__(self):
892
- self.items = LayoutItems(self.plot)
893
- self.W, self.H = self.plot.theme.getp("figure_size")
741
+ self.t = top_space(self.items)
742
+ """All subspaces above the top of the panels"""
894
743
 
895
- # Calculate the spacing along the edges of the panel area
896
- # (spacing required by plotnine)
897
- self.l = left_spaces(self.items)
898
- self.r = right_spaces(self.items)
899
- self.t = top_spaces(self.items)
900
- self.b = bottom_spaces(self.items)
744
+ self.b = bottom_space(self.items)
745
+ """All subspaces below the bottom of the panels"""
901
746
 
902
- def get_gridspec_params(self) -> GridSpecParams:
903
- # Calculate the gridspec params
904
- # (spacing required by mpl)
905
- self.gsparams = self._calculate_panel_spacing()
747
+ self.W, self.H = plot.theme.getp("figure_size")
748
+
749
+ def arrange(self):
750
+ """
751
+ Resize plot and place artists in final positions around the panels
752
+ """
753
+ self.resize_gridspec()
754
+ self.items._move_artists(self)
755
+
756
+ def resize_gridspec(self):
757
+ """
758
+ Apply the space calculations to the sub_gridspec
759
+
760
+ After calling this method, the sub_gridspec will be appropriately
761
+ sized to accomodate the artists around the panels.
762
+ """
763
+ gsparams = self.calculate_gridspec_params()
764
+ gsparams.validate()
765
+ self.sub_gridspec.update_params_and_artists(gsparams)
766
+
767
+ def calculate_gridspec_params(self) -> GridSpecParams:
768
+ """
769
+ Grid spacing between panels w.r.t figure
770
+ """
771
+ gsparams = self._calculate_panel_spacing()
906
772
 
907
773
  # Adjust the spacing parameters for the desired aspect ratio
908
774
  # It is simpler to adjust for the aspect ratio than to calculate
@@ -912,26 +778,26 @@ class LayoutSpaces:
912
778
  current_ratio = self.aspect_ratio
913
779
  if ratio > current_ratio:
914
780
  # Increase aspect ratio, taller panels
915
- self._reduce_width(ratio)
781
+ gsparams = self._reduce_width(gsparams, ratio)
916
782
  elif ratio < current_ratio:
917
783
  # Increase aspect ratio, wider panels
918
- self._reduce_height(ratio)
784
+ gsparams = self._reduce_height(gsparams, ratio)
919
785
 
920
- return self.gsparams
786
+ return gsparams
921
787
 
922
788
  @property
923
789
  def plot_width(self) -> float:
924
790
  """
925
791
  Width [figure dimensions] of the whole plot
926
792
  """
927
- return self.plot._gridspec.bbox_relative.width
793
+ return float(self.gridspec.width)
928
794
 
929
795
  @property
930
796
  def plot_height(self) -> float:
931
797
  """
932
798
  Height [figure dimensions] of the whole plot
933
799
  """
934
- return self.plot._gridspec.bbox_relative.height
800
+ return float(self.gridspec.height)
935
801
 
936
802
  @property
937
803
  def panel_width(self) -> float:
@@ -948,66 +814,20 @@ class LayoutSpaces:
948
814
  return self.t.panel_top - self.b.panel_bottom
949
815
 
950
816
  @property
951
- def tag_width(self) -> float:
952
- """
953
- Width [figure dimensions] of space taken up by the tag
954
- """
955
- # Atleast one of these is zero
956
- return max(self.l.tag_width, self.r.tag_width)
957
-
958
- @property
959
- def tag_height(self) -> float:
817
+ def horizontal_space(self) -> float:
960
818
  """
961
- Height [figure dimensions] of space taken up by the tag
819
+ Horizontal non-panel space [figure dimensions]
962
820
  """
963
- # Atleast one of these is zero
964
- return max(self.t.tag_height, self.b.tag_height)
821
+ # The same as plot_width - panel_width
822
+ return self.l.total + self.r.total
965
823
 
966
824
  @property
967
- def left_tag_width(self) -> float:
825
+ def vertical_space(self) -> float:
968
826
  """
969
- Width [figure dimensions] of space taken up by a left tag
827
+ Vertical non-panel space [figure dimensions]
970
828
  """
971
- return self.l.tag_width
972
-
973
- @property
974
- def right_tag_width(self) -> float:
975
- """
976
- Width [figure dimensions] of space taken up by a right tag
977
- """
978
- return self.r.tag_width
979
-
980
- @property
981
- def top_tag_height(self) -> float:
982
- """
983
- Width [figure dimensions] of space taken up by a top tag
984
- """
985
- return self.t.tag_height
986
-
987
- @property
988
- def bottom_tag_height(self) -> float:
989
- """
990
- Height [figure dimensions] of space taken up by a bottom tag
991
- """
992
- return self.b.tag_height
993
-
994
- @property
995
- def left_axis_title_clearance(self) -> float:
996
- """
997
- Distance between the left y-axis title and the panel
998
-
999
- In figure dimensions.
1000
- """
1001
- return self.l.axis_title_clearance
1002
-
1003
- @property
1004
- def bottom_axis_title_clearance(self) -> float:
1005
- """
1006
- Distance between the bottom x-axis title and the panel
1007
-
1008
- In figure dimensions.
1009
- """
1010
- return self.b.axis_title_clearance
829
+ # The same as plot_height - panel_height
830
+ return self.t.total + self.b.total
1011
831
 
1012
832
  def increase_horizontal_plot_margin(self, dw: float):
1013
833
  """
@@ -1084,9 +904,6 @@ class LayoutSpaces:
1084
904
  ncol = self.plot.facet.ncol
1085
905
  nrow = self.plot.facet.nrow
1086
906
 
1087
- left, right = self.l.panel_left, self.r.panel_right
1088
- top, bottom = self.t.panel_top, self.b.panel_bottom
1089
-
1090
907
  # Both spacings are specified as fractions of the figure width
1091
908
  # Multiply the vertical by (W/H) so that the gullies along both
1092
909
  # directions are equally spaced.
@@ -1094,8 +911,8 @@ class LayoutSpaces:
1094
911
  self.sh = theme.getp("panel_spacing_y") * self.W / self.H
1095
912
 
1096
913
  # width and height of axes as fraction of figure width & height
1097
- self.w = ((right - left) - self.sw * (ncol - 1)) / ncol
1098
- self.h = ((top - bottom) - self.sh * (nrow - 1)) / nrow
914
+ self.w = (self.panel_width - self.sw * (ncol - 1)) / ncol
915
+ self.h = (self.panel_height - self.sh * (nrow - 1)) / nrow
1099
916
 
1100
917
  # Spacing as fraction of axes width & height
1101
918
  wspace = self.sw / self.w
@@ -1112,9 +929,6 @@ class LayoutSpaces:
1112
929
  ncol = facet.ncol
1113
930
  nrow = facet.nrow
1114
931
 
1115
- left, right = self.l.panel_left, self.r.panel_right
1116
- top, bottom = self.t.panel_top, self.b.panel_bottom
1117
-
1118
932
  # Both spacings are specified as fractions of the figure width
1119
933
  self.sw = theme.getp("panel_spacing_x")
1120
934
  self.sh = theme.getp("panel_spacing_y") * self.W / self.H
@@ -1143,8 +957,8 @@ class LayoutSpaces:
1143
957
  ) + self.items.axis_ticks_y_max_width_at("all")
1144
958
 
1145
959
  # width and height of axes as fraction of figure width & height
1146
- self.w = ((right - left) - self.sw * (ncol - 1)) / ncol
1147
- self.h = ((top - bottom) - self.sh * (nrow - 1)) / nrow
960
+ self.w = (self.panel_width - self.sw * (ncol - 1)) / ncol
961
+ self.h = (self.panel_height - self.sh * (nrow - 1)) / nrow
1148
962
 
1149
963
  # Spacing as fraction of axes width & height
1150
964
  wspace = self.sw / self.w
@@ -1155,16 +969,18 @@ class LayoutSpaces:
1155
969
  """
1156
970
  Calculate spacing parts for facet_null
1157
971
  """
1158
- self.w = self.r.panel_right - self.l.panel_left
1159
- self.h = self.t.panel_top - self.b.panel_bottom
972
+ self.w = self.panel_width
973
+ self.h = self.panel_height
1160
974
  self.sw = 0
1161
975
  self.sh = 0
1162
976
  return 0, 0
1163
977
 
1164
- def _reduce_height(self, ratio: float):
978
+ def _reduce_height(self, gsparams: GridSpecParams, ratio: float):
1165
979
  """
1166
980
  Reduce the height of axes to get the aspect ratio
1167
981
  """
982
+ gsparams = copy(gsparams)
983
+
1168
984
  # New height w.r.t figure height
1169
985
  h1 = ratio * self.w * (self.W / self.H)
1170
986
 
@@ -1172,17 +988,20 @@ class LayoutSpaces:
1172
988
  dh = (self.h - h1) * self.plot.facet.nrow / 2
1173
989
 
1174
990
  # Reduce plot area height
1175
- self.gsparams.top -= dh
1176
- self.gsparams.bottom += dh
1177
- self.gsparams.hspace = self.sh / h1
991
+ gsparams.top -= dh
992
+ gsparams.bottom += dh
993
+ gsparams.hspace = self.sh / h1
1178
994
 
1179
995
  # Add more vertical plot margin
1180
996
  self.increase_vertical_plot_margin(dh)
997
+ return gsparams
1181
998
 
1182
- def _reduce_width(self, ratio: float):
999
+ def _reduce_width(self, gsparams: GridSpecParams, ratio: float):
1183
1000
  """
1184
1001
  Reduce the width of axes to get the aspect ratio
1185
1002
  """
1003
+ gsparams = copy(gsparams)
1004
+
1186
1005
  # New width w.r.t figure width
1187
1006
  w1 = (self.h * self.H) / (ratio * self.W)
1188
1007
 
@@ -1190,12 +1009,13 @@ class LayoutSpaces:
1190
1009
  dw = (self.w - w1) * self.plot.facet.ncol / 2
1191
1010
 
1192
1011
  # Reduce width
1193
- self.gsparams.left += dw
1194
- self.gsparams.right -= dw
1195
- self.gsparams.wspace = self.sw / w1
1012
+ gsparams.left += dw
1013
+ gsparams.right -= dw
1014
+ gsparams.wspace = self.sw / w1
1196
1015
 
1197
1016
  # Add more horizontal margin
1198
1017
  self.increase_horizontal_plot_margin(dw)
1018
+ return gsparams
1199
1019
 
1200
1020
  @property
1201
1021
  def aspect_ratio(self) -> float: