1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

""" 

This module is to support *bbox_inches* option in savefig command. 

""" 

 

from matplotlib.transforms import Bbox, TransformedBbox, Affine2D 

 

 

def adjust_bbox(fig, bbox_inches, fixed_dpi=None): 

""" 

Temporarily adjust the figure so that only the specified area 

(bbox_inches) is saved. 

 

It modifies fig.bbox, fig.bbox_inches, 

fig.transFigure._boxout, and fig.patch. While the figure size 

changes, the scale of the original figure is conserved. A 

function which restores the original values are returned. 

""" 

 

origBbox = fig.bbox 

origBboxInches = fig.bbox_inches 

_boxout = fig.transFigure._boxout 

 

asp_list = [] 

locator_list = [] 

for ax in fig.axes: 

pos = ax.get_position(original=False).frozen() 

locator_list.append(ax.get_axes_locator()) 

asp_list.append(ax.get_aspect()) 

 

def _l(a, r, pos=pos): 

return pos 

ax.set_axes_locator(_l) 

ax.set_aspect("auto") 

 

def restore_bbox(): 

 

for ax, asp, loc in zip(fig.axes, asp_list, locator_list): 

ax.set_aspect(asp) 

ax.set_axes_locator(loc) 

 

fig.bbox = origBbox 

fig.bbox_inches = origBboxInches 

fig.transFigure._boxout = _boxout 

fig.transFigure.invalidate() 

fig.patch.set_bounds(0, 0, 1, 1) 

 

if fixed_dpi is not None: 

tr = Affine2D().scale(fixed_dpi) 

dpi_scale = fixed_dpi / fig.dpi 

else: 

tr = Affine2D().scale(fig.dpi) 

dpi_scale = 1. 

 

_bbox = TransformedBbox(bbox_inches, tr) 

 

fig.bbox_inches = Bbox.from_bounds(0, 0, 

bbox_inches.width, bbox_inches.height) 

x0, y0 = _bbox.x0, _bbox.y0 

w1, h1 = fig.bbox.width * dpi_scale, fig.bbox.height * dpi_scale 

fig.transFigure._boxout = Bbox.from_bounds(-x0, -y0, w1, h1) 

fig.transFigure.invalidate() 

 

fig.bbox = TransformedBbox(fig.bbox_inches, tr) 

 

fig.patch.set_bounds(x0 / w1, y0 / h1, 

fig.bbox.width / w1, fig.bbox.height / h1) 

 

return restore_bbox 

 

 

def process_figure_for_rasterizing(fig, bbox_inches_restore, fixed_dpi=None): 

""" 

This need to be called when figure dpi changes during the drawing 

(e.g., rasterizing). It recovers the bbox and re-adjust it with 

the new dpi. 

""" 

 

bbox_inches, restore_bbox = bbox_inches_restore 

restore_bbox() 

r = adjust_bbox(fig, bbox_inches, fixed_dpi) 

 

return bbox_inches, r