root / ase / gui / gui.py @ 3
Historique | Voir | Annoter | Télécharger (41,34 ko)
1 | 1 | tkerber | # husk:
|
---|---|---|---|
2 | 1 | tkerber | # Exit*2? remove pylab.show()
|
3 | 1 | tkerber | # close button
|
4 | 1 | tkerber | # DFT
|
5 | 1 | tkerber | # ADOS
|
6 | 1 | tkerber | # grey-out stuff after one second: vmd, rasmol, ...
|
7 | 1 | tkerber | # Show with ....
|
8 | 1 | tkerber | # rasmol: set same rotation as ag
|
9 | 1 | tkerber | # Graphs: save, Python, 3D
|
10 | 1 | tkerber | # start from python (interactive mode?)
|
11 | 1 | tkerber | # ascii-art option (colored)|
|
12 | 1 | tkerber | # option -o (output) and -f (force overwrite)
|
13 | 1 | tkerber | # surfacebuilder
|
14 | 1 | tkerber | # screen-dump
|
15 | 1 | tkerber | # icon
|
16 | 1 | tkerber | # ag-community-server
|
17 | 1 | tkerber | # translate option: record all translations,
|
18 | 1 | tkerber | # and check for missing translations.
|
19 | 1 | tkerber | |
20 | 1 | tkerber | #TODO: Add possible way of choosing orinetations. \
|
21 | 1 | tkerber | #TODO: Two atoms defines a direction, three atoms their normal does
|
22 | 1 | tkerber | #TODO: Align orientations chosen in Rot_selected v unselcted
|
23 | 1 | tkerber | #TODO: Get the atoms_rotate_0 thing string
|
24 | 1 | tkerber | #TODO: Use set atoms instead og the get atoms
|
25 | 1 | tkerber | #TODO: Arrow keys will decide how the orientation changes
|
26 | 1 | tkerber | #TODO: Undo redo que should be implemented
|
27 | 1 | tkerber | #TODO: Update should have possibility to change positions
|
28 | 1 | tkerber | #TODO: Window for rotation modes and move moves which can be chosen
|
29 | 1 | tkerber | #TODO: WHen rotate and move / hide the movie menu
|
30 | 1 | tkerber | |
31 | 1 | tkerber | import os |
32 | 1 | tkerber | import weakref |
33 | 1 | tkerber | import numpy as np |
34 | 1 | tkerber | |
35 | 1 | tkerber | import gtk |
36 | 1 | tkerber | from ase.gui.view import View |
37 | 1 | tkerber | from ase.gui.status import Status |
38 | 1 | tkerber | from ase.gui.widgets import pack, help, Help, oops |
39 | 1 | tkerber | from ase.gui.languages import translate as _ |
40 | 1 | tkerber | |
41 | 1 | tkerber | from ase.gui.settings import Settings |
42 | 1 | tkerber | from ase.gui.surfaceslab import SetupSurfaceSlab |
43 | 1 | tkerber | from ase.gui.nanoparticle import SetupNanoparticle |
44 | 1 | tkerber | from ase.gui.nanotube import SetupNanotube |
45 | 1 | tkerber | from ase.gui.graphene import SetupGraphene |
46 | 1 | tkerber | from ase.gui.calculator import SetCalculator |
47 | 1 | tkerber | from ase.gui.energyforces import EnergyForces |
48 | 1 | tkerber | from ase.gui.minimize import Minimize |
49 | 1 | tkerber | from ase.gui.scaling import HomogeneousDeformation |
50 | 1 | tkerber | |
51 | 1 | tkerber | ui_info = """\
|
52 | 1 | tkerber | <ui>
|
53 | 1 | tkerber | <menubar name='MenuBar'>
|
54 | 1 | tkerber | <menu action='FileMenu'>
|
55 | 1 | tkerber | <menuitem action='Open'/>
|
56 | 1 | tkerber | <menuitem action='New'/>
|
57 | 1 | tkerber | <menuitem action='Save'/>
|
58 | 1 | tkerber | <separator/>
|
59 | 1 | tkerber | <menuitem action='Quit'/>
|
60 | 1 | tkerber | </menu>
|
61 | 1 | tkerber | <menu action='EditMenu'>
|
62 | 1 | tkerber | <menuitem action='SelectAll'/>
|
63 | 1 | tkerber | <menuitem action='Invert'/>
|
64 | 1 | tkerber | <menuitem action='SelectConstrained'/>
|
65 | 1 | tkerber | <separator/>
|
66 | 1 | tkerber | <menuitem action='Modify'/>
|
67 | 1 | tkerber | <menuitem action='AddAtoms'/>
|
68 | 1 | tkerber | <menuitem action='DeleteAtoms'/>
|
69 | 1 | tkerber | <separator/>
|
70 | 1 | tkerber | <menuitem action='First'/>
|
71 | 1 | tkerber | <menuitem action='Previous'/>
|
72 | 1 | tkerber | <menuitem action='Next'/>
|
73 | 1 | tkerber | <menuitem action='Last'/>
|
74 | 1 | tkerber | </menu>
|
75 | 1 | tkerber | <menu action='ViewMenu'>
|
76 | 1 | tkerber | <menuitem action='ShowUnitCell'/>
|
77 | 1 | tkerber | <menuitem action='ShowAxes'/>
|
78 | 1 | tkerber | <menuitem action='ShowBonds'/>
|
79 | 1 | tkerber | <separator/>
|
80 | 1 | tkerber | <menuitem action='Repeat'/>
|
81 | 1 | tkerber | <menuitem action='Rotate'/>
|
82 | 1 | tkerber | <menuitem action='Focus'/>
|
83 | 1 | tkerber | <menuitem action='ZoomIn'/>
|
84 | 1 | tkerber | <menuitem action='ZoomOut'/>
|
85 | 1 | tkerber | <menuitem action='Settings'/>
|
86 | 1 | tkerber | <menuitem action='VMD'/>
|
87 | 1 | tkerber | <menuitem action='RasMol'/>
|
88 | 1 | tkerber | <menuitem action='XMakeMol'/>
|
89 | 1 | tkerber | <menuitem action='Avogadro'/>
|
90 | 1 | tkerber | </menu>
|
91 | 1 | tkerber | <menu action='ToolsMenu'>
|
92 | 1 | tkerber | <menuitem action='Graphs'/>
|
93 | 1 | tkerber | <menuitem action='Movie'/>
|
94 | 1 | tkerber | <menuitem action='EModify'/>
|
95 | 1 | tkerber | <menuitem action='Constraints'/>
|
96 | 1 | tkerber | <menuitem action='MoveAtoms'/>
|
97 | 1 | tkerber | <menuitem action='RotateAtoms'/>
|
98 | 1 | tkerber | <menuitem action='OrientAtoms'/>
|
99 | 1 | tkerber | <menuitem action='DFT'/>
|
100 | 1 | tkerber | <menuitem action='NEB'/>
|
101 | 1 | tkerber | <menuitem action='BulkModulus'/>
|
102 | 1 | tkerber | </menu>
|
103 | 1 | tkerber | <menu action='SetupMenu'>
|
104 | 1 | tkerber | <menuitem action='Surface'/>
|
105 | 1 | tkerber | <menuitem action='Nanoparticle'/>
|
106 | 1 | tkerber | <menuitem action='Graphene'/>
|
107 | 1 | tkerber | <menuitem action='Nanotube'/>
|
108 | 1 | tkerber | </menu>
|
109 | 1 | tkerber | <menu action='CalculateMenu'>
|
110 | 1 | tkerber | <menuitem action='SetCalculator'/>
|
111 | 1 | tkerber | <separator/>
|
112 | 1 | tkerber | <menuitem action='EnergyForces'/>
|
113 | 1 | tkerber | <menuitem action='Minimize'/>
|
114 | 1 | tkerber | <menuitem action='Scaling'/>
|
115 | 1 | tkerber | </menu>
|
116 | 1 | tkerber | <menu action='HelpMenu'>
|
117 | 1 | tkerber | <menuitem action='About'/>
|
118 | 1 | tkerber | <menuitem action='Webpage'/>
|
119 | 1 | tkerber | <menuitem action='Debug'/>
|
120 | 1 | tkerber | </menu>
|
121 | 1 | tkerber | </menubar>
|
122 | 1 | tkerber | </ui>"""
|
123 | 1 | tkerber | |
124 | 1 | tkerber | class GUI(View, Status): |
125 | 1 | tkerber | def __init__(self, images, rotations='', show_unit_cell=True, |
126 | 1 | tkerber | show_bonds=False):
|
127 | 1 | tkerber | self.images = images
|
128 | 1 | tkerber | self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
129 | 1 | tkerber | #self.window.set_icon(gtk.gdk.pixbuf_new_from_file('guiase.png'))
|
130 | 1 | tkerber | self.window.set_position(gtk.WIN_POS_CENTER)
|
131 | 1 | tkerber | #self.window.connect("destroy", lambda w: gtk.main_quit())
|
132 | 1 | tkerber | self.window.connect('delete_event', self.exit) |
133 | 1 | tkerber | vbox = gtk.VBox() |
134 | 1 | tkerber | self.window.add(vbox)
|
135 | 1 | tkerber | if gtk.pygtk_version < (2, 12): |
136 | 1 | tkerber | self.set_tip = gtk.Tooltips().set_tip
|
137 | 1 | tkerber | |
138 | 1 | tkerber | actions = gtk.ActionGroup("Actions")
|
139 | 1 | tkerber | actions.add_actions([ |
140 | 1 | tkerber | ('FileMenu', None, '_File'), |
141 | 1 | tkerber | ('EditMenu', None, '_Edit'), |
142 | 1 | tkerber | ('ViewMenu', None, '_View' ), |
143 | 1 | tkerber | ('ToolsMenu', None, '_Tools'), |
144 | 1 | tkerber | ('SetupMenu', None, '_Setup'), |
145 | 1 | tkerber | ('CalculateMenu', None, '_Calculate'), |
146 | 1 | tkerber | ('HelpMenu', None, '_Help'), |
147 | 1 | tkerber | ('Open', gtk.STOCK_OPEN, '_Open', '<control>O', |
148 | 1 | tkerber | 'Create a new file',
|
149 | 1 | tkerber | self.open),
|
150 | 1 | tkerber | ('New', gtk.STOCK_NEW, '_New', '<control>N', |
151 | 1 | tkerber | 'New ase.gui window',
|
152 | 1 | tkerber | lambda widget: os.system('ag &')), |
153 | 1 | tkerber | ('Save', gtk.STOCK_SAVE, '_Save', '<control>S', |
154 | 1 | tkerber | 'Save current file',
|
155 | 1 | tkerber | self.save),
|
156 | 1 | tkerber | ('Quit', gtk.STOCK_QUIT, '_Quit', '<control>Q', |
157 | 1 | tkerber | 'Quit',
|
158 | 1 | tkerber | self.exit),
|
159 | 1 | tkerber | ('SelectAll', None, 'Select _all', None, |
160 | 1 | tkerber | '',
|
161 | 1 | tkerber | self.select_all),
|
162 | 1 | tkerber | ('Invert', None, '_Invert selection', None, |
163 | 1 | tkerber | '',
|
164 | 1 | tkerber | self.invert_selection),
|
165 | 1 | tkerber | ('SelectConstrained', None, 'Select _constrained atoms', None, |
166 | 1 | tkerber | '',
|
167 | 1 | tkerber | self.select_constrained_atoms),
|
168 | 1 | tkerber | ('Modify', None, '_Modify', '<control>Y', |
169 | 1 | tkerber | 'Change tags, moments and atom types of the selected atoms',
|
170 | 1 | tkerber | self.modify_atoms),
|
171 | 1 | tkerber | ('AddAtoms', None, '_Add atoms', '<control>A', |
172 | 1 | tkerber | 'Insert or import atoms and molecules',
|
173 | 1 | tkerber | self.add_atoms),
|
174 | 1 | tkerber | ('DeleteAtoms', None, '_Delete selected atoms', 'BackSpace', |
175 | 1 | tkerber | 'Deletes the selected atoms',
|
176 | 1 | tkerber | self.delete_selected_atoms),
|
177 | 1 | tkerber | ('First', gtk.STOCK_GOTO_FIRST, '_First image', 'Home', |
178 | 1 | tkerber | '',
|
179 | 1 | tkerber | self.step),
|
180 | 1 | tkerber | ('Previous', gtk.STOCK_GO_BACK, '_Previous image', 'Page_Up', |
181 | 1 | tkerber | '',
|
182 | 1 | tkerber | self.step),
|
183 | 1 | tkerber | ('Next', gtk.STOCK_GO_FORWARD, '_Next image', 'Page_Down', |
184 | 1 | tkerber | '',
|
185 | 1 | tkerber | self.step),
|
186 | 1 | tkerber | ('Last', gtk.STOCK_GOTO_LAST, '_Last image', 'End', |
187 | 1 | tkerber | '',
|
188 | 1 | tkerber | self.step),
|
189 | 1 | tkerber | ('Repeat', None, 'Repeat ...', None, |
190 | 1 | tkerber | '',
|
191 | 1 | tkerber | self.repeat_window),
|
192 | 1 | tkerber | ('Rotate', None, 'Rotate ...', None, |
193 | 1 | tkerber | '',
|
194 | 1 | tkerber | self.rotate_window),
|
195 | 1 | tkerber | ('Focus', gtk.STOCK_ZOOM_FIT, 'Focus', 'F', |
196 | 1 | tkerber | '',
|
197 | 1 | tkerber | self.focus),
|
198 | 1 | tkerber | ('ZoomIn', gtk.STOCK_ZOOM_IN, 'Zoom in', 'plus', |
199 | 1 | tkerber | '',
|
200 | 1 | tkerber | self.zoom),
|
201 | 1 | tkerber | ('ZoomOut', gtk.STOCK_ZOOM_OUT, 'Zoom out', 'minus', |
202 | 1 | tkerber | '',
|
203 | 1 | tkerber | self.zoom),
|
204 | 1 | tkerber | ('Settings', gtk.STOCK_PREFERENCES, 'Settings ...', None, |
205 | 1 | tkerber | '',
|
206 | 1 | tkerber | self.settings),
|
207 | 1 | tkerber | ('VMD', None, 'VMD', None, |
208 | 1 | tkerber | '',
|
209 | 1 | tkerber | self.external_viewer),
|
210 | 1 | tkerber | ('RasMol', None, 'RasMol', None, |
211 | 1 | tkerber | '',
|
212 | 1 | tkerber | self.external_viewer),
|
213 | 1 | tkerber | ('XMakeMol', None, 'xmakemol', None, |
214 | 1 | tkerber | '',
|
215 | 1 | tkerber | self.external_viewer),
|
216 | 1 | tkerber | ('Avogadro', None, 'avogadro', None, |
217 | 1 | tkerber | '',
|
218 | 1 | tkerber | self.external_viewer),
|
219 | 1 | tkerber | ('Graphs', None, 'Graphs ...', None, |
220 | 1 | tkerber | '',
|
221 | 1 | tkerber | self.plot_graphs),
|
222 | 1 | tkerber | ('Movie', None, 'Movie ...', None, |
223 | 1 | tkerber | '',
|
224 | 1 | tkerber | self.movie),
|
225 | 1 | tkerber | ('EModify', None, 'Expert modify ...', None, |
226 | 1 | tkerber | '',
|
227 | 1 | tkerber | self.execute),
|
228 | 1 | tkerber | ('Constraints', None, 'Constraints ...', None, |
229 | 1 | tkerber | '',
|
230 | 1 | tkerber | self.constraints_window),
|
231 | 1 | tkerber | ('DFT', None, 'DFT ...', None, |
232 | 1 | tkerber | '',
|
233 | 1 | tkerber | self.dft_window),
|
234 | 1 | tkerber | ('NEB', None, 'NE_B', None, |
235 | 1 | tkerber | '',
|
236 | 1 | tkerber | self.NEB),
|
237 | 1 | tkerber | ('BulkModulus', None, 'B_ulk Modulus', None, |
238 | 1 | tkerber | '',
|
239 | 1 | tkerber | self.bulk_modulus),
|
240 | 1 | tkerber | ('Bulk', None, '_Bulk Crystal', None, |
241 | 1 | tkerber | "Create a bulk crystal with arbitrary orientation",
|
242 | 1 | tkerber | self.bulk_window),
|
243 | 1 | tkerber | ('Surface', None, '_Surface slab', None, |
244 | 1 | tkerber | "Create the most common surfaces",
|
245 | 1 | tkerber | self.surface_window),
|
246 | 1 | tkerber | ('Nanoparticle', None, '_Nanoparticle', None, |
247 | 1 | tkerber | "Create a crystalline nanoparticle",
|
248 | 1 | tkerber | self.nanoparticle_window),
|
249 | 1 | tkerber | ('Nanotube', None, 'Nano_tube', None, |
250 | 1 | tkerber | "Create a nanotube",
|
251 | 1 | tkerber | self.nanotube_window),
|
252 | 1 | tkerber | ('Graphene', None, 'Graphene', None, |
253 | 1 | tkerber | "Create a graphene sheet or nanoribbon",
|
254 | 1 | tkerber | self.graphene_window),
|
255 | 1 | tkerber | ('SetCalculator', None, 'Set _Calculator', None, |
256 | 1 | tkerber | "Set a calculator used in all calculation modules",
|
257 | 1 | tkerber | self.calculator_window),
|
258 | 1 | tkerber | ('EnergyForces', None, '_Energy and Forces', None, |
259 | 1 | tkerber | "Calculate energy and forces",
|
260 | 1 | tkerber | self.energy_window),
|
261 | 1 | tkerber | ('Minimize', None, 'Energy _Minimization', None, |
262 | 1 | tkerber | "Minimize the energy",
|
263 | 1 | tkerber | self.energy_minimize_window),
|
264 | 1 | tkerber | ('Scaling', None, 'Scale system', None, |
265 | 1 | tkerber | "Deform system by scaling it",
|
266 | 1 | tkerber | self.scaling_window),
|
267 | 1 | tkerber | ('About', None, '_About', None, |
268 | 1 | tkerber | None,
|
269 | 1 | tkerber | self.about),
|
270 | 1 | tkerber | ('Webpage', gtk.STOCK_HELP, 'Webpage ...', None, None, webpage), |
271 | 1 | tkerber | ('Debug', None, 'Debug ...', None, None, self.debug)]) |
272 | 1 | tkerber | actions.add_toggle_actions([ |
273 | 1 | tkerber | ('ShowUnitCell', None, 'Show _unit cell', '<control>U', |
274 | 1 | tkerber | 'Bold',
|
275 | 1 | tkerber | self.toggle_show_unit_cell,
|
276 | 1 | tkerber | show_unit_cell > 0),
|
277 | 1 | tkerber | ('ShowAxes', None, 'Show _axes', None, |
278 | 1 | tkerber | 'Bold',
|
279 | 1 | tkerber | self.toggle_show_axes,
|
280 | 1 | tkerber | True),
|
281 | 1 | tkerber | ('ShowBonds', None, 'Show _bonds', '<control>B', |
282 | 1 | tkerber | 'Bold',
|
283 | 1 | tkerber | self.toggle_show_bonds,
|
284 | 1 | tkerber | show_bonds), |
285 | 1 | tkerber | ('MoveAtoms', None, '_Move atoms', '<control>M', |
286 | 1 | tkerber | 'Bold',
|
287 | 1 | tkerber | self.toggle_move_mode,
|
288 | 1 | tkerber | False),
|
289 | 1 | tkerber | ('RotateAtoms', None, '_Rotate atoms', '<control>R', |
290 | 1 | tkerber | 'Bold',
|
291 | 1 | tkerber | self.toggle_rotate_mode,
|
292 | 1 | tkerber | False),
|
293 | 1 | tkerber | ('OrientAtoms', None, 'Orien_t atoms', '<control>T', |
294 | 1 | tkerber | 'Bold',
|
295 | 1 | tkerber | self.toggle_orient_mode,
|
296 | 1 | tkerber | False)
|
297 | 1 | tkerber | ]) |
298 | 1 | tkerber | self.ui = ui = gtk.UIManager()
|
299 | 1 | tkerber | ui.insert_action_group(actions, 0)
|
300 | 1 | tkerber | self.window.add_accel_group(ui.get_accel_group())
|
301 | 1 | tkerber | |
302 | 1 | tkerber | try:
|
303 | 1 | tkerber | mergeid = ui.add_ui_from_string(ui_info) |
304 | 1 | tkerber | except gobject.GError, msg:
|
305 | 1 | tkerber | print 'building menus failed: %s' % msg |
306 | 1 | tkerber | |
307 | 1 | tkerber | vbox.pack_start(ui.get_widget('/MenuBar'), False, False, 0) |
308 | 1 | tkerber | |
309 | 1 | tkerber | View.__init__(self, vbox, rotations)
|
310 | 1 | tkerber | Status.__init__(self, vbox)
|
311 | 1 | tkerber | vbox.show() |
312 | 1 | tkerber | #self.window.set_events(gtk.gdk.BUTTON_PRESS_MASK)
|
313 | 1 | tkerber | self.window.connect('key-press-event', self.scroll) |
314 | 1 | tkerber | self.window.connect('scroll_event', self.scroll_event) |
315 | 1 | tkerber | self.window.show()
|
316 | 1 | tkerber | self.graphs = [] # List of open pylab windows |
317 | 1 | tkerber | self.graph_wref = [] # List of weakrefs to Graph objects |
318 | 1 | tkerber | self.movie_window = None |
319 | 1 | tkerber | self.vulnerable_windows = []
|
320 | 1 | tkerber | self.simulation = {} # Used by modules on Calculate menu. |
321 | 1 | tkerber | self.module_state = {} # Used by modules to store their state. |
322 | 1 | tkerber | |
323 | 1 | tkerber | def run(self, expr=None): |
324 | 1 | tkerber | self.set_colors()
|
325 | 1 | tkerber | self.set_coordinates(self.images.nimages - 1, focus=True) |
326 | 1 | tkerber | |
327 | 1 | tkerber | if self.images.nimages > 1: |
328 | 1 | tkerber | self.movie()
|
329 | 1 | tkerber | |
330 | 1 | tkerber | if expr is None and not np.isnan(self.images.E[0]): |
331 | 1 | tkerber | expr = 'i, e - E[-1]'
|
332 | 1 | tkerber | |
333 | 1 | tkerber | if expr is not None and expr != '' and self.images.nimages > 1: |
334 | 1 | tkerber | self.plot_graphs(expr=expr)
|
335 | 1 | tkerber | |
336 | 1 | tkerber | gtk.main() |
337 | 1 | tkerber | |
338 | 1 | tkerber | |
339 | 1 | tkerber | def step(self, action): |
340 | 1 | tkerber | d = {'First': -10000000, |
341 | 1 | tkerber | 'Previous': -1, |
342 | 1 | tkerber | 'Next': 1, |
343 | 1 | tkerber | 'Last': 10000000}[action.get_name()] |
344 | 1 | tkerber | i = max(0, min(self.images.nimages - 1, self.frame + d)) |
345 | 1 | tkerber | self.set_frame(i)
|
346 | 1 | tkerber | if self.movie_window is not None: |
347 | 1 | tkerber | self.movie_window.frame_number.value = i
|
348 | 1 | tkerber | |
349 | 1 | tkerber | def _do_zoom(self, x): |
350 | 1 | tkerber | """Utility method for zooming"""
|
351 | 1 | tkerber | self.scale *= x
|
352 | 1 | tkerber | self.draw()
|
353 | 1 | tkerber | |
354 | 1 | tkerber | def zoom(self, action): |
355 | 1 | tkerber | """Zoom in/out on keypress or clicking menu item"""
|
356 | 1 | tkerber | x = {'ZoomIn': 1.2, 'ZoomOut':1 / 1.2}[action.get_name()] |
357 | 1 | tkerber | self._do_zoom(x)
|
358 | 1 | tkerber | |
359 | 1 | tkerber | def scroll_event(self, window, event): |
360 | 1 | tkerber | """Zoom in/out when using mouse wheel"""
|
361 | 1 | tkerber | x = 1.0
|
362 | 1 | tkerber | if event.direction == gtk.gdk.SCROLL_UP:
|
363 | 1 | tkerber | x = 1.2
|
364 | 1 | tkerber | elif event.direction == gtk.gdk.SCROLL_DOWN:
|
365 | 1 | tkerber | x = 1.0 / 1.2 |
366 | 1 | tkerber | self._do_zoom(x)
|
367 | 1 | tkerber | |
368 | 1 | tkerber | def settings(self, menuitem): |
369 | 1 | tkerber | Settings(self)
|
370 | 1 | tkerber | |
371 | 1 | tkerber | def scroll(self, window, event): |
372 | 1 | tkerber | from copy import copy |
373 | 1 | tkerber | CTRL = event.state == gtk.gdk.CONTROL_MASK |
374 | 1 | tkerber | SHIFT = event.state == gtk.gdk.SHIFT_MASK |
375 | 1 | tkerber | dxdydz = {gtk.keysyms.KP_Add: ('zoom', 1.2, 0), |
376 | 1 | tkerber | gtk.keysyms.KP_Subtract: ('zoom', 1 / 1.2, 0), |
377 | 1 | tkerber | gtk.keysyms.Up: ( 0, +1 - CTRL, +CTRL), |
378 | 1 | tkerber | gtk.keysyms.Down: ( 0, -1 + CTRL, -CTRL), |
379 | 1 | tkerber | gtk.keysyms.Right: (+1, 0, 0), |
380 | 1 | tkerber | gtk.keysyms.Left: (-1, 0, 0)}.get(event.keyval, None) |
381 | 1 | tkerber | try:
|
382 | 1 | tkerber | inch = chr(event.keyval)
|
383 | 1 | tkerber | except:
|
384 | 1 | tkerber | inch = None
|
385 | 1 | tkerber | |
386 | 1 | tkerber | sel = [] |
387 | 1 | tkerber | |
388 | 1 | tkerber | atom_move = self.ui.get_widget('/MenuBar/ToolsMenu/MoveAtoms' |
389 | 1 | tkerber | ).get_active() |
390 | 1 | tkerber | atom_rotate = self.ui.get_widget('/MenuBar/ToolsMenu/RotateAtoms' |
391 | 1 | tkerber | ).get_active() |
392 | 1 | tkerber | atom_orient = self.ui.get_widget('/MenuBar/ToolsMenu/OrientAtoms' |
393 | 1 | tkerber | ).get_active() |
394 | 1 | tkerber | if dxdydz is None: |
395 | 1 | tkerber | return
|
396 | 1 | tkerber | dx, dy, dz = dxdydz |
397 | 1 | tkerber | if dx == 'zoom': |
398 | 1 | tkerber | self._do_zoom(dy)
|
399 | 1 | tkerber | return
|
400 | 1 | tkerber | if dx == 'zoom': |
401 | 1 | tkerber | self._do_zoom(dy)
|
402 | 1 | tkerber | return
|
403 | 1 | tkerber | d = self.scale * 0.1 |
404 | 1 | tkerber | tvec = np.array([dx, dy, dz]) |
405 | 1 | tkerber | |
406 | 1 | tkerber | dir_vec = np.dot(self.axes, tvec)
|
407 | 1 | tkerber | if (atom_move):
|
408 | 1 | tkerber | rotmat = self.axes
|
409 | 1 | tkerber | s = 0.1
|
410 | 1 | tkerber | if SHIFT:
|
411 | 1 | tkerber | s = 0.01
|
412 | 1 | tkerber | add = s * dir_vec |
413 | 1 | tkerber | for i in range(len(self.R)): |
414 | 1 | tkerber | if self.atoms_to_rotate_0[i]: |
415 | 1 | tkerber | self.R[i] += add
|
416 | 1 | tkerber | for jx in range(self.images.nimages): |
417 | 1 | tkerber | self.images.P[jx][i] += add
|
418 | 1 | tkerber | elif atom_rotate:
|
419 | 1 | tkerber | from rot_tools import rotate_about_vec, \ |
420 | 1 | tkerber | rotate_vec
|
421 | 1 | tkerber | sel = self.images.selected
|
422 | 1 | tkerber | if sum(sel) == 0: |
423 | 1 | tkerber | sel = self.atoms_to_rotate_0
|
424 | 1 | tkerber | nsel = sum(sel)
|
425 | 1 | tkerber | # this is the first one to get instatiated
|
426 | 1 | tkerber | if nsel != 2: |
427 | 1 | tkerber | self.rot_vec = dir_vec
|
428 | 1 | tkerber | |
429 | 1 | tkerber | change = False
|
430 | 1 | tkerber | z_axis = np.dot(self.axes, np.array([0, 0, 1])) |
431 | 1 | tkerber | if self.atoms_to_rotate == None: |
432 | 1 | tkerber | change = True
|
433 | 1 | tkerber | self.z_axis_old = z_axis.copy()
|
434 | 1 | tkerber | self.dx_change = [0, 0] |
435 | 1 | tkerber | self.atoms_to_rotate = self.atoms_to_rotate_0.copy() |
436 | 1 | tkerber | self.atoms_selected = sel.copy()
|
437 | 1 | tkerber | self.rot_vec = dir_vec
|
438 | 1 | tkerber | |
439 | 1 | tkerber | if nsel != 2 or sum(self.atoms_to_rotate) == 2: |
440 | 1 | tkerber | self.dx_change = [0, 0] |
441 | 1 | tkerber | |
442 | 1 | tkerber | for i in range(len(sel)): |
443 | 1 | tkerber | if sel[i] != self.atoms_selected[i]: |
444 | 1 | tkerber | change = True
|
445 | 1 | tkerber | cz = [dx, dy+dz] |
446 | 1 | tkerber | |
447 | 1 | tkerber | if cz[0] or cz[1]: |
448 | 1 | tkerber | change = False
|
449 | 1 | tkerber | if not(cz[0] * (self.dx_change[1])): |
450 | 1 | tkerber | change = True
|
451 | 1 | tkerber | for i in range(2): |
452 | 1 | tkerber | if cz[i] and self.dx_change[i]: |
453 | 1 | tkerber | self.rot_vec = self.rot_vec * cz[i] * self.dx_change[i] |
454 | 1 | tkerber | if cz[1]: |
455 | 1 | tkerber | change = False
|
456 | 1 | tkerber | |
457 | 1 | tkerber | if np.prod(self.z_axis_old != z_axis): |
458 | 1 | tkerber | change = True
|
459 | 1 | tkerber | self.z_axis_old = z_axis.copy()
|
460 | 1 | tkerber | self.dx_change = copy(cz)
|
461 | 1 | tkerber | dihedral_rotation = len(self.images.selected_ordered) == 4 |
462 | 1 | tkerber | |
463 | 1 | tkerber | if change:
|
464 | 1 | tkerber | self.atoms_selected = sel.copy()
|
465 | 1 | tkerber | |
466 | 1 | tkerber | if nsel == 2 and sum(self.atoms_to_rotate) != 2: |
467 | 1 | tkerber | asel = [] |
468 | 1 | tkerber | for i, j in enumerate(sel): |
469 | 1 | tkerber | if j:
|
470 | 1 | tkerber | asel.append(i) |
471 | 1 | tkerber | a1, a2 = asel |
472 | 1 | tkerber | |
473 | 1 | tkerber | rvx = self.images.P[self.frame][a1] - \ |
474 | 1 | tkerber | self.images.P[self.frame][a2] |
475 | 1 | tkerber | |
476 | 1 | tkerber | rvy = np.cross(rvx, |
477 | 1 | tkerber | np.dot(self.axes,
|
478 | 1 | tkerber | np.array([0, 0, 1]))) |
479 | 1 | tkerber | self.rot_vec = rvx * dx + rvy * (dy + dz)
|
480 | 1 | tkerber | self.dx_change = [dx, dy+dz]
|
481 | 1 | tkerber | |
482 | 1 | tkerber | # dihedral rotation?
|
483 | 1 | tkerber | if dihedral_rotation:
|
484 | 1 | tkerber | sel = self.images.selected_ordered
|
485 | 1 | tkerber | self.rot_vec = (dx+dy+dz)*(self.R[sel[2]]-self.R[sel[1]]) |
486 | 1 | tkerber | |
487 | 1 | tkerber | rot_cen = np.array([0.0, 0.0, 0.0]) |
488 | 1 | tkerber | if dihedral_rotation:
|
489 | 1 | tkerber | sel = self.images.selected_ordered
|
490 | 1 | tkerber | rot_cen = self.R[sel[1]].copy() |
491 | 1 | tkerber | elif nsel:
|
492 | 1 | tkerber | for i, b in enumerate( sel): |
493 | 1 | tkerber | if b:
|
494 | 1 | tkerber | rot_cen += self.R[i]
|
495 | 1 | tkerber | rot_cen /= float(nsel)
|
496 | 1 | tkerber | |
497 | 1 | tkerber | degrees = 5 * (1 - SHIFT) + SHIFT |
498 | 1 | tkerber | degrees = abs(sum(dxdydz)) * 3.1415 / 360.0 * degrees |
499 | 1 | tkerber | rotmat = rotate_about_vec(self.rot_vec, degrees)
|
500 | 1 | tkerber | |
501 | 1 | tkerber | # now rotate the atoms that are to be rotated
|
502 | 1 | tkerber | for i in range(len(self.R)): |
503 | 1 | tkerber | if self.atoms_to_rotate[i]: |
504 | 1 | tkerber | self.R[i] -= rot_cen
|
505 | 1 | tkerber | for jx in range(self.images.nimages): |
506 | 1 | tkerber | self.images.P[jx][i] -= rot_cen
|
507 | 1 | tkerber | |
508 | 1 | tkerber | self.R[i] = rotate_vec(rotmat, self.R[i]) |
509 | 1 | tkerber | for jx in range(self.images.nimages): |
510 | 1 | tkerber | self.images.P[jx][i] = rotate_vec(rotmat, self.images.P[jx][i]) |
511 | 1 | tkerber | |
512 | 1 | tkerber | self.R[i] += rot_cen
|
513 | 1 | tkerber | for jx in range(self.images.nimages): |
514 | 1 | tkerber | self.images.P[jx][i] += rot_cen
|
515 | 1 | tkerber | elif atom_orient:
|
516 | 1 | tkerber | to_vec = np.array([dx, dy, dz]) |
517 | 1 | tkerber | |
518 | 1 | tkerber | from rot_tools import rotate_vec_into_newvec |
519 | 1 | tkerber | rot_mat = rotate_vec_into_newvec(self.orient_normal, to_vec)
|
520 | 1 | tkerber | self.axes = rot_mat
|
521 | 1 | tkerber | |
522 | 1 | tkerber | self.set_coordinates()
|
523 | 1 | tkerber | else:
|
524 | 1 | tkerber | self.center -= (dx * 0.1 * self.axes[:, 0] - |
525 | 1 | tkerber | dy * 0.1 * self.axes[:, 1]) |
526 | 1 | tkerber | self.draw()
|
527 | 1 | tkerber | |
528 | 1 | tkerber | |
529 | 1 | tkerber | def add_atoms(self, widget, data=None): |
530 | 1 | tkerber | """
|
531 | 1 | tkerber | Presents a dialogbox to the user, that allows him to add atoms/molecule to the current slab.
|
532 | 1 | tkerber |
|
533 | 1 | tkerber | The molecule/atom is rotated using the current rotation of the coordinate system.
|
534 | 1 | tkerber |
|
535 | 1 | tkerber | The molecule/atom can be added at a specified position - if the keyword auto+Z is used,
|
536 | 1 | tkerber | the COM of the selected atoms will be used as COM for the moleculed. The COM is furthermore
|
537 | 1 | tkerber | translated Z ang towards the user.
|
538 | 1 | tkerber |
|
539 | 1 | tkerber | If no molecules are selected, the COM of all the atoms will be used for the x-y components of the
|
540 | 1 | tkerber | active coordinate system, while the z-direction will be chosen from the nearest atom position
|
541 | 1 | tkerber | along this direction.
|
542 | 1 | tkerber |
|
543 | 1 | tkerber | Note: If this option is used, all frames except the active one are deleted.
|
544 | 1 | tkerber | """
|
545 | 1 | tkerber | if data:
|
546 | 1 | tkerber | if data == 'load': |
547 | 1 | tkerber | chooser = gtk.FileChooserDialog( |
548 | 1 | tkerber | _('Open ...'), None, gtk.FILE_CHOOSER_ACTION_OPEN, |
549 | 1 | tkerber | (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, |
550 | 1 | tkerber | gtk.STOCK_OPEN, gtk.RESPONSE_OK)) |
551 | 1 | tkerber | ok = chooser.run() |
552 | 1 | tkerber | if ok == gtk.RESPONSE_OK:
|
553 | 1 | tkerber | filename = chooser.get_filename() |
554 | 1 | tkerber | chooser.destroy() |
555 | 1 | tkerber | if not ok: |
556 | 1 | tkerber | return
|
557 | 1 | tkerber | |
558 | 1 | tkerber | if data == 'OK' or data == 'load': |
559 | 1 | tkerber | import ase |
560 | 1 | tkerber | if data == 'load': |
561 | 1 | tkerber | molecule = filename |
562 | 1 | tkerber | else:
|
563 | 1 | tkerber | molecule = self.add_entries[1].get_text() |
564 | 1 | tkerber | tag = self.add_entries[2].get_text() |
565 | 1 | tkerber | mom = self.add_entries[3].get_text() |
566 | 1 | tkerber | pos = self.add_entries[4].get_text().lower() |
567 | 1 | tkerber | |
568 | 1 | tkerber | a = None
|
569 | 1 | tkerber | try:
|
570 | 1 | tkerber | a = ase.Atoms([ase.Atom(molecule)]) |
571 | 1 | tkerber | except:
|
572 | 1 | tkerber | try:
|
573 | 1 | tkerber | a = ase.molecule(molecule) |
574 | 1 | tkerber | except:
|
575 | 1 | tkerber | try:
|
576 | 1 | tkerber | a = ase.read(molecule, -1)
|
577 | 1 | tkerber | except:
|
578 | 1 | tkerber | self.add_entries[1].set_text('?' + molecule) |
579 | 1 | tkerber | return ()
|
580 | 1 | tkerber | |
581 | 1 | tkerber | directions = np.transpose(self.axes)
|
582 | 1 | tkerber | if a != None: |
583 | 1 | tkerber | for i in a: |
584 | 1 | tkerber | try:
|
585 | 1 | tkerber | i.set_tag(int(tag))
|
586 | 1 | tkerber | except:
|
587 | 1 | tkerber | self.add_entries[2].set_text('?' + tag) |
588 | 1 | tkerber | return ()
|
589 | 1 | tkerber | try:
|
590 | 1 | tkerber | i.magmom = float(mom)
|
591 | 1 | tkerber | except:
|
592 | 1 | tkerber | self.add_entries[3].set_text('?' + mom) |
593 | 1 | tkerber | return ()
|
594 | 1 | tkerber | # apply the current rotation matrix to A
|
595 | 1 | tkerber | for i in a: |
596 | 1 | tkerber | i.position = np.dot(self.axes, i.position)
|
597 | 1 | tkerber | # find the extent of the molecule in the local coordinate system
|
598 | 1 | tkerber | a_cen_pos = np.array([0.0, 0.0, 0.0]) |
599 | 1 | tkerber | m_cen_pos = 0.0
|
600 | 1 | tkerber | for i in a.positions: |
601 | 1 | tkerber | a_cen_pos[0] += np.dot(directions[0], i) |
602 | 1 | tkerber | a_cen_pos[1] += np.dot(directions[1], i) |
603 | 1 | tkerber | a_cen_pos[2] += np.dot(directions[2], i) |
604 | 1 | tkerber | |
605 | 1 | tkerber | m_cen_pos = max(np.dot(-directions[2], i), m_cen_pos) |
606 | 1 | tkerber | a_cen_pos[0] /= len(a.positions) |
607 | 1 | tkerber | a_cen_pos[1] /= len(a.positions) |
608 | 1 | tkerber | a_cen_pos[2] /= len(a.positions) |
609 | 1 | tkerber | a_cen_pos[2] -= m_cen_pos
|
610 | 1 | tkerber | |
611 | 1 | tkerber | # now find the position
|
612 | 1 | tkerber | cen_pos = np.array([0.0, 0.0, 0.0]) |
613 | 1 | tkerber | if sum(self.images.selected) > 0: |
614 | 1 | tkerber | for i in range(len(self.R)): |
615 | 1 | tkerber | if self.images.selected[i]: |
616 | 1 | tkerber | cen_pos += self.R[i]
|
617 | 1 | tkerber | cen_pos /= sum(self.images.selected) |
618 | 1 | tkerber | elif len(self.R) > 0: |
619 | 1 | tkerber | px = 0.0
|
620 | 1 | tkerber | py = 0.0
|
621 | 1 | tkerber | pz = -1e6
|
622 | 1 | tkerber | |
623 | 1 | tkerber | for i in range(len(self.R)): |
624 | 1 | tkerber | px += np.dot(directions[0], self.R[i]) |
625 | 1 | tkerber | py += np.dot(directions[1], self.R[i]) |
626 | 1 | tkerber | pz = max(np.dot(directions[2], self.R[i]), pz) |
627 | 1 | tkerber | px = (px/float(len(self.R))) |
628 | 1 | tkerber | py = (py/float(len(self.R))) |
629 | 1 | tkerber | cen_pos = directions[0] * px + \
|
630 | 1 | tkerber | directions[1] * py + \
|
631 | 1 | tkerber | directions[2] * pz
|
632 | 1 | tkerber | |
633 | 1 | tkerber | if 'auto' in pos: |
634 | 1 | tkerber | pos = pos.replace('auto', '') |
635 | 1 | tkerber | import re |
636 | 1 | tkerber | pos = re.sub('\s', '', pos) |
637 | 1 | tkerber | if '(' in pos: |
638 | 1 | tkerber | sign = eval('%s1' % pos[0]) |
639 | 1 | tkerber | a_cen_pos -= sign * np.array(eval(pos[1:]), float) |
640 | 1 | tkerber | else:
|
641 | 1 | tkerber | a_cen_pos -= float(pos) * directions[2] |
642 | 1 | tkerber | else:
|
643 | 1 | tkerber | cen_pos = np.array(eval(pos))
|
644 | 1 | tkerber | for i in a: |
645 | 1 | tkerber | i.position += cen_pos - a_cen_pos |
646 | 1 | tkerber | |
647 | 1 | tkerber | # and them to the molecule
|
648 | 1 | tkerber | atoms = self.images.get_atoms(self.frame) |
649 | 1 | tkerber | atoms = atoms + a |
650 | 1 | tkerber | self.new_atoms(atoms, init_magmom=True) |
651 | 1 | tkerber | |
652 | 1 | tkerber | # and finally select the new molecule for easy moving and rotation
|
653 | 1 | tkerber | for i in range(len(a)): |
654 | 1 | tkerber | self.images.selected[len(atoms) - i - 1] = True |
655 | 1 | tkerber | |
656 | 1 | tkerber | self.draw()
|
657 | 1 | tkerber | self.add_entries[0].destroy() |
658 | 1 | tkerber | if data == None: |
659 | 1 | tkerber | molecule = ''
|
660 | 1 | tkerber | tag = '0'
|
661 | 1 | tkerber | mom = '0'
|
662 | 1 | tkerber | pos = 'auto+1'
|
663 | 1 | tkerber | self.add_entries = []
|
664 | 1 | tkerber | window = gtk.Window(gtk.WINDOW_TOPLEVEL) |
665 | 1 | tkerber | self.add_entries.append(window)
|
666 | 1 | tkerber | window.set_title('Add atoms')
|
667 | 1 | tkerber | |
668 | 1 | tkerber | vbox = gtk.VBox(False, 0) |
669 | 1 | tkerber | window.add(vbox) |
670 | 1 | tkerber | vbox.show() |
671 | 1 | tkerber | pack = False
|
672 | 1 | tkerber | for i, j in [['Insert atom or molecule', molecule], |
673 | 1 | tkerber | ['Tag', tag],
|
674 | 1 | tkerber | ['Moment', mom],
|
675 | 1 | tkerber | ['Position', pos]]:
|
676 | 1 | tkerber | |
677 | 1 | tkerber | label = gtk.Label(i) |
678 | 1 | tkerber | if not pack: |
679 | 1 | tkerber | vbox.pack_start(label, True, True, 0) |
680 | 1 | tkerber | else:
|
681 | 1 | tkerber | pack = True
|
682 | 1 | tkerber | vbox.add(label) |
683 | 1 | tkerber | label.show() |
684 | 1 | tkerber | |
685 | 1 | tkerber | entry = gtk.Entry() |
686 | 1 | tkerber | entry.set_text(j) |
687 | 1 | tkerber | self.add_entries.append(entry)
|
688 | 1 | tkerber | entry.set_max_length(50)
|
689 | 1 | tkerber | entry.show() |
690 | 1 | tkerber | |
691 | 1 | tkerber | vbox.add(entry) |
692 | 1 | tkerber | |
693 | 1 | tkerber | button = gtk.Button('_Load molecule')
|
694 | 1 | tkerber | button.connect('clicked', self.add_atoms, 'load') |
695 | 1 | tkerber | button.show() |
696 | 1 | tkerber | vbox.add(button) |
697 | 1 | tkerber | button = gtk.Button('_OK')
|
698 | 1 | tkerber | button.connect('clicked', self.add_atoms, 'OK') |
699 | 1 | tkerber | button.show() |
700 | 1 | tkerber | vbox.add(button) |
701 | 1 | tkerber | button = gtk.Button('_Cancel')
|
702 | 1 | tkerber | button.connect('clicked', self.add_atoms, 'Cancel') |
703 | 1 | tkerber | button.show() |
704 | 1 | tkerber | vbox.add(button) |
705 | 1 | tkerber | |
706 | 1 | tkerber | window.show() |
707 | 1 | tkerber | |
708 | 1 | tkerber | def modify_atoms(self, widget, data=None): |
709 | 1 | tkerber | """
|
710 | 1 | tkerber | Presents a dialog box where the user is able to change the atomic type, the magnetic
|
711 | 1 | tkerber | moment and tags of the selected atoms. An item marked with X will not be changed.
|
712 | 1 | tkerber | """
|
713 | 1 | tkerber | if data:
|
714 | 1 | tkerber | if data == 'OK': |
715 | 1 | tkerber | import ase |
716 | 1 | tkerber | symbol = self.add_entries[1].get_text() |
717 | 1 | tkerber | tag = self.add_entries[2].get_text() |
718 | 1 | tkerber | mom = self.add_entries[3].get_text() |
719 | 1 | tkerber | a = None
|
720 | 1 | tkerber | if symbol != 'X': |
721 | 1 | tkerber | try:
|
722 | 1 | tkerber | a = ase.Atoms([ase.Atom(symbol)]) |
723 | 1 | tkerber | except:
|
724 | 1 | tkerber | self.add_entries[1].set_text('?' + symbol) |
725 | 1 | tkerber | return ()
|
726 | 1 | tkerber | |
727 | 1 | tkerber | y = self.images.selected.copy()
|
728 | 1 | tkerber | # and them to the molecule
|
729 | 1 | tkerber | atoms = self.images.get_atoms(self.frame) |
730 | 1 | tkerber | for i in range(len(atoms)): |
731 | 1 | tkerber | if self.images.selected[i]: |
732 | 1 | tkerber | if a:
|
733 | 1 | tkerber | atoms[i].symbol = symbol |
734 | 1 | tkerber | try:
|
735 | 1 | tkerber | if tag != 'X': |
736 | 1 | tkerber | atoms[i].tag = int(tag)
|
737 | 1 | tkerber | except:
|
738 | 1 | tkerber | self.add_entries[2].set_text('?' + tag) |
739 | 1 | tkerber | return ()
|
740 | 1 | tkerber | try:
|
741 | 1 | tkerber | if mom != 'X': |
742 | 1 | tkerber | atoms[i].magmom = float(mom)
|
743 | 1 | tkerber | except:
|
744 | 1 | tkerber | self.add_entries[3].set_text('?' + mom) |
745 | 1 | tkerber | return ()
|
746 | 1 | tkerber | self.new_atoms(atoms, init_magmom=True) |
747 | 1 | tkerber | |
748 | 1 | tkerber | # and finally select the new molecule for easy moving and rotation
|
749 | 1 | tkerber | self.images.selected = y
|
750 | 1 | tkerber | self.draw()
|
751 | 1 | tkerber | |
752 | 1 | tkerber | self.add_entries[0].destroy() |
753 | 1 | tkerber | if data == None and sum(self.images.selected): |
754 | 1 | tkerber | atoms = self.images.get_atoms(self.frame) |
755 | 1 | tkerber | s_tag = ''
|
756 | 1 | tkerber | s_mom = ''
|
757 | 1 | tkerber | s_symbol = ''
|
758 | 1 | tkerber | # Get the tags, moments and symbols of the selected atomsa
|
759 | 1 | tkerber | for i in range(len(atoms)): |
760 | 1 | tkerber | if self.images.selected[i]: |
761 | 1 | tkerber | if not(s_tag): |
762 | 1 | tkerber | s_tag = str(atoms[i].tag)
|
763 | 1 | tkerber | elif s_tag != str(atoms[i].tag): |
764 | 1 | tkerber | s_tag = 'X'
|
765 | 1 | tkerber | if not(s_mom): |
766 | 1 | tkerber | s_mom = ("%2.2f" % (atoms[i].magmom))
|
767 | 1 | tkerber | elif s_mom != ("%2.2f" % (atoms[i].magmom)): |
768 | 1 | tkerber | s_mom = 'X'
|
769 | 1 | tkerber | if not(s_symbol): |
770 | 1 | tkerber | s_symbol = str(atoms[i].symbol)
|
771 | 1 | tkerber | elif s_symbol != str(atoms[i].symbol): |
772 | 1 | tkerber | s_symbol = 'X'
|
773 | 1 | tkerber | |
774 | 1 | tkerber | self.add_entries = []
|
775 | 1 | tkerber | window = gtk.Window(gtk.WINDOW_TOPLEVEL) |
776 | 1 | tkerber | self.add_entries.append(window)
|
777 | 1 | tkerber | window.set_title('Modify')
|
778 | 1 | tkerber | |
779 | 1 | tkerber | vbox = gtk.VBox(False, 0) |
780 | 1 | tkerber | window.add(vbox) |
781 | 1 | tkerber | vbox.show() |
782 | 1 | tkerber | pack = False
|
783 | 1 | tkerber | for i, j in [['Atom', s_symbol], |
784 | 1 | tkerber | ['Tag', s_tag],
|
785 | 1 | tkerber | ['Moment', s_mom]]:
|
786 | 1 | tkerber | label = gtk.Label(i) |
787 | 1 | tkerber | if not pack: |
788 | 1 | tkerber | vbox.pack_start(label, True, True, 0) |
789 | 1 | tkerber | else:
|
790 | 1 | tkerber | pack = True
|
791 | 1 | tkerber | vbox.add(label) |
792 | 1 | tkerber | label.show() |
793 | 1 | tkerber | |
794 | 1 | tkerber | entry = gtk.Entry() |
795 | 1 | tkerber | entry.set_text(j) |
796 | 1 | tkerber | self.add_entries.append(entry)
|
797 | 1 | tkerber | entry.set_max_length(50)
|
798 | 1 | tkerber | entry.show() |
799 | 1 | tkerber | vbox.add(entry) |
800 | 1 | tkerber | button = gtk.Button('_OK')
|
801 | 1 | tkerber | button.connect('clicked', self.modify_atoms, 'OK') |
802 | 1 | tkerber | button.show() |
803 | 1 | tkerber | vbox.add(button) |
804 | 1 | tkerber | button = gtk.Button('_Cancel')
|
805 | 1 | tkerber | button.connect('clicked', self.modify_atoms, 'Cancel') |
806 | 1 | tkerber | button.show() |
807 | 1 | tkerber | vbox.add(button) |
808 | 1 | tkerber | |
809 | 1 | tkerber | window.show() |
810 | 1 | tkerber | |
811 | 1 | tkerber | def delete_selected_atoms(self, widget, data=None): |
812 | 1 | tkerber | if data == 'OK': |
813 | 1 | tkerber | atoms = self.images.get_atoms(self.frame) |
814 | 1 | tkerber | lena = len(atoms)
|
815 | 1 | tkerber | for i in range(len(atoms)): |
816 | 1 | tkerber | li = lena-1-i
|
817 | 1 | tkerber | if self.images.selected[li]: |
818 | 1 | tkerber | del(atoms[li])
|
819 | 1 | tkerber | self.new_atoms(atoms)
|
820 | 1 | tkerber | |
821 | 1 | tkerber | self.draw()
|
822 | 1 | tkerber | if data:
|
823 | 1 | tkerber | self.window.destroy()
|
824 | 1 | tkerber | |
825 | 1 | tkerber | if not(data) and sum(self.images.selected): |
826 | 1 | tkerber | more = '' + (sum(self.images.selected) > 1) * 's' |
827 | 1 | tkerber | self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
828 | 1 | tkerber | self.window.set_title('Confirmation') |
829 | 1 | tkerber | self.window.set_border_width(10) |
830 | 1 | tkerber | self.box1 = gtk.HBox(False, 0) |
831 | 1 | tkerber | self.window.add(self.box1) |
832 | 1 | tkerber | self.button1 = gtk.Button('Delete selected atom%s?' % more) |
833 | 1 | tkerber | self.button1.connect("clicked", self.delete_selected_atoms, "OK") |
834 | 1 | tkerber | self.box1.pack_start(self.button1, True, True, 0) |
835 | 1 | tkerber | self.button1.show()
|
836 | 1 | tkerber | |
837 | 1 | tkerber | self.button2 = gtk.Button("Cancel") |
838 | 1 | tkerber | self.button2.connect("clicked", self.delete_selected_atoms, "Cancel") |
839 | 1 | tkerber | self.box1.pack_start(self.button2, True, True, 0) |
840 | 1 | tkerber | self.button2.show()
|
841 | 1 | tkerber | |
842 | 1 | tkerber | self.box1.show()
|
843 | 1 | tkerber | self.window.show()
|
844 | 1 | tkerber | |
845 | 1 | tkerber | def debug(self, x): |
846 | 1 | tkerber | from ase.gui.debug import Debug |
847 | 1 | tkerber | Debug(self)
|
848 | 1 | tkerber | |
849 | 1 | tkerber | def execute(self, widget=None): |
850 | 1 | tkerber | from ase.gui.execute import Execute |
851 | 1 | tkerber | Execute(self)
|
852 | 1 | tkerber | |
853 | 1 | tkerber | def constraints_window(self, widget=None): |
854 | 1 | tkerber | from ase.gui.constraints import Constraints |
855 | 1 | tkerber | Constraints(self)
|
856 | 1 | tkerber | |
857 | 1 | tkerber | def dft_window(self, widget=None): |
858 | 1 | tkerber | from ase.gui.dft import DFT |
859 | 1 | tkerber | DFT(self)
|
860 | 1 | tkerber | |
861 | 1 | tkerber | def select_all(self, widget): |
862 | 1 | tkerber | self.images.selected[:] = True |
863 | 1 | tkerber | self.draw()
|
864 | 1 | tkerber | |
865 | 1 | tkerber | def invert_selection(self, widget): |
866 | 1 | tkerber | self.images.selected[:] = ~self.images.selected |
867 | 1 | tkerber | self.draw()
|
868 | 1 | tkerber | |
869 | 1 | tkerber | def select_constrained_atoms(self, widget): |
870 | 1 | tkerber | self.images.selected[:] = ~self.images.dynamic |
871 | 1 | tkerber | self.draw()
|
872 | 1 | tkerber | |
873 | 1 | tkerber | def movie(self, widget=None): |
874 | 1 | tkerber | from ase.gui.movie import Movie |
875 | 1 | tkerber | self.movie_window = Movie(self) |
876 | 1 | tkerber | |
877 | 1 | tkerber | def plot_graphs(self, x=None, expr=None): |
878 | 1 | tkerber | from ase.gui.graphs import Graphs |
879 | 1 | tkerber | g = Graphs(self)
|
880 | 1 | tkerber | if expr is not None: |
881 | 1 | tkerber | g.plot(expr=expr) |
882 | 1 | tkerber | self.graph_wref.append(weakref.ref(g))
|
883 | 1 | tkerber | |
884 | 1 | tkerber | def plot_graphs_newatoms(self): |
885 | 1 | tkerber | "Notify any Graph objects that they should make new plots."
|
886 | 1 | tkerber | new_wref = [] |
887 | 1 | tkerber | found = 0
|
888 | 1 | tkerber | for wref in self.graph_wref: |
889 | 1 | tkerber | ref = wref() |
890 | 1 | tkerber | if ref is not None: |
891 | 1 | tkerber | ref.plot() |
892 | 1 | tkerber | new_wref.append(wref) # Preserve weakrefs that still work.
|
893 | 1 | tkerber | found += 1
|
894 | 1 | tkerber | self.graph_wref = new_wref
|
895 | 1 | tkerber | return found
|
896 | 1 | tkerber | |
897 | 1 | tkerber | def NEB(self, action): |
898 | 1 | tkerber | from ase.gui.neb import NudgedElasticBand |
899 | 1 | tkerber | NudgedElasticBand(self.images)
|
900 | 1 | tkerber | |
901 | 1 | tkerber | def bulk_modulus(self, action): |
902 | 1 | tkerber | from ase.gui.bulk_modulus import BulkModulus |
903 | 1 | tkerber | BulkModulus(self.images)
|
904 | 1 | tkerber | |
905 | 1 | tkerber | def open(self, button=None, filenames=None): |
906 | 1 | tkerber | if filenames == None: |
907 | 1 | tkerber | chooser = gtk.FileChooserDialog( |
908 | 1 | tkerber | _('Open ...'), None, gtk.FILE_CHOOSER_ACTION_OPEN, |
909 | 1 | tkerber | (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, |
910 | 1 | tkerber | gtk.STOCK_OPEN, gtk.RESPONSE_OK)) |
911 | 1 | tkerber | ok = chooser.run() == gtk.RESPONSE_OK |
912 | 1 | tkerber | if ok:
|
913 | 1 | tkerber | filenames = [chooser.get_filename()] |
914 | 1 | tkerber | chooser.destroy() |
915 | 1 | tkerber | |
916 | 1 | tkerber | if not ok: |
917 | 1 | tkerber | return
|
918 | 1 | tkerber | |
919 | 1 | tkerber | self.reset_tools_modes()
|
920 | 1 | tkerber | self.images.read(filenames, slice(None)) |
921 | 1 | tkerber | self.set_colors()
|
922 | 1 | tkerber | self.set_coordinates(self.images.nimages - 1, focus=True) |
923 | 1 | tkerber | |
924 | 1 | tkerber | def import_atoms (self, button=None, filenames=None): |
925 | 1 | tkerber | if filenames == None: |
926 | 1 | tkerber | chooser = gtk.FileChooserDialog( |
927 | 1 | tkerber | _('Open ...'), None, gtk.FILE_CHOOSER_ACTION_OPEN, |
928 | 1 | tkerber | (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, |
929 | 1 | tkerber | gtk.STOCK_OPEN, gtk.RESPONSE_OK)) |
930 | 1 | tkerber | ok = chooser.run() |
931 | 1 | tkerber | if ok == gtk.RESPONSE_OK:
|
932 | 1 | tkerber | filenames = [chooser.get_filename()] |
933 | 1 | tkerber | chooser.destroy() |
934 | 1 | tkerber | |
935 | 1 | tkerber | if not ok: |
936 | 1 | tkerber | return
|
937 | 1 | tkerber | |
938 | 1 | tkerber | |
939 | 1 | tkerber | self.images.import_atoms(filenames, self.frame) |
940 | 1 | tkerber | self.set_colors()
|
941 | 1 | tkerber | self.set_coordinates(self.images.nimages - 1, focus=True) |
942 | 1 | tkerber | |
943 | 1 | tkerber | def save(self, action): |
944 | 1 | tkerber | chooser = gtk.FileChooserDialog( |
945 | 1 | tkerber | _('Save ...'), None, gtk.FILE_CHOOSER_ACTION_SAVE, |
946 | 1 | tkerber | (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, |
947 | 1 | tkerber | gtk.STOCK_SAVE, gtk.RESPONSE_OK)) |
948 | 1 | tkerber | |
949 | 1 | tkerber | # Add a file type filter
|
950 | 1 | tkerber | types = [] |
951 | 1 | tkerber | name_to_suffix = {} |
952 | 1 | tkerber | for name, suffix in [('Automatic', None), |
953 | 1 | tkerber | ('XYZ file', 'xyz'), |
954 | 1 | tkerber | ('ASE trajectory', 'traj'), |
955 | 1 | tkerber | ('PDB file', 'pdb'), |
956 | 1 | tkerber | ('Gaussian cube file', 'cube'), |
957 | 1 | tkerber | ('Python script', 'py'), |
958 | 1 | tkerber | ('VNL file', 'vnl'), |
959 | 1 | tkerber | ('Portable Network Graphics', 'png'), |
960 | 1 | tkerber | ('Persistance of Vision', 'pov'), |
961 | 1 | tkerber | ('Encapsulated PostScript', 'eps'), |
962 | 1 | tkerber | ('FHI-aims geometry input', 'in'), |
963 | 1 | tkerber | ('VASP geometry input', 'POSCAR')]: |
964 | 1 | tkerber | if suffix is None: |
965 | 1 | tkerber | name = _(name) |
966 | 1 | tkerber | else:
|
967 | 1 | tkerber | name = '%s (%s)' % (_(name), suffix)
|
968 | 1 | tkerber | filt = gtk.FileFilter() |
969 | 1 | tkerber | filt.set_name(name) |
970 | 1 | tkerber | if suffix is None: |
971 | 1 | tkerber | filt.add_pattern('*')
|
972 | 1 | tkerber | elif suffix == 'POSCAR': |
973 | 1 | tkerber | filt.add_pattern('*POSCAR*')
|
974 | 1 | tkerber | else:
|
975 | 1 | tkerber | filt.add_pattern('*.'+suffix)
|
976 | 1 | tkerber | if suffix is not None: |
977 | 1 | tkerber | types.append(suffix) |
978 | 1 | tkerber | name_to_suffix[name] = suffix |
979 | 1 | tkerber | |
980 | 1 | tkerber | chooser.add_filter(filt) |
981 | 1 | tkerber | |
982 | 1 | tkerber | if self.images.nimages > 1: |
983 | 1 | tkerber | img_vbox = gtk.VBox() |
984 | 1 | tkerber | button = gtk.CheckButton('Save current image only (#%d)' %
|
985 | 1 | tkerber | self.frame)
|
986 | 1 | tkerber | pack(img_vbox, button) |
987 | 1 | tkerber | entry = gtk.Entry(10)
|
988 | 1 | tkerber | pack(img_vbox, [gtk.Label(_('Slice: ')), entry,
|
989 | 1 | tkerber | help('Help for slice ...')])
|
990 | 1 | tkerber | entry.set_text('0:%d' % self.images.nimages) |
991 | 1 | tkerber | img_vbox.show() |
992 | 1 | tkerber | chooser.set_extra_widget(img_vbox) |
993 | 1 | tkerber | |
994 | 1 | tkerber | while True: |
995 | 1 | tkerber | # Loop until the user selects a proper file name, or cancels.
|
996 | 1 | tkerber | response = chooser.run() |
997 | 1 | tkerber | if response == gtk.RESPONSE_CANCEL:
|
998 | 1 | tkerber | chooser.destroy() |
999 | 1 | tkerber | return
|
1000 | 1 | tkerber | elif response != gtk.RESPONSE_OK:
|
1001 | 1 | tkerber | print >>sys.stderr, "AG INTERNAL ERROR: strange response in Save,", response |
1002 | 1 | tkerber | chooser.destroy() |
1003 | 1 | tkerber | return
|
1004 | 1 | tkerber | |
1005 | 1 | tkerber | filename = chooser.get_filename() |
1006 | 1 | tkerber | |
1007 | 1 | tkerber | suffix = os.path.splitext(filename)[1][1:] |
1008 | 1 | tkerber | if 'POSCAR' in filename: |
1009 | 1 | tkerber | suffix = 'POSCAR'
|
1010 | 1 | tkerber | if suffix == '': |
1011 | 1 | tkerber | # No suffix given. If the user has chosen a special
|
1012 | 1 | tkerber | # file type, use the corresponding suffix.
|
1013 | 1 | tkerber | filt = chooser.get_filter().get_name() |
1014 | 1 | tkerber | suffix = name_to_suffix[filt] |
1015 | 1 | tkerber | filename = filename + '.' + suffix
|
1016 | 1 | tkerber | |
1017 | 1 | tkerber | if suffix not in types: |
1018 | 1 | tkerber | oops(message='Unknown output format!',
|
1019 | 1 | tkerber | message2='Use one of: ' + ', '.join(types[1:])) |
1020 | 1 | tkerber | continue
|
1021 | 1 | tkerber | |
1022 | 1 | tkerber | if self.images.nimages > 1: |
1023 | 1 | tkerber | if button.get_active():
|
1024 | 1 | tkerber | filename += '@%d' % self.frame |
1025 | 1 | tkerber | else:
|
1026 | 1 | tkerber | filename += '@' + entry.get_text()
|
1027 | 1 | tkerber | |
1028 | 1 | tkerber | break
|
1029 | 1 | tkerber | |
1030 | 1 | tkerber | chooser.destroy() |
1031 | 1 | tkerber | |
1032 | 1 | tkerber | bbox = np.empty(4)
|
1033 | 1 | tkerber | size = np.array([self.width, self.height]) / self.scale |
1034 | 1 | tkerber | bbox[0:2] = np.dot(self.center, self.axes[:, :2]) - size / 2 |
1035 | 1 | tkerber | bbox[2:] = bbox[:2] + size |
1036 | 1 | tkerber | suc = self.ui.get_widget('/MenuBar/ViewMenu/ShowUnitCell').get_active() |
1037 | 1 | tkerber | self.images.write(filename, self.axes, show_unit_cell=suc, bbox=bbox) |
1038 | 1 | tkerber | |
1039 | 1 | tkerber | def bulk_window(self, menuitem): |
1040 | 1 | tkerber | SetupBulkCrystal(self)
|
1041 | 1 | tkerber | |
1042 | 1 | tkerber | def surface_window(self, menuitem): |
1043 | 1 | tkerber | SetupSurfaceSlab(self)
|
1044 | 1 | tkerber | |
1045 | 1 | tkerber | def nanoparticle_window(self, menuitem): |
1046 | 1 | tkerber | SetupNanoparticle(self)
|
1047 | 1 | tkerber | |
1048 | 1 | tkerber | def graphene_window(self, menuitem): |
1049 | 1 | tkerber | SetupGraphene(self)
|
1050 | 1 | tkerber | |
1051 | 1 | tkerber | def nanotube_window(self, menuitem): |
1052 | 1 | tkerber | SetupNanotube(self)
|
1053 | 1 | tkerber | |
1054 | 1 | tkerber | def calculator_window(self, menuitem): |
1055 | 1 | tkerber | SetCalculator(self)
|
1056 | 1 | tkerber | |
1057 | 1 | tkerber | def energy_window(self, menuitem): |
1058 | 1 | tkerber | EnergyForces(self)
|
1059 | 1 | tkerber | |
1060 | 1 | tkerber | def energy_minimize_window(self, menuitem): |
1061 | 1 | tkerber | Minimize(self)
|
1062 | 1 | tkerber | |
1063 | 1 | tkerber | def scaling_window(self, menuitem): |
1064 | 1 | tkerber | HomogeneousDeformation(self)
|
1065 | 1 | tkerber | |
1066 | 1 | tkerber | def new_atoms(self, atoms, init_magmom=False): |
1067 | 1 | tkerber | "Set a new atoms object."
|
1068 | 1 | tkerber | self.notify_vulnerable()
|
1069 | 1 | tkerber | self.reset_tools_modes()
|
1070 | 1 | tkerber | |
1071 | 1 | tkerber | rpt = getattr(self.images, 'repeat', None) |
1072 | 1 | tkerber | self.images.repeat_images(np.ones(3, int)) |
1073 | 1 | tkerber | self.images.initialize([atoms], init_magmom=init_magmom)
|
1074 | 1 | tkerber | self.frame = 0 # Prevent crashes |
1075 | 1 | tkerber | self.images.repeat_images(rpt)
|
1076 | 1 | tkerber | self.set_colors()
|
1077 | 1 | tkerber | self.set_coordinates(frame=0, focus=True) |
1078 | 1 | tkerber | |
1079 | 1 | tkerber | def prepare_new_atoms(self): |
1080 | 1 | tkerber | "Marks that the next call to append_atoms should clear the images."
|
1081 | 1 | tkerber | self.images.prepare_new_atoms()
|
1082 | 1 | tkerber | |
1083 | 1 | tkerber | def append_atoms(self, atoms): |
1084 | 1 | tkerber | "Set a new atoms object."
|
1085 | 1 | tkerber | #self.notify_vulnerable() # Do this manually after last frame.
|
1086 | 1 | tkerber | frame = self.images.append_atoms(atoms)
|
1087 | 1 | tkerber | self.set_coordinates(frame=frame-1, focus=True) |
1088 | 1 | tkerber | |
1089 | 1 | tkerber | def notify_vulnerable(self): |
1090 | 1 | tkerber | """Notify windows that would break when new_atoms is called.
|
1091 | 1 | tkerber |
|
1092 | 1 | tkerber | The notified windows may adapt to the new atoms. If that is not
|
1093 | 1 | tkerber | possible, they should delete themselves.
|
1094 | 1 | tkerber | """
|
1095 | 1 | tkerber | new_vul = [] # Keep weakrefs to objects that still exist.
|
1096 | 1 | tkerber | for wref in self.vulnerable_windows: |
1097 | 1 | tkerber | ref = wref() |
1098 | 1 | tkerber | if ref is not None: |
1099 | 1 | tkerber | new_vul.append(wref) |
1100 | 1 | tkerber | ref.notify_atoms_changed() |
1101 | 1 | tkerber | self.vulnerable_windows = new_vul
|
1102 | 1 | tkerber | |
1103 | 1 | tkerber | def register_vulnerable(self, obj): |
1104 | 1 | tkerber | """Register windows that are vulnerable to changing the images.
|
1105 | 1 | tkerber |
|
1106 | 1 | tkerber | Some windows will break if the atoms (and in particular the
|
1107 | 1 | tkerber | number of images) are changed. They can register themselves
|
1108 | 1 | tkerber | and be closed when that happens.
|
1109 | 1 | tkerber | """
|
1110 | 1 | tkerber | self.vulnerable_windows.append(weakref.ref(obj))
|
1111 | 1 | tkerber | |
1112 | 1 | tkerber | def exit(self, button, event=None): |
1113 | 1 | tkerber | gtk.main_quit() |
1114 | 1 | tkerber | return True |
1115 | 1 | tkerber | |
1116 | 1 | tkerber | def xxx(self, x=None, |
1117 | 1 | tkerber | message1='Not implemented!',
|
1118 | 1 | tkerber | message2='do you really need it?'):
|
1119 | 1 | tkerber | oops(message1, message2) |
1120 | 1 | tkerber | |
1121 | 1 | tkerber | def about(self, action): |
1122 | 1 | tkerber | try:
|
1123 | 1 | tkerber | dialog = gtk.AboutDialog() |
1124 | 1 | tkerber | except AttributeError: |
1125 | 1 | tkerber | self.xxx()
|
1126 | 1 | tkerber | else:
|
1127 | 1 | tkerber | dialog.run() |
1128 | 1 | tkerber | |
1129 | 1 | tkerber | def webpage(widget): |
1130 | 1 | tkerber | import webbrowser |
1131 | 1 | tkerber | webbrowser.open('https://wiki.fysik.dtu.dk/ase/ase/gui.html')
|