Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1'''celleditor.py - Window for editing the cell of an atoms object
2'''
3from ase.cell import Cell
4from ase.gui.i18n import _
6import ase.gui.ui as ui
7import numpy as np
10class CellEditor:
11 '''Window for editing the cell of an atoms object.'''
12 def __init__(self, gui):
13 self.gui = gui
14 self.gui.register_vulnerable(self)
16 # Create grid control for cells
17 # xx xy xz ||x|| pbc
18 # yx yy yz ||y|| pbc
19 # zx zy zz ||z|| pbc
20 self.cell_grid = []
21 self.pbc = []
22 self.angles = []
24 atoms = self.gui.atoms
26 cell = atoms.cell
27 mags = cell.lengths()
28 angles = cell.angles()
29 pbc = atoms.pbc
31 for i in [0, 1, 2]: # x_ y_ z_
32 row = []
33 for j in [0, 1, 2]: # _x _y _z
34 row.append(ui.SpinBox(cell[i][j], -30, 30, 0.1,
35 self.apply_vectors, rounding=7, width=9))
36 row.append(ui.SpinBox(mags[i], -30, 30, 0.1, self.apply_magnitudes,
37 rounding=7, width=9))
38 self.cell_grid.append(row)
39 self.pbc.append(ui.CheckButton('', bool(pbc[i]), self.apply_pbc))
40 self.angles.append(ui.SpinBox(angles[i], -360, 360, 15,
41 self.apply_angles,
42 rounding=7, width=9))
44 self.scale_atoms = ui.CheckButton('', False)
45 self.vacuum = ui.SpinBox(5, 0, 15, 0.1, self.apply_vacuum)
47 # TRANSLATORS: This is a title of a window.
48 win = self.win = ui.Window(_('Cell Editor'))
50 x, y, z = self.cell_grid
52 win.add([_('A:'), x[0], x[1], x[2], _('||A||:'), x[3],
53 _('periodic:'), self.pbc[0]])
54 win.add([_('B:'), y[0], y[1], y[2], _('||B||:'), y[3],
55 _('periodic:'), self.pbc[1]])
56 win.add([_('C:'), z[0], z[1], z[2], _('||C||:'), z[3],
57 _('periodic:'), self.pbc[2]])
58 win.add([_('∠BC:'), self.angles[0], _('∠AC:'), self.angles[1],
59 _('∠AB:'), self.angles[2]])
60 win.add([_('Scale atoms with cell:'), self.scale_atoms])
61 win.add([ui.Button(_('Apply Vectors'), self.apply_vectors),
62 ui.Button(_('Apply Magnitudes'), self.apply_magnitudes),
63 ui.Button(_('Apply Angles'), self.apply_angles)])
64 win.add([_('Pressing 〈Enter〉 as you enter values will '
65 'automatically apply correctly')])
66 # TRANSLATORS: verb
67 win.add([ui.Button(_('Center'), self.apply_center),
68 ui.Button(_('Wrap'), self.apply_wrap),
69 _('Vacuum:'), self.vacuum,
70 ui.Button(_('Apply Vacuum'), self.apply_vacuum)])
72 def apply_center(self, *args):
73 atoms = self.gui.atoms.copy()
74 atoms.center()
75 self.gui.new_atoms(atoms)
77 def apply_wrap(self, *args):
78 atoms = self.gui.atoms.copy()
79 atoms.wrap()
80 self.gui.new_atoms(atoms)
82 def apply_vacuum(self, *args):
83 atoms = self.gui.atoms.copy()
85 axis = []
86 for index, pbc in enumerate(atoms.pbc):
87 if not pbc:
88 axis.append(index)
90 atoms.center(vacuum=self.vacuum.value, axis=axis)
91 self.gui.new_atoms(atoms)
93 def apply_vectors(self, *args):
94 atoms = self.gui.atoms.copy()
96 atoms.set_cell(self.get_vectors(),
97 scale_atoms=self.scale_atoms.var.get())
98 self.gui.new_atoms(atoms)
100 def get_vectors(self):
101 x, y, z = self.cell_grid
102 cell = np.array(
103 [[x[0].value, x[1].value, x[2].value],
104 [y[0].value, y[1].value, y[2].value],
105 [z[0].value, z[1].value, z[2].value]]
106 )
107 return Cell(cell)
109 def get_magnitudes(self):
110 x, y, z = self.cell_grid
111 return np.array([x[3].value, y[3].value, z[3].value])
113 def apply_magnitudes(self, *args):
114 atoms = self.gui.atoms.copy()
116 old_mags = atoms.cell.lengths()
117 new_mags = self.get_magnitudes()
119 newcell = atoms.cell.copy()
120 for i in range(3):
121 newcell[i] *= new_mags[i] / old_mags[i]
123 atoms.set_cell(newcell,
124 scale_atoms=self.scale_atoms.var.get())
126 self.gui.new_atoms(atoms)
128 def apply_angles(self, *args):
129 atoms = self.gui.atoms.copy()
131 cell_data = atoms.cell.cellpar()
132 cell_data[3:7] = [self.angles[0].value, self.angles[1].value,
133 self.angles[2].value]
135 atoms.set_cell(cell_data, scale_atoms=self.scale_atoms.var.get())
137 self.gui.new_atoms(atoms)
139 def apply_pbc(self, *args):
140 atoms = self.gui.atoms.copy()
142 pbc = [pbc.var.get() for pbc in self.pbc]
143 atoms.set_pbc(pbc)
145 self.gui.new_atoms(atoms)
147 def notify_atoms_changed(self):
148 atoms = self.gui.atoms
149 self.update(atoms.cell, atoms.pbc)
151 def update(self, cell, pbc):
152 cell = Cell(cell)
153 mags = cell.lengths()
154 angles = cell.angles()
156 for i in range(3):
157 for j in range(3):
158 if np.isnan(cell[i][j]):
159 cell[i][j] = 0
160 self.cell_grid[i][j].value = cell[i][j]
162 if np.isnan(mags[i]):
163 mags[i] = 0
164 self.cell_grid[i][3].value = mags[i]
166 if np.isnan(angles[i]):
167 angles[i] = 0
168 self.angles[i].value = angles[i]
170 self.pbc[i].var.set(bool(pbc[i]))