Coverage for /builds/ase/ase/ase/visualize/ngl.py: 14.04%
57 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
1# fmt: off
3from ase import Atoms
6class NGLDisplay:
7 """Structure display class
9 Provides basic structure/trajectory display
10 in the notebook and optional gui which can be used to enhance its
11 usability. It is also possible to extend the functionality of the
12 particular instance of the viewer by adding further widgets
13 manipulating the structure.
14 """
16 def __init__(self, atoms, xsize=500, ysize=500):
17 import nglview
18 import nglview.color
19 from ipywidgets import Dropdown, FloatSlider, HBox, IntSlider, VBox
20 self.atoms = atoms
21 if isinstance(atoms[0], Atoms):
22 # Assume this is a trajectory or struct list
23 self.view = nglview.show_asetraj(atoms, default=False)
24 self.frm = IntSlider(value=0, min=0, max=len(atoms) - 1)
25 self.frm.observe(self._update_frame)
26 self.struct = atoms[0]
27 else:
28 # Assume this is just a single structure
29 self.view = nglview.show_ase(atoms, default=False)
30 self.struct = atoms
31 self.frm = None
33 self.colors = {}
34 self.view._remote_call('setSize', target='Widget',
35 args=['%dpx' % (xsize,), '%dpx' % (ysize,)])
36 self.view.add_unitcell()
37 self.view.add_spacefill()
38 self.view.camera = 'orthographic'
39 self.view.parameters = {"clipDist": 0}
41 self.view.center()
43 self.asel = Dropdown(options=['All'] +
44 list(set(self.struct.get_chemical_symbols())),
45 value='All', description='Show')
47 self.csel = Dropdown(options=nglview.color.COLOR_SCHEMES,
48 value='element', description='Color scheme')
50 self.rad = FloatSlider(value=0.5, min=0.0, max=1.5, step=0.01,
51 description='Ball size')
53 self.asel.observe(self._select_atom)
54 self.csel.observe(self._update_repr)
55 self.rad.observe(self._update_repr)
57 self.view.update_spacefill(radiusType='covalent',
58 radiusScale=0.5,
59 color_scheme=self.csel.value,
60 color_scale='rainbow')
62 wdg = [self.asel, self.csel, self.rad]
63 if self.frm:
64 wdg.append(self.frm)
66 self.gui = HBox([self.view, VBox(wdg)])
67 # Make useful shortcuts for the user of the class
68 self.gui.view = self.view
69 self.gui.control_box = self.gui.children[1]
70 self.gui.custom_colors = self.custom_colors
72 def _update_repr(self, chg=None):
73 self.view.update_spacefill(radiusType='covalent',
74 radiusScale=self.rad.value,
75 color_scheme=self.csel.value,
76 color_scale='rainbow')
78 def _update_frame(self, chg=None):
79 self.view.frame = self.frm.value
80 return
82 def _select_atom(self, chg=None):
83 sel = self.asel.value
84 self.view.remove_spacefill()
85 for e in set(self.struct.get_chemical_symbols()):
86 if (sel == 'All' or e == sel):
87 if e in self.colors:
88 self.view.add_spacefill(selection='#' + e,
89 color=self.colors[e])
90 else:
91 self.view.add_spacefill(selection='#' + e)
92 self._update_repr()
94 def custom_colors(self, clr=None):
95 """
96 Define custom colors for some atoms. Pass a dictionary of the form
97 {'Fe':'red', 'Au':'yellow'} to the function.
98 To reset the map to default call the method without parameters.
99 """
100 if clr:
101 self.colors = clr
102 else:
103 self.colors = {}
104 self._select_atom()
107def view_ngl(atoms, data=None, repeat=None, w=500, h=500):
108 """
109 Returns the nglviewer + some control widgets in the VBox ipywidget.
110 The viewer supports any Atoms objectand any sequence of Atoms objects.
111 The returned object has two shortcuts members:
113 .view:
114 nglviewer ipywidget for direct interaction
115 .control_box:
116 VBox ipywidget containing view control widgets
117 """
118 # TODO: make `data` and `repeat` really available
119 return NGLDisplay(atoms, w, h).gui