Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tqdm/gui.py: 90%

10 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:51 +0000

1""" 

2Matplotlib GUI progressbar decorator for iterators. 

3 

4Usage: 

5>>> from tqdm.gui import trange, tqdm 

6>>> for i in trange(10): 

7... ... 

8""" 

9# future division is important to divide integers and get as 

10# a result precise floating numbers (instead of truncated int) 

11import re 

12from warnings import warn 

13 

14# to inherit from the tqdm class 

15from .std import TqdmExperimentalWarning 

16from .std import tqdm as std_tqdm 

17 

18# import compatibility functions and utilities 

19 

20__author__ = {"github.com/": ["casperdcl", "lrq3000"]} 

21__all__ = ['tqdm_gui', 'tgrange', 'tqdm', 'trange'] 

22 

23 

24class tqdm_gui(std_tqdm): # pragma: no cover 

25 """Experimental Matplotlib GUI version of tqdm!""" 

26 # TODO: @classmethod: write() on GUI? 

27 def __init__(self, *args, **kwargs): 

28 from collections import deque 

29 

30 import matplotlib as mpl 

31 import matplotlib.pyplot as plt 

32 kwargs = kwargs.copy() 

33 kwargs['gui'] = True 

34 colour = kwargs.pop('colour', 'g') 

35 super(tqdm_gui, self).__init__(*args, **kwargs) 

36 

37 if self.disable: 

38 return 

39 

40 warn("GUI is experimental/alpha", TqdmExperimentalWarning, stacklevel=2) 

41 self.mpl = mpl 

42 self.plt = plt 

43 

44 # Remember if external environment uses toolbars 

45 self.toolbar = self.mpl.rcParams['toolbar'] 

46 self.mpl.rcParams['toolbar'] = 'None' 

47 

48 self.mininterval = max(self.mininterval, 0.5) 

49 self.fig, ax = plt.subplots(figsize=(9, 2.2)) 

50 # self.fig.subplots_adjust(bottom=0.2) 

51 total = self.__len__() # avoids TypeError on None #971 

52 if total is not None: 

53 self.xdata = [] 

54 self.ydata = [] 

55 self.zdata = [] 

56 else: 

57 self.xdata = deque([]) 

58 self.ydata = deque([]) 

59 self.zdata = deque([]) 

60 self.line1, = ax.plot(self.xdata, self.ydata, color='b') 

61 self.line2, = ax.plot(self.xdata, self.zdata, color='k') 

62 ax.set_ylim(0, 0.001) 

63 if total is not None: 

64 ax.set_xlim(0, 100) 

65 ax.set_xlabel("percent") 

66 self.fig.legend((self.line1, self.line2), ("cur", "est"), 

67 loc='center right') 

68 # progressbar 

69 self.hspan = plt.axhspan(0, 0.001, xmin=0, xmax=0, color=colour) 

70 else: 

71 # ax.set_xlim(-60, 0) 

72 ax.set_xlim(0, 60) 

73 ax.invert_xaxis() 

74 ax.set_xlabel("seconds") 

75 ax.legend(("cur", "est"), loc='lower left') 

76 ax.grid() 

77 # ax.set_xlabel('seconds') 

78 ax.set_ylabel((self.unit if self.unit else "it") + "/s") 

79 if self.unit_scale: 

80 plt.ticklabel_format(style='sci', axis='y', scilimits=(0, 0)) 

81 ax.yaxis.get_offset_text().set_x(-0.15) 

82 

83 # Remember if external environment is interactive 

84 self.wasion = plt.isinteractive() 

85 plt.ion() 

86 self.ax = ax 

87 

88 def close(self): 

89 if self.disable: 

90 return 

91 

92 self.disable = True 

93 

94 with self.get_lock(): 

95 self._instances.remove(self) 

96 

97 # Restore toolbars 

98 self.mpl.rcParams['toolbar'] = self.toolbar 

99 # Return to non-interactive mode 

100 if not self.wasion: 

101 self.plt.ioff() 

102 if self.leave: 

103 self.display() 

104 else: 

105 self.plt.close(self.fig) 

106 

107 def clear(self, *_, **__): 

108 pass 

109 

110 def display(self, *_, **__): 

111 n = self.n 

112 cur_t = self._time() 

113 elapsed = cur_t - self.start_t 

114 delta_it = n - self.last_print_n 

115 delta_t = cur_t - self.last_print_t 

116 

117 # Inline due to multiple calls 

118 total = self.total 

119 xdata = self.xdata 

120 ydata = self.ydata 

121 zdata = self.zdata 

122 ax = self.ax 

123 line1 = self.line1 

124 line2 = self.line2 

125 # instantaneous rate 

126 y = delta_it / delta_t 

127 # overall rate 

128 z = n / elapsed 

129 # update line data 

130 xdata.append(n * 100.0 / total if total else cur_t) 

131 ydata.append(y) 

132 zdata.append(z) 

133 

134 # Discard old values 

135 # xmin, xmax = ax.get_xlim() 

136 # if (not total) and elapsed > xmin * 1.1: 

137 if (not total) and elapsed > 66: 

138 xdata.popleft() 

139 ydata.popleft() 

140 zdata.popleft() 

141 

142 ymin, ymax = ax.get_ylim() 

143 if y > ymax or z > ymax: 

144 ymax = 1.1 * y 

145 ax.set_ylim(ymin, ymax) 

146 ax.figure.canvas.draw() 

147 

148 if total: 

149 line1.set_data(xdata, ydata) 

150 line2.set_data(xdata, zdata) 

151 try: 

152 poly_lims = self.hspan.get_xy() 

153 except AttributeError: 

154 self.hspan = self.plt.axhspan(0, 0.001, xmin=0, xmax=0, color='g') 

155 poly_lims = self.hspan.get_xy() 

156 poly_lims[0, 1] = ymin 

157 poly_lims[1, 1] = ymax 

158 poly_lims[2] = [n / total, ymax] 

159 poly_lims[3] = [poly_lims[2, 0], ymin] 

160 if len(poly_lims) > 4: 

161 poly_lims[4, 1] = ymin 

162 self.hspan.set_xy(poly_lims) 

163 else: 

164 t_ago = [cur_t - i for i in xdata] 

165 line1.set_data(t_ago, ydata) 

166 line2.set_data(t_ago, zdata) 

167 

168 d = self.format_dict 

169 # remove {bar} 

170 d['bar_format'] = (d['bar_format'] or "{l_bar}<bar/>{r_bar}").replace( 

171 "{bar}", "<bar/>") 

172 msg = self.format_meter(**d) 

173 if '<bar/>' in msg: 

174 msg = "".join(re.split(r'\|?<bar/>\|?', msg, 1)) 

175 ax.set_title(msg, fontname="DejaVu Sans Mono", fontsize=11) 

176 self.plt.pause(1e-9) 

177 

178 

179def tgrange(*args, **kwargs): 

180 """Shortcut for `tqdm.gui.tqdm(range(*args), **kwargs)`.""" 

181 return tqdm_gui(range(*args), **kwargs) 

182 

183 

184# Aliases 

185tqdm = tqdm_gui 

186trange = tgrange