Coverage for /builds/kinetik161/ase/ase/gui/movie.py: 60.32%

63 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-12-10 11:04 +0000

1import numpy as np 

2 

3import ase.gui.ui as ui 

4from ase.gui.i18n import _ 

5 

6 

7class Movie: 

8 def __init__(self, gui): 

9 self.win = win = ui.Window( 

10 _('Movie'), close=self.close, wmtype='utility') 

11 win.add(_('Image number:')) 

12 self.frame_number = ui.Scale(gui.frame, 0, 

13 len(gui.images) - 1, 

14 callback=self.new_frame) 

15 win.add(self.frame_number) 

16 

17 win.add([ui.Button(_('First'), self.click, -1, True), 

18 ui.Button(_('Back'), self.click, -1), 

19 ui.Button(_('Forward'), self.click, 1), 

20 ui.Button(_('Last'), self.click, 1, True)]) 

21 

22 play = ui.Button(_('Play'), self.play) 

23 stop = ui.Button(_('Stop'), self.stop) 

24 

25 # TRANSLATORS: This function plays an animation forwards and backwards 

26 # alternatingly, e.g. for displaying vibrational movement 

27 self.rock = ui.CheckButton(_('Rock')) 

28 

29 win.add([play, stop, self.rock]) 

30 

31 if len(gui.images) > 150: 

32 skipdefault = len(gui.images) // 150 

33 tdefault = min(max(len(gui.images) / (skipdefault * 5.0), 

34 1.0), 30) 

35 else: 

36 skipdefault = 0 

37 tdefault = min(max(len(gui.images) / 5.0, 1.0), 30) 

38 self.time = ui.SpinBox(tdefault, 1.0, 99, 0.1) 

39 self.skip = ui.SpinBox(skipdefault, 0, 99, 1) 

40 win.add([_(' Frame rate: '), self.time, _(' Skip frames: '), 

41 self.skip]) 

42 

43 self.gui = gui 

44 self.direction = 1 

45 self.timer = None 

46 gui.register_vulnerable(self) 

47 

48 def notify_atoms_changed(self): 

49 """Called by gui object when the atoms have changed.""" 

50 self.close() 

51 

52 def close(self): 

53 self.stop() 

54 self.win.close() 

55 

56 def click(self, step, firstlast=False): 

57 if firstlast and step < 0: 

58 i = 0 

59 elif firstlast: 

60 i = len(self.gui.images) 

61 else: 

62 i = max(0, min(len(self.gui.images) - 1, self.gui.frame + step)) 

63 

64 self.frame_number.value = i 

65 if firstlast: 

66 self.direction = np.sign(-step) 

67 else: 

68 self.direction = np.sign(step) 

69 

70 def new_frame(self, value): 

71 self.gui.set_frame(value) 

72 

73 def play(self): 

74 self.stop() 

75 t = 1 / self.time.value 

76 self.timer = self.gui.window.after(t, self.step) 

77 

78 def stop(self): 

79 if self.timer is not None: 

80 self.timer.cancel() 

81 

82 def step(self): 

83 i = self.gui.frame 

84 nimages = len(self.gui.images) 

85 delta = int(self.skip.value) + 1 

86 

87 if self.rock.value: 

88 if i <= self.skip.value: 

89 self.direction = 1 

90 elif i >= nimages - delta: 

91 self.direction = -1 

92 i += self.direction * delta 

93 else: 

94 i = (i + self.direction * delta + nimages) % nimages 

95 

96 self.frame_number.value = i 

97 self.play()