Coverage for /usr/local/lib/python3.11/dist-packages/grond/plot/config.py: 54%

104 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2024-11-27 15:15 +0000

1# https://pyrocko.org/grond - GPLv3 

2# 

3# The Grond Developers, 21st Century 

4from pyrocko.guts import Object, Float, Int, List, Tuple, String, load, clone 

5 

6from grond.meta import GrondError 

7 

8guts_prefix = 'grond' 

9 

10 

11inch = 2.54 

12points = inch / 72.0 

13 

14 

15class PlotFormat(Object): 

16 

17 @property 

18 def extension(self): 

19 return self.name 

20 

21 def get_dpi(self, size_cm): 

22 return None 

23 

24 def render_mpl(self, fig, path, **kwargs): 

25 raise NotImplementedError 

26 

27 def render_automap(self, automap, path, **kwargs): 

28 raise NotImplementedError 

29 

30 

31class PNG(PlotFormat): 

32 name = 'png' 

33 

34 dpi = Int.T( 

35 optional=True, 

36 help='DPI of the figure') 

37 size_pixels = Int.T( 

38 optional=True, 

39 help='Size in pixels') 

40 width_pixels = Int.T( 

41 optional=True, 

42 help='Width in pixels') 

43 height_pixels = Int.T( 

44 optional=True, 

45 help='Height in pixels') 

46 

47 @property 

48 def extension(self): 

49 if self.dpi is not None: 

50 return 'd%i.png' % self.dpi 

51 elif self.size_pixels is not None: 

52 return 's%i.png' % self.size_pixels 

53 elif self.width_pixels is not None: 

54 return 'w%i.png' % self.width_pixels 

55 elif self.height_pixels is not None: 

56 return 'h%i.png' % self.height_pixels 

57 else: 

58 return 'd100.png' 

59 

60 def get_dpi(self, size_cm): 

61 w_cm, h_cm = size_cm 

62 w_inch, h_inch = w_cm/inch, h_cm/inch 

63 if self.dpi: 

64 return self.dpi 

65 elif self.size_pixels is not None: 

66 return min(self.size_pixels/w_inch, self.size_pixels/h_inch) 

67 elif self.width_pixels is not None: 

68 return self.width_pixels/w_inch 

69 elif self.height_pixels is not None: 

70 return self.height_pixels/h_inch 

71 else: 

72 return 100.0 

73 

74 def render_mpl(self, fig, path, **kwargs): 

75 return fig.savefig(path, format=self.name, **kwargs) 

76 

77 def render_automap(self, automap, path, **kwargs): 

78 return automap.save(path, **kwargs) 

79 

80 

81class PDF(PlotFormat): 

82 name = 'pdf' 

83 

84 dpi = Int.T( 

85 default=150, 

86 help='DPI of the figure') 

87 

88 def get_dpi(self, size_cm): 

89 return self.dpi 

90 

91 def render_mpl(self, fig, path, **kwargs): 

92 return fig.savefig(path, format=self.name, **kwargs) 

93 

94 def render_automap(self, automap, path, **kwargs): 

95 return automap.save(path, **kwargs) 

96 

97 

98class SVG(PlotFormat): 

99 name = 'svg' 

100 

101 dpi = Int.T( 

102 default=150, 

103 help='DPI of the figure') 

104 

105 def get_dpi(self, size_cm): 

106 return self.dpi 

107 

108 def render_mpl(self, fig, path, **kwargs): 

109 return fig.savefig(path, format=self.name, **kwargs) 

110 

111 def render_automap(self, automap, path, **kwargs): 

112 return automap.save(path, **kwargs) 

113 

114 

115class HTML(PlotFormat): 

116 name = 'html' 

117 

118 @property 

119 def extension(self): 

120 return 'html' 

121 

122 def render_mpl(self, fig, path, **kwargs): 

123 import mpld3 

124 kwargs.pop('dpi') 

125 

126 mpld3.save_html( 

127 fig, 

128 fileobj=path, 

129 **kwargs) 

130 

131 

132class PlotConfig(Object): 

133 name = 'undefined' 

134 variant = String.T( 

135 default='default', 

136 help='Variant of the plot (if applicable)') 

137 formats = List.T( 

138 PlotFormat.T(), 

139 default=[PNG()], 

140 help='Format of the plot') 

141 size_cm = Tuple.T( 

142 2, Float.T(), 

143 help='size of the plot') 

144 font_size = Float.T( 

145 default=10., 

146 help='font size') 

147 

148 @property 

149 def size_inch(self): 

150 return self.size_cm[0]/inch, self.size_cm[1]/inch 

151 

152 @property 

153 def size_points(self): 

154 return self.size_cm[0]/points, self.size_cm[1]/points 

155 

156 def make(self, environ): 

157 pass 

158 

159 

160class PlotConfigCollection(Object): 

161 plot_configs = List.T(PlotConfig.T()) 

162 

163 @classmethod 

164 def load(cls, path): 

165 from grond.plot import get_all_plot_classes 

166 get_all_plot_classes() # make sure all plot classes are loaded 

167 collection = load(filename=path) 

168 if not isinstance(collection, PlotConfigCollection): 

169 raise GrondError( 

170 'invalid plot collection configuration in file "%s"' % path) 

171 

172 return collection 

173 

174 def get_weeded(self, env): 

175 '''Get subset of plot configs supported by the current environment.''' 

176 

177 plot_classes = env.get_plot_classes() 

178 plot_configs_avail = [ 

179 clone(pc) 

180 for pc in self.plot_configs 

181 if pc.__class__ in plot_classes] 

182 

183 return PlotConfigCollection(plot_configs=plot_configs_avail) 

184 

185 

186__all__ = [ 

187 'PlotFormat', 

188 'PNG', 

189 'PDF', 

190 'PlotConfig', 

191 'PlotConfigCollection', 

192]