Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/env python 

2# cardinal_pythonlib/plot.py 

3 

4""" 

5=============================================================================== 

6 

7 Original code copyright (C) 2009-2021 Rudolf Cardinal (rudolf@pobox.com). 

8 

9 This file is part of cardinal_pythonlib. 

10 

11 Licensed under the Apache License, Version 2.0 (the "License"); 

12 you may not use this file except in compliance with the License. 

13 You may obtain a copy of the License at 

14 

15 https://www.apache.org/licenses/LICENSE-2.0 

16 

17 Unless required by applicable law or agreed to in writing, software 

18 distributed under the License is distributed on an "AS IS" BASIS, 

19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

20 See the License for the specific language governing permissions and 

21 limitations under the License. 

22 

23=============================================================================== 

24 

25**Support for plotting via matplotlib.pyplot.** 

26""" 

27 

28import io 

29# noinspection PyUnresolvedReferences 

30from types import ModuleType 

31from typing import TYPE_CHECKING, Union 

32 

33from cardinal_pythonlib import rnc_web 

34 

35if TYPE_CHECKING: 

36 try: 

37 # noinspection PyPackageRequirements 

38 from matplotlib.figure import Figure 

39 except ImportError: 

40 Figure = None 

41 

42 

43# ============================================================================= 

44# Image embedding in PDFs 

45# ============================================================================= 

46# xhtml2pdf (2013-04-11) supports PNG, but not SVG. 

47# You can convert SVG to PNG for embedding: 

48# https://stackoverflow.com/questions/787287 

49# You could make a PDF and append it, though that would (without further 

50# effort) lack the patient headers. 

51 

52def png_img_html_from_pyplot_figure(fig: "Figure", 

53 dpi: int = 100, 

54 extra_html_class: str = None) -> str: 

55 """ 

56 Converts a ``pyplot`` figure to an HTML IMG tag with encapsulated PNG. 

57 """ 

58 if fig is None: 

59 return "" 

60 # Make a file-like object 

61 memfile = io.BytesIO() 

62 # In general, can do 

63 # fig.savefig(filename/file-like-object/backend, format=...) 

64 # or 

65 # backend.savefig(fig): 

66 # see e.g. http://matplotlib.org/api/backend_pdf_api.html 

67 # noinspection PyUnresolvedReferences 

68 fig.savefig(memfile, format="png", dpi=dpi) 

69 memfile.seek(0) 

70 pngblob = memoryview(memfile.read()) 

71 return rnc_web.get_png_img_html(pngblob, extra_html_class) 

72 

73 

74def svg_html_from_pyplot_figure(fig: "Figure") -> str: 

75 """ 

76 Converts a ``pyplot`` figure to an SVG tag. 

77 """ 

78 if fig is None: 

79 return "" 

80 memfile = io.BytesIO() # StringIO doesn't like mixing str/unicode 

81 # noinspection PyUnresolvedReferences 

82 fig.savefig(memfile, format="svg") 

83 return memfile.getvalue().decode("utf-8") # returns a text/Unicode type 

84 # SVG works directly in HTML; it returns <svg ...></svg> 

85 

86 

87# ============================================================================= 

88# Plotting 

89# ============================================================================= 

90 

91def set_matplotlib_fontsize(matplotlib: ModuleType, 

92 fontsize: Union[int, float] = 12) -> None: 

93 """ 

94 Sets the current font size within the ``matplotlib`` library. 

95 

96 **WARNING:** not an appropriate method for multithreaded environments, as 

97 it writes (indirectly) to ``matplotlib`` global objects. See CamCOPS for 

98 alternative methods. 

99 """ 

100 font = { 

101 # https://stackoverflow.com/questions/3899980 

102 # http://matplotlib.org/users/customizing.html 

103 'family': 'sans-serif', 

104 # ... serif, sans-serif, cursive, fantasy, monospace 

105 'style': 'normal', # normal (roman), italic, oblique 

106 'variant': 'normal', # normal, small-caps 

107 'weight': 'normal', 

108 # ... normal [=400], bold [=700], bolder [relative to current], 

109 # lighter [relative], 100, 200, 300, ..., 900 

110 'size': fontsize # in pt (default 12) 

111 } 

112 # noinspection PyUnresolvedReferences 

113 matplotlib.rc('font', **font) 

114 legend = { 

115 # https://stackoverflow.com/questions/7125009 

116 'fontsize': fontsize 

117 } 

118 # noinspection PyUnresolvedReferences 

119 matplotlib.rc('legend', **legend)