Statistiques
| Révision :

root / ase / gui / view.py @ 15

Historique | Voir | Annoter | Télécharger (22,5 ko)

1 1 tkerber
#!/usr/bin/env python
2 1 tkerber
3 1 tkerber
# Emacs: treat this as -*- python -*-
4 1 tkerber
5 1 tkerber
import os
6 1 tkerber
import gtk
7 1 tkerber
import tempfile
8 1 tkerber
from math import cos, sin, sqrt
9 1 tkerber
10 1 tkerber
import numpy as np
11 1 tkerber
12 1 tkerber
from ase.data.colors import jmol_colors
13 1 tkerber
from ase.gui.repeat import Repeat
14 1 tkerber
from ase.gui.rotate import Rotate
15 1 tkerber
from ase.utils import rotate
16 1 tkerber
17 1 tkerber
18 1 tkerber
class View:
19 1 tkerber
    def __init__(self, vbox, rotations):
20 1 tkerber
        self.colors = [None] * (len(jmol_colors) + 1)
21 1 tkerber
        self.nselected = 0
22 1 tkerber
        self.light_green_markings = 0
23 1 tkerber
        self.axes = rotate(rotations)
24 1 tkerber
        # this is a hack, in order to be able to toggle menu actions off/on
25 1 tkerber
        # without getting into an infinte loop
26 1 tkerber
        self.menu_change = 0
27 1 tkerber
28 1 tkerber
        self.atoms_to_rotate = None
29 1 tkerber
30 1 tkerber
        self.drawing_area = gtk.DrawingArea()
31 1 tkerber
        self.drawing_area.set_size_request(450, 450)
32 1 tkerber
        self.drawing_area.connect('button_press_event', self.press)
33 1 tkerber
        self.drawing_area.connect('button_release_event', self.release)
34 1 tkerber
        self.drawing_area.connect('motion-notify-event', self.move)
35 1 tkerber
        # Signals used to handle backing pixmap:
36 1 tkerber
        self.drawing_area.connect('expose_event', self.expose_event)
37 1 tkerber
        self.drawing_area.connect('configure_event', self.configure_event)
38 1 tkerber
        self.drawing_area.set_events(gtk.gdk.BUTTON_PRESS_MASK |
39 1 tkerber
                                     gtk.gdk.BUTTON_RELEASE_MASK |
40 1 tkerber
                                     gtk.gdk.BUTTON_MOTION_MASK |
41 1 tkerber
                                     gtk.gdk.POINTER_MOTION_HINT_MASK)
42 1 tkerber
        vbox.pack_start(self.drawing_area)
43 1 tkerber
        self.drawing_area.show()
44 1 tkerber
        self.configured = False
45 1 tkerber
        self.frame = None
46 1 tkerber
47 1 tkerber
    def set_coordinates(self, frame=None, focus=None):
48 1 tkerber
        if frame is None:
49 1 tkerber
            frame = self.frame
50 1 tkerber
        self.make_box()
51 1 tkerber
        self.bind(frame)
52 1 tkerber
        n = self.images.natoms
53 1 tkerber
        self.X = np.empty((n + len(self.B1) + len(self.bonds), 3))
54 1 tkerber
        #self.X[n:] = np.dot(self.B1, self.images.A[frame])
55 1 tkerber
        #self.B = np.dot(self.B2, self.images.A[frame])
56 1 tkerber
        self.set_frame(frame, focus=focus, init=True)
57 1 tkerber
58 1 tkerber
    def set_frame(self, frame=None, focus=False, init=False):
59 1 tkerber
        if frame is None:
60 1 tkerber
            frame = self.frame
61 1 tkerber
62 1 tkerber
        n = self.images.natoms
63 1 tkerber
64 1 tkerber
        if init or frame != self.frame:
65 1 tkerber
            A = self.images.A
66 1 tkerber
            nc = len(self.B1)
67 1 tkerber
            nb = len(self.bonds)
68 1 tkerber
69 1 tkerber
            if init or (A[frame] != A[self.frame]).any():
70 1 tkerber
                self.X[n:n + nc] = np.dot(self.B1, A[frame])
71 1 tkerber
                self.B = np.empty((nc + nb, 3))
72 1 tkerber
                self.B[:nc] = np.dot(self.B2, A[frame])
73 1 tkerber
74 1 tkerber
            if nb > 0:
75 1 tkerber
                P = self.images.P[frame]
76 1 tkerber
                Af = self.images.repeat[:, np.newaxis] * A[frame]
77 1 tkerber
                a = P[self.bonds[:, 0]]
78 1 tkerber
                b = P[self.bonds[:, 1]] + np.dot(self.bonds[:, 2:], Af) - a
79 1 tkerber
                d = (b**2).sum(1)**0.5
80 1 tkerber
                r = 0.65 * self.images.r
81 1 tkerber
                x0 = (r[self.bonds[:, 0]] / d).reshape((-1, 1))
82 1 tkerber
                x1 = (r[self.bonds[:, 1]] / d).reshape((-1, 1))
83 1 tkerber
                self.X[n + nc:] = a + b * x0
84 1 tkerber
                b *= 1.0 - x0 - x1
85 1 tkerber
                b[self.bonds[:, 2:].any(1)] *= 0.5
86 1 tkerber
                self.B[nc:] = self.X[n + nc:] + b
87 1 tkerber
88 1 tkerber
            filenames = self.images.filenames
89 1 tkerber
            filename = filenames[frame]
90 1 tkerber
            if self.frame is None or filename != filenames[self.frame]:
91 1 tkerber
                if filename is None:
92 1 tkerber
                    filename = 'ase.gui'
93 1 tkerber
                self.window.set_title(filename)
94 1 tkerber
95 1 tkerber
        self.frame = frame
96 1 tkerber
97 1 tkerber
        self.X[:n] = self.images.P[frame]
98 1 tkerber
        self.R = self.X[:n]
99 1 tkerber
        if focus:
100 1 tkerber
            self.focus()
101 1 tkerber
        else:
102 1 tkerber
            self.draw()
103 1 tkerber
104 1 tkerber
    def set_colors(self):
105 1 tkerber
        new = self.drawing_area.window.new_gc
106 1 tkerber
        alloc = self.colormap.alloc_color
107 1 tkerber
        for z in self.images.Z:
108 1 tkerber
            if self.colors[z] is None:
109 1 tkerber
                c, p, k = jmol_colors[z]
110 1 tkerber
                self.colors[z] = new(alloc(int(65535 * c),
111 1 tkerber
                                           int(65535 * p),
112 1 tkerber
                                           int(65535 * k)))
113 1 tkerber
114 1 tkerber
    def plot_cell(self):
115 1 tkerber
        V = self.images.A[0]
116 1 tkerber
        R1 = []
117 1 tkerber
        R2 = []
118 1 tkerber
        for c in range(3):
119 1 tkerber
            v = V[c]
120 1 tkerber
            d = sqrt(np.dot(v, v))
121 1 tkerber
            n = max(2, int(d / 0.3))
122 1 tkerber
            h = v / (2 * n - 1)
123 1 tkerber
            R = np.arange(n)[:, None] * (2 * h)
124 1 tkerber
            for i, j in [(0, 0), (0, 1), (1, 0), (1, 1)]:
125 1 tkerber
                R1.append(R + i * V[(c + 1) % 3] + j * V[(c + 2) % 3])
126 1 tkerber
                R2.append(R1[-1] + h)
127 1 tkerber
        return np.concatenate(R1), np.concatenate(R2)
128 1 tkerber
129 1 tkerber
    def make_box(self):
130 1 tkerber
        if not self.ui.get_widget('/MenuBar/ViewMenu/ShowUnitCell'
131 1 tkerber
                                  ).get_active():
132 1 tkerber
            self.B1 = self.B2 = np.zeros((0, 3))
133 1 tkerber
            return
134 1 tkerber
135 1 tkerber
        V = self.images.A[0]
136 1 tkerber
        nn = []
137 1 tkerber
        for c in range(3):
138 1 tkerber
            v = V[c]
139 1 tkerber
            d = sqrt(np.dot(v, v))
140 1 tkerber
            n = max(2, int(d / 0.3))
141 1 tkerber
            nn.append(n)
142 1 tkerber
        self.B1 = np.zeros((2, 2, sum(nn), 3))
143 1 tkerber
        self.B2 = np.zeros((2, 2, sum(nn), 3))
144 1 tkerber
        n1 = 0
145 1 tkerber
        for c, n in enumerate(nn):
146 1 tkerber
            n2 = n1 + n
147 1 tkerber
            h = 1.0 / (2 * n - 1)
148 1 tkerber
            R = np.arange(n) * (2 * h)
149 1 tkerber
150 1 tkerber
            for i, j in [(0, 0), (0, 1), (1, 0), (1, 1)]:
151 1 tkerber
                self.B1[i, j, n1:n2, c] = R
152 1 tkerber
                self.B1[i, j, n1:n2, (c + 1) % 3] = i
153 1 tkerber
                self.B1[i, j, n1:n2, (c + 2) % 3] = j
154 1 tkerber
            self.B2[:, :, n1:n2] = self.B1[:, :, n1:n2]
155 1 tkerber
            self.B2[:, :, n1:n2, c] += h
156 1 tkerber
            n1 = n2
157 1 tkerber
        self.B1.shape = (-1, 3)
158 1 tkerber
        self.B2.shape = (-1, 3)
159 1 tkerber
160 1 tkerber
    def bind(self, frame):
161 1 tkerber
        if not self.ui.get_widget('/MenuBar/ViewMenu/ShowBonds'
162 1 tkerber
                                  ).get_active():
163 1 tkerber
            self.bonds = np.empty((0, 5), int)
164 1 tkerber
            return
165 1 tkerber
166 1 tkerber
        from ase.atoms import Atoms
167 1 tkerber
        from ase.calculators.neighborlist import NeighborList
168 1 tkerber
        nl = NeighborList(self.images.r * 1.5, skin=0, self_interaction=False)
169 1 tkerber
        nl.update(Atoms(positions=self.images.P[frame],
170 1 tkerber
                        cell=(self.images.repeat[:, np.newaxis] *
171 1 tkerber
                              self.images.A[frame]),
172 1 tkerber
                        pbc=self.images.pbc))
173 1 tkerber
        nb = nl.nneighbors + nl.npbcneighbors
174 1 tkerber
        self.bonds = np.empty((nb, 5), int)
175 1 tkerber
        if nb == 0:
176 1 tkerber
            return
177 1 tkerber
178 1 tkerber
        n1 = 0
179 1 tkerber
        for a in range(self.images.natoms):
180 1 tkerber
            indices, offsets = nl.get_neighbors(a)
181 1 tkerber
            n2 = n1 + len(indices)
182 1 tkerber
            self.bonds[n1:n2, 0] = a
183 1 tkerber
            self.bonds[n1:n2, 1] = indices
184 1 tkerber
            self.bonds[n1:n2, 2:] = offsets
185 1 tkerber
            n1 = n2
186 1 tkerber
187 1 tkerber
        i = self.bonds[:n2, 2:].any(1)
188 1 tkerber
        self.bonds[n2:, 0] = self.bonds[i, 1]
189 1 tkerber
        self.bonds[n2:, 1] = self.bonds[i, 0]
190 1 tkerber
        self.bonds[n2:, 2:] = -self.bonds[i, 2:]
191 1 tkerber
192 1 tkerber
    def toggle_show_unit_cell(self, action):
193 1 tkerber
        self.set_coordinates()
194 1 tkerber
195 1 tkerber
    def reset_tools_modes(self):
196 1 tkerber
        dummy = self.menu_change
197 1 tkerber
        self.menu_change = 1
198 1 tkerber
        self.atoms_to_rotate = None
199 1 tkerber
        for c_mode in ['Rotate', 'Orient', 'Move']:
200 1 tkerber
              self.ui.get_widget('/MenuBar/ToolsMenu/%sAtoms' % c_mode).set_active(False)
201 1 tkerber
        self.light_green_markings = 0
202 1 tkerber
        self.menu_change = 0
203 1 tkerber
        self.draw()
204 1 tkerber
205 1 tkerber
206 1 tkerber
    def toggle_mode(self, mode):
207 1 tkerber
        self.menu_change = 1
208 1 tkerber
        i_sum = 0
209 1 tkerber
        for c_mode in ['Rotate', 'Orient', 'Move']:
210 1 tkerber
            i_sum += self.ui.get_widget('/MenuBar/ToolsMenu/%sAtoms' % c_mode).get_active()
211 1 tkerber
        if i_sum == 0 or (i_sum == 1 and sum(self.images.selected) == 0):
212 1 tkerber
            self.reset_tools_modes()
213 1 tkerber
            return()
214 1 tkerber
215 1 tkerber
        if i_sum == 2:
216 1 tkerber
            try:
217 1 tkerber
                self.images.selected = self.atoms_to_rotate_0.copy()
218 1 tkerber
            except:
219 1 tkerber
                self.atoms_to_rotate_0 = self.images.selected.copy()
220 1 tkerber
        if i_sum == 1:
221 1 tkerber
            self.atoms_to_rotate_0 = self.images.selected.copy()
222 1 tkerber
223 1 tkerber
        for c_mode in ['Rotate', 'Orient', 'Move']:
224 1 tkerber
            if c_mode != mode:
225 1 tkerber
                  self.ui.get_widget('/MenuBar/ToolsMenu/%sAtoms' % c_mode).set_active(False)
226 1 tkerber
227 1 tkerber
        if self.ui.get_widget('/MenuBar/ToolsMenu/%sAtoms' % mode).get_active():
228 1 tkerber
            self.atoms_to_rotate_0 = self.images.selected.copy()
229 1 tkerber
            for i in range(len(self.images.selected)):
230 1 tkerber
               self.images.selected[i] = False
231 1 tkerber
            self.light_green_markings = 1
232 1 tkerber
        else:
233 1 tkerber
            try:
234 1 tkerber
                atr = self.atoms_to_rotate_0
235 1 tkerber
                for i in range(len(self.images.selected)):
236 1 tkerber
                    self.images.selected[i] = atr[i]
237 1 tkerber
            except:
238 1 tkerber
                pass
239 1 tkerber
240 1 tkerber
        self.menu_change = 0
241 1 tkerber
        self.draw()
242 1 tkerber
243 1 tkerber
    def toggle_move_mode(self, action):
244 1 tkerber
        """
245 1 tkerber
        Toggles the move mode, where the selected atoms can be moved with the arrow
246 1 tkerber
        keys and pg up/dn. If the shift key is pressed, the movement will be reduced.
247 1 tkerber

248 1 tkerber
        The movement will be relative to the current rotation of the coordinate system.
249 1 tkerber

250 1 tkerber
        The implementation of the move mode is found in the gui.scroll
251 1 tkerber
        """
252 1 tkerber
        if not (self.menu_change):
253 1 tkerber
            self.toggle_mode('Move')
254 1 tkerber
255 1 tkerber
    def toggle_rotate_mode(self, action):
256 1 tkerber
        """
257 1 tkerber
        Toggles the rotate mode, where the selected atoms can be rotated with the arrow keys
258 1 tkerber
        and pg up/dn. If the shift key is pressed, the rotation angle will be reduced.
259 1 tkerber

260 1 tkerber
        The atoms to be rotated will be marked with light green - and the COM of the selected
261 1 tkerber
        atoms will be used as the COM of the rotation. This can be changed while rotating the
262 1 tkerber
        selected atoms.
263 1 tkerber

264 1 tkerber
        If only two atoms are seleceted, and the number of atoms to be rotated is different from
265 1 tkerber
        two, the selected atoms will define the axis of rotation.
266 1 tkerber

267 1 tkerber
        The implementation of the rotate mode is found in the gui.scroll
268 1 tkerber
        """
269 1 tkerber
        if not (self.menu_change):
270 1 tkerber
            self.toggle_mode('Rotate')
271 1 tkerber
272 1 tkerber
    def toggle_orient_mode(self, action):
273 1 tkerber
        """
274 1 tkerber
        Toggle the orientation mode - the orientation of the atoms will be changed
275 1 tkerber
        according to the arrow keys selected.
276 1 tkerber

277 1 tkerber
        If nothing is selected, standard directions are x, y and z
278 1 tkerber
        if two atoms are selected, the standard directions are along their displacement vector
279 1 tkerber
        if three atoms are selected, the orientation is changed according to the normal of these
280 1 tkerber
        three vectors.
281 1 tkerber
        """
282 1 tkerber
        if not (self.menu_change):
283 1 tkerber
            self.toggle_mode('Orient')
284 1 tkerber
        self.orient_normal = np.array([1.0, 0.0, 0.0])
285 1 tkerber
        sel_pos = []
286 1 tkerber
        for i, j in enumerate(self.atoms_to_rotate_0):
287 1 tkerber
            if j:
288 1 tkerber
                sel_pos.append(self.R[i])
289 1 tkerber
        if len(sel_pos) == 2:
290 1 tkerber
            self.orient_normal = sel_pos[0] - sel_pos[1]
291 1 tkerber
        if len(sel_pos) == 3:
292 1 tkerber
            v1 = sel_pos[1] - sel_pos[0]
293 1 tkerber
            v2 = sel_pos[1] - sel_pos[2]
294 1 tkerber
            self.orient_normal = np.cross(v1, v2)
295 1 tkerber
        self.orient_normal /= sum(self.orient_normal ** 2) ** 0.5
296 1 tkerber
297 1 tkerber
    def toggle_show_axes(self, action):
298 1 tkerber
        self.draw()
299 1 tkerber
300 1 tkerber
    def toggle_show_bonds(self, action):
301 1 tkerber
        self.set_coordinates()
302 1 tkerber
303 1 tkerber
    def repeat_window(self, menuitem):
304 1 tkerber
        self.reset_tools_modes()
305 1 tkerber
        Repeat(self)
306 1 tkerber
307 1 tkerber
    def rotate_window(self, menuitem):
308 1 tkerber
        Rotate(self)
309 1 tkerber
310 1 tkerber
    def focus(self, x=None):
311 1 tkerber
        if (self.images.natoms == 0 and not
312 1 tkerber
            self.ui.get_widget('/MenuBar/ViewMenu/ShowUnitCell').get_active()):
313 1 tkerber
            self.scale = 1.0
314 1 tkerber
            self.center = np.zeros(3)
315 1 tkerber
            self.draw()
316 1 tkerber
            return
317 1 tkerber
318 1 tkerber
        P = np.dot(self.X, self.axes)
319 1 tkerber
        n = self.images.natoms
320 1 tkerber
        P[:n] -= self.images.r[:, None]
321 1 tkerber
        P1 = P.min(0)
322 1 tkerber
        P[:n] += 2 * self.images.r[:, None]
323 1 tkerber
        P2 = P.max(0)
324 1 tkerber
        self.center = np.dot(self.axes, (P1 + P2) / 2)
325 1 tkerber
        S = 1.3 * (P2 - P1)
326 1 tkerber
        if S[0] * self.height < S[1] * self.width:
327 1 tkerber
            self.scale = self.height / S[1]
328 1 tkerber
        else:
329 1 tkerber
            self.scale = self.width / S[0]
330 1 tkerber
        self.draw()
331 1 tkerber
332 1 tkerber
    def draw(self, status=True):
333 1 tkerber
        self.pixmap.draw_rectangle(self.white_gc, True, 0, 0,
334 1 tkerber
                                   self.width, self.height)
335 1 tkerber
        axes = self.scale * self.axes * (1, -1, 1)
336 1 tkerber
        offset = (np.dot(self.center, axes) -
337 1 tkerber
                  (0.5 * self.width, 0.5 * self.height, 0))
338 1 tkerber
        X = np.dot(self.X, axes) - offset
339 1 tkerber
        n = self.images.natoms
340 1 tkerber
        self.indices = X[:, 2].argsort()
341 1 tkerber
        P = self.P = X[:n, :2]
342 1 tkerber
        X1 = X[n:, :2].round().astype(int)
343 1 tkerber
        X2 = (np.dot(self.B, axes) - offset).round().astype(int)
344 1 tkerber
345 1 tkerber
        if self.ui.get_widget('/MenuBar/ViewMenu/ShowBonds').get_active():
346 1 tkerber
            r = self.images.r * (0.65 * self.scale)
347 1 tkerber
        else:
348 1 tkerber
            r = self.images.r * self.scale
349 1 tkerber
        A = (P - r[:, None]).round().astype(int)
350 1 tkerber
        d = (2 * r).round().astype(int)
351 1 tkerber
        selected_gc = self.selected_gc
352 1 tkerber
353 1 tkerber
        colors = self.colors
354 1 tkerber
        Z = self.images.Z
355 1 tkerber
        arc = self.pixmap.draw_arc
356 1 tkerber
        line = self.pixmap.draw_line
357 1 tkerber
        black_gc = self.black_gc
358 1 tkerber
        dynamic = self.images.dynamic
359 1 tkerber
        selected = self.images.selected
360 1 tkerber
        visible = self.images.visible
361 1 tkerber
        for a in self.indices:
362 1 tkerber
            if a < n:
363 1 tkerber
                ra = d[a]
364 1 tkerber
                if visible[a]:
365 1 tkerber
                    arc(colors[Z[a]], True, A[a, 0], A[a, 1], ra, ra, 0, 23040)
366 1 tkerber
                if  self.light_green_markings and self.atoms_to_rotate_0[a]:
367 1 tkerber
                    arc(self.green, False, A[a, 0] + 2, A[a, 1] + 2,
368 1 tkerber
                        ra - 4, ra - 4, 0, 23040)
369 1 tkerber
370 1 tkerber
                if not dynamic[a]:
371 1 tkerber
                    R1 = int(0.14644 * ra)
372 1 tkerber
                    R2 = int(0.85355 * ra)
373 1 tkerber
                    line(black_gc,
374 1 tkerber
                         A[a, 0] + R1, A[a, 1] + R1,
375 1 tkerber
                         A[a, 0] + R2, A[a, 1] + R2)
376 1 tkerber
                    line(black_gc,
377 1 tkerber
                         A[a, 0] + R2, A[a, 1] + R1,
378 1 tkerber
                         A[a, 0] + R1, A[a, 1] + R2)
379 1 tkerber
                if selected[a]:
380 1 tkerber
                    arc(selected_gc, False, A[a, 0], A[a, 1], ra, ra, 0, 23040)
381 1 tkerber
                elif visible[a]:
382 1 tkerber
                    arc(black_gc, False, A[a, 0], A[a, 1], ra, ra, 0, 23040)
383 1 tkerber
            else:
384 1 tkerber
                a -= n
385 1 tkerber
                line(black_gc, X1[a, 0], X1[a, 1], X2[a, 0], X2[a, 1])
386 1 tkerber
387 1 tkerber
        if self.ui.get_widget('/MenuBar/ViewMenu/ShowAxes').get_active():
388 1 tkerber
            self.draw_axes()
389 1 tkerber
390 1 tkerber
        if self.images.nimages > 1:
391 1 tkerber
            self.draw_frame_number()
392 1 tkerber
393 1 tkerber
        self.drawing_area.window.draw_drawable(self.white_gc, self.pixmap,
394 1 tkerber
                                               0, 0, 0, 0,
395 1 tkerber
                                               self.width, self.height)
396 1 tkerber
397 1 tkerber
        if status:
398 1 tkerber
            self.status()
399 1 tkerber
400 1 tkerber
    def draw_axes(self):
401 1 tkerber
        L = np.zeros((10, 2, 3))
402 1 tkerber
        L[:3, 1] = self.axes * 15
403 1 tkerber
        L[3:5] = self.axes[0] * 20
404 1 tkerber
        L[5:7] = self.axes[1] * 20
405 1 tkerber
        L[7:] = self.axes[2] * 20
406 1 tkerber
        L[3:, :, :2] += (((-4, -5), (4,  5)), ((-4,  5), ( 4, -5)),
407 1 tkerber
                         ((-4,  5), (0,  0)), ((-4, -5), ( 4,  5)),
408 1 tkerber
                         ((-4,  5), (4,  5)), (( 4,  5), (-4, -5)),
409 1 tkerber
                         ((-4, -5), (4, -5)))
410 1 tkerber
        L = L.round().astype(int)
411 1 tkerber
        L[:, :, 0] += 20
412 1 tkerber
        L[:, :, 1] = self.height - 20 - L[:, :, 1]
413 1 tkerber
        line = self.pixmap.draw_line
414 1 tkerber
        colors = ([self.black_gc] * 3 +
415 1 tkerber
                  [self.red] * 2 + [self.green] * 2 + [self.blue] * 3)
416 1 tkerber
        for i in L[:, 1, 2].argsort():
417 1 tkerber
            (a, b), (c, d) = L[i, :, :2]
418 1 tkerber
            line(colors[i], a, b, c, d)
419 1 tkerber
420 1 tkerber
    digits = np.array(((1, 1, 1, 1, 1, 1, 0),
421 1 tkerber
                       (0, 1, 1, 0, 0, 0, 0),
422 1 tkerber
                       (1, 0, 1, 1, 0, 1, 1),
423 1 tkerber
                       (1, 1, 1, 1, 0, 0, 1),
424 1 tkerber
                       (0, 1, 1, 0, 1, 0, 1),
425 1 tkerber
                       (1, 1, 0, 1, 1, 0, 1),
426 1 tkerber
                       (1, 1, 0, 1, 1, 1, 1),
427 1 tkerber
                       (0, 1, 1, 1, 0, 0, 0),
428 1 tkerber
                       (1, 1, 1, 1, 1, 1, 1),
429 1 tkerber
                       (0, 1, 1, 1, 1, 0, 1)), bool)
430 1 tkerber
431 1 tkerber
    bars = np.array(((0, 2, 1, 2),
432 1 tkerber
                     (1, 2, 1, 1),
433 1 tkerber
                     (1, 1, 1, 0),
434 1 tkerber
                     (1, 0, 0, 0),
435 1 tkerber
                     (0, 0, 0, 1),
436 1 tkerber
                     (0, 1, 0, 2),
437 1 tkerber
                     (0, 1, 1, 1))) * 5
438 1 tkerber
439 1 tkerber
    def draw_frame_number(self):
440 1 tkerber
        n = str(self.frame)
441 1 tkerber
        x = self.width - 3 - 8 * len(n)
442 1 tkerber
        y = self.height - 27
443 1 tkerber
        color = self.black_gc
444 1 tkerber
        line = self.pixmap.draw_line
445 1 tkerber
        for c in n:
446 1 tkerber
            bars = View.bars[View.digits[int(c)]]
447 1 tkerber
            for a, b, c, d in bars:
448 1 tkerber
                line(color, a + x, b + y, c + x, d + y)
449 1 tkerber
            x += 8
450 1 tkerber
451 1 tkerber
    def release(self, drawing_area, event):
452 1 tkerber
        if event.button != 1:
453 1 tkerber
            return
454 1 tkerber
455 1 tkerber
        selected = self.images.selected
456 1 tkerber
        selected_ordered = self.images.selected_ordered
457 1 tkerber
458 1 tkerber
        if event.time < self.t0 + 200:  # 200 ms
459 1 tkerber
            d = self.P - self.xy
460 1 tkerber
            hit = np.less((d**2).sum(1), (self.scale * self.images.r)**2)
461 1 tkerber
            for a in self.indices[::-1]:
462 1 tkerber
                if a < self.images.natoms and hit[a]:
463 1 tkerber
                    if event.state & gtk.gdk.CONTROL_MASK:
464 1 tkerber
                        selected[a] = not selected[a]
465 1 tkerber
                        if selected[a]:
466 1 tkerber
                            selected_ordered += [a]
467 1 tkerber
                        elif len(selected_ordered) > 0:
468 1 tkerber
                            if selected_ordered[-1] == a:
469 1 tkerber
                                selected_ordered = selected_ordered[:-1]
470 1 tkerber
                            else:
471 1 tkerber
                                selected_ordered = []
472 1 tkerber
                    else:
473 1 tkerber
                        selected[:] = False
474 1 tkerber
                        selected[a] = True
475 1 tkerber
                        selected_ordered = [a]
476 1 tkerber
                    break
477 1 tkerber
            else:
478 1 tkerber
                selected[:] = False
479 1 tkerber
                selected_ordered = []
480 1 tkerber
            self.draw()
481 1 tkerber
        else:
482 1 tkerber
            A = (event.x, event.y)
483 1 tkerber
            C1 = np.minimum(A, self.xy)
484 1 tkerber
            C2 = np.maximum(A, self.xy)
485 1 tkerber
            hit = np.logical_and(self.P > C1, self.P < C2)
486 1 tkerber
            indices = np.compress(hit.prod(1), np.arange(len(hit)))
487 1 tkerber
            if not (event.state & gtk.gdk.CONTROL_MASK):
488 1 tkerber
                selected[:] = False
489 1 tkerber
            selected[indices] = True
490 1 tkerber
            if len(indices) == 1 and indices[0] not in self.images.selected_ordered:
491 1 tkerber
                selected_ordered += [indices[0]]
492 1 tkerber
            elif len(indices) > 1:
493 1 tkerber
                selected_ordered = []
494 1 tkerber
            self.draw()
495 1 tkerber
496 1 tkerber
        indices = np.arange(self.images.natoms)[self.images.selected]
497 1 tkerber
        if len(indices) != len(selected_ordered):
498 1 tkerber
            selected_ordered = []
499 1 tkerber
        self.images.selected_ordered = selected_ordered
500 1 tkerber
501 1 tkerber
    def press(self, drawing_area, event):
502 1 tkerber
        self.button = event.button
503 1 tkerber
        self.xy = (event.x, event.y)
504 1 tkerber
        self.t0 = event.time
505 1 tkerber
        self.axes0 = self.axes
506 1 tkerber
        self.center0 = self.center
507 1 tkerber
508 1 tkerber
    def move(self, drawing_area, event):
509 1 tkerber
510 1 tkerber
        x, y, state = event.window.get_pointer()
511 1 tkerber
        x0, y0 = self.xy
512 1 tkerber
        if self.button == 1:
513 1 tkerber
            window = self.drawing_area.window
514 1 tkerber
            window.draw_drawable(self.white_gc, self.pixmap,
515 1 tkerber
                                 0, 0, 0, 0,
516 1 tkerber
                                 self.width, self.height)
517 1 tkerber
            x0 = int(round(x0))
518 1 tkerber
            y0 = int(round(y0))
519 1 tkerber
            window.draw_rectangle(self.selected_gc, False,
520 1 tkerber
                                  min(x, x0), min(y, y0),
521 1 tkerber
                                  abs(x - x0), abs(y - y0))
522 1 tkerber
            return
523 1 tkerber
        if self.button == 2:
524 1 tkerber
            return
525 1 tkerber
        if state & gtk.gdk.SHIFT_MASK:
526 1 tkerber
            self.center = (self.center0 -
527 1 tkerber
                           np.dot(self.axes, (x - x0, y0 - y, 0)) / self.scale)
528 1 tkerber
        else:
529 1 tkerber
            # Snap mode: the a-b angle and t should multipla of 15 degrees ???
530 1 tkerber
            a = x - x0
531 1 tkerber
            b = y0 - y
532 1 tkerber
            t = sqrt(a * a + b * b)
533 1 tkerber
            if t > 0:
534 1 tkerber
                a /= t
535 1 tkerber
                b /= t
536 1 tkerber
            else:
537 1 tkerber
                a = 1.0
538 1 tkerber
                b = 0.0
539 1 tkerber
            c = cos(0.01 * t)
540 1 tkerber
            s = -sin(0.01 * t)
541 1 tkerber
            rotation = np.array([(c * a * a + b * b, (c - 1) * b * a, s * a),
542 1 tkerber
                                 ((c - 1) * a * b, c * b * b + a * a, s * b),
543 1 tkerber
                                 (-s * a, -s * b, c)])
544 1 tkerber
            self.axes = np.dot(self.axes0, rotation)
545 1 tkerber
            if self.images.natoms > 0:
546 1 tkerber
                com = self.X[:self.images.natoms].mean(0)
547 1 tkerber
            else:
548 1 tkerber
                com = self.images.A[self.frame].mean(0)
549 1 tkerber
            self.center = com - np.dot(com - self.center0,
550 1 tkerber
                                       np.dot(self.axes0, self.axes.T))
551 1 tkerber
        self.draw(status=False)
552 1 tkerber
553 1 tkerber
    # Create a new backing pixmap of the appropriate size
554 1 tkerber
    def configure_event(self, drawing_area, event):
555 1 tkerber
        if self.configured:
556 1 tkerber
            w = self.width
557 1 tkerber
            h = self.height
558 1 tkerber
        else:
559 1 tkerber
            self.colormap = self.drawing_area.get_colormap()
560 1 tkerber
            self.black_gc = self.drawing_area.get_style().black_gc
561 1 tkerber
            self.white_gc = self.drawing_area.get_style().white_gc
562 1 tkerber
            self.red = self.drawing_area.window.new_gc(
563 1 tkerber
                self.colormap.alloc_color(62345, 0, 0), line_width=2)
564 1 tkerber
            self.green = self.drawing_area.window.new_gc(
565 1 tkerber
                self.colormap.alloc_color(0, 54456, 0), line_width=2)
566 1 tkerber
            self.blue = self.drawing_area.window.new_gc(
567 1 tkerber
                self.colormap.alloc_color(0, 0, 54456), line_width=2)
568 1 tkerber
            self.selected_gc = self.drawing_area.window.new_gc(
569 1 tkerber
                self.colormap.alloc_color(0, 16456, 0),
570 1 tkerber
                line_width=3)
571 1 tkerber
572 1 tkerber
        x, y, self.width, self.height = drawing_area.get_allocation()
573 1 tkerber
        self.pixmap = gtk.gdk.Pixmap(drawing_area.window,
574 1 tkerber
                                     self.width, self.height)
575 1 tkerber
        if self.configured:
576 1 tkerber
            self.scale *= sqrt(1.0 * self.width * self.height / (w * h))
577 1 tkerber
            self.draw()
578 1 tkerber
        self.configured = True
579 1 tkerber
580 1 tkerber
    # Redraw the screen from the backing pixmap
581 1 tkerber
    def expose_event(self, drawing_area, event):
582 1 tkerber
        x , y, width, height = event.area
583 1 tkerber
        gc = self.white_gc
584 1 tkerber
        drawing_area.window.draw_drawable(gc, self.pixmap,
585 1 tkerber
                                          x, y, x, y, width, height)
586 1 tkerber
587 1 tkerber
    def external_viewer(self, action):
588 1 tkerber
        name = action.get_name()
589 1 tkerber
        command = {'Avogadro' : 'avogadro',
590 1 tkerber
                   'XMakeMol': 'xmakemol -f',
591 1 tkerber
                   'RasMol':'rasmol -xyz',
592 1 tkerber
                   'VMD': 'vmd'}[name]
593 1 tkerber
        fd, filename = tempfile.mkstemp('.xyz', 'ase.gui-')
594 1 tkerber
        os.close(fd)
595 1 tkerber
        self.images.write(filename)
596 1 tkerber
        os.system('(%s %s &); (sleep 60; rm %s) &' %
597 1 tkerber
                  (command, filename, filename))