File: movie.py

package info (click to toggle)
python-ase 3.12.0-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 14,192 kB
  • ctags: 8,112
  • sloc: python: 93,375; sh: 99; makefile: 94
file content (131 lines) | stat: -rw-r--r-- 4,488 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import gtk
from gettext import gettext as _
import gobject

import numpy as np

from ase.gui.widgets import pack


class Movie(gtk.Window):
    def __init__(self, gui):
        gtk.Window.__init__(self)
        self.set_position(gtk.WIN_POS_NONE)
        self.connect('destroy', self.close)
        self.set_title(_('Movie'))
        vbox = gtk.VBox()
        pack(vbox, gtk.Label(_('Image number:')))
        self.frame_number = gtk.Adjustment(gui.frame, 0,
                                           gui.images.nimages - 1,
                                           1.0, 5.0)
        self.frame_number.connect('value-changed', self.new_frame)

        hscale = pack(vbox, gtk.HScale(self.frame_number))
        hscale.set_update_policy(gtk.UPDATE_CONTINUOUS)
        hscale.set_digits(0)

        buttons = [gtk.Button(stock=gtk.STOCK_GOTO_FIRST),
                   gtk.Button(stock=gtk.STOCK_GO_BACK),
                   gtk.Button(stock=gtk.STOCK_GO_FORWARD),
                   gtk.Button(stock=gtk.STOCK_GOTO_LAST)]

        buttons[0].connect('clicked', self.click, -1, True)
        buttons[1].connect('clicked', self.click, -1)
        buttons[2].connect('clicked', self.click, 1)
        buttons[3].connect('clicked', self.click, 1, True)

        pack(vbox, buttons)

        play = gtk.Button(_('Play'))
        play.connect('clicked', self.play)
        stop = gtk.Button(_('Stop'))
        stop.connect('clicked', self.stop)
        # TRANSLATORS: This function plays an animation forwards and backwards
        # alternatingly, e.g. for displaying vibrational movement
        self.rock = gtk.CheckButton(_('Rock'))

        pack(vbox, [play, stop, gtk.Label('  '), self.rock])

        if gui.images.nimages > 150:
            skipdefault = gui.images.nimages // 150
            tdefault = min(max(gui.images.nimages / (skipdefault * 5.0),
                               1.0), 30)
        else:
            skipdefault = 0
            tdefault = min(max(gui.images.nimages / 5.0, 1.0), 30)
        self.time = gtk.Adjustment(tdefault, 1.0, 99, 0.1)
        self.time_spin = gtk.SpinButton(self.time, 0, 0)
        self.time_spin.set_digits(1)
        self.time.connect('value-changed', self.frame_rate_changed)
        self.skip = gtk.Adjustment(skipdefault, 0, 99, 1)
        self.skip_spin = gtk.SpinButton(self.skip, 0, 0)
        pack(vbox, [gtk.Label(_(' Frame rate: ')), self.time_spin,
                    gtk.Label(_(' Skip frames: ')), self.skip_spin,
                    gtk.Label('   ')])
        self.add(vbox)
        vbox.show()
        self.show()
        self.gui = gui
        self.direction = 1
        self.id = None
        gui.register_vulnerable(self)

    def notify_atoms_changed(self):
        """Called by gui object when the atoms have changed."""
        self.destroy()
        
    def close(self, event):
        self.stop()

    def click(self, button, step, firstlast=False):
        if firstlast and step < 0:
            i = 0
        elif firstlast:
            i = self.gui.images.nimages - 1
        else:
            i = max(0, min(self.gui.images.nimages - 1, self.gui.frame + step))
        self.gui.set_frame(i)
        self.frame_number.value = i
        if firstlast:
            self.direction = np.sign(-step)
        else:
            self.direction = np.sign(step)
            
    def new_frame(self, widget):
        self.gui.set_coordinates(int(self.frame_number.value))

    def play(self, widget=None):
        if self.id is not None:
            gobject.source_remove(self.id)
        t = int(1000.0 / float(self.time.value))
        self.id = gobject.timeout_add(t, self.step)

    def stop(self, widget=None):
        if self.id is not None:
            gobject.source_remove(self.id)
            self.id = None

    def frame_rate_changed(self, widget=None):
        if self.id is not None:
            self.play()

    def step(self):
        i = self.gui.frame
        nimages = self.gui.images.nimages
        delta = int(self.skip.value + 1)
        
        if self.rock.get_active():
            if i <= self.skip.value:
                self.direction = 1
            elif i >= nimages - delta:
                self.direction = -1
            i += self.direction * delta
        else:
            i = (i + self.direction * delta + nimages) % nimages
            
        self.frame_number.value = i
        return True

    def new_time(self, widget):
        if self.id is not None:
            self.play()