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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

11 statements  

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().__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 hspan = getattr(self, 'hspan', None) 

126 # instantaneous rate 

127 y = delta_it / delta_t 

128 # overall rate 

129 z = n / elapsed 

130 # update line data 

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

132 ydata.append(y) 

133 zdata.append(z) 

134 

135 # Discard old values 

136 # xmin, xmax = ax.get_xlim() 

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

138 if (not total) and elapsed > 66: 

139 xdata.popleft() 

140 ydata.popleft() 

141 zdata.popleft() 

142 

143 ymin, ymax = ax.get_ylim() 

144 if y > ymax or z > ymax: 

145 ymax = 1.1 * y 

146 ax.set_ylim(ymin, ymax) 

147 ax.figure.canvas.draw() 

148 

149 if total: 

150 line1.set_data(xdata, ydata) 

151 line2.set_data(xdata, zdata) 

152 if hspan: 

153 hspan.set_xy((0, ymin)) 

154 hspan.set_height(ymax - ymin) 

155 hspan.set_width(n / total) 

156 else: 

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

158 line1.set_data(t_ago, ydata) 

159 line2.set_data(t_ago, zdata) 

160 

161 d = self.format_dict 

162 # remove {bar} 

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

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

165 msg = self.format_meter(**d) 

166 if '<bar/>' in msg: 

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

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

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

170 

171 

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

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

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

175 

176 

177# Aliases 

178tqdm = tqdm_gui 

179trange = tgrange