Skip to content

FashionView module

FashionView

Bases: widgets.DOMWidget

An interactive molecule-builder interface for the Hylleraas Software Platform

Author: Audun Skau Hansen (2023)

The FashionView module enables two-way communication of data between a Javascript frond-end 3D visualization and a IPython-kernel in Jupyter. User interaction with the front-end can trigger events on the kernel, and the kernel can instantly update the view.

Keyword arguments:

Argument Description Subattributes and defaults
molecular_system An instance of a class containing information on the molecular system   pos (Nx3 list with N atom positions), count (N atoms ), bonds (Nb x 2 list of connected atoms), size (numpy array with simulation box size)
radius_scale Scaling of atomic radius 1.0
realism Use van der Waals radius for atoms and CPK coloring False (bool)
background_color Background color [1.0, 1.0, 1.0] (list defining the color white)
bonds Background color [1.0, 1.0, 1.0] (list defining the color white)
window_scale_height, window_scale_width Scaling of visualization within canvas 0.5, 0.75
options a list of strings to be rendered as buttons / options in the front end environment
fxaa Fast Approximate Anti-Aliasing (source, overview) True (bool)
sao Screen space ambient occlusion effect (source, overview) False (bool)
saoScale 100
saoBias 0.1
saoIntensity 0.1
saoKernelRadius 10
saoMinResolution 0.5
saoBlur False (bool)
saoBlurRadius 50
saoBlurStdDev 1.0
saoBlurDepthCutoff 0.05
dof Depth of field effect (source, overview) False (bool)
focus 10
aperture 0.001
max_blur 0.01

Example usage

For example usage, see the provided example class using BubbleBox

Source code in evince/fashionview.py
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
@widgets.register
class FashionView(widgets.DOMWidget):
    """
    # An interactive molecule-builder interface for the Hylleraas Software Platform
    Author: Audun Skau Hansen (2023)

    The FashionView module enables two-way communication of data between a Javascript frond-end 3D visualization and a IPython-kernel in Jupyter. User interaction with the front-end can trigger events on the kernel, and the kernel can instantly update the view.

    ## Keyword arguments:


    | Argument      | Description | Subattributes and defaults |
    | ----------- | ----------- | ---------- |
    | molecular_system      | An instance of a class containing information on the molecular system |  ```pos``` (Nx3 list with N atom positions), ```count``` (N atoms ), ```bonds``` (Nb x 2 list of connected atoms), ```size``` (numpy array with simulation box size)
    |  radius_scale    |  Scaling of atomic radius | ```1.0```  |
    |  realism    |  Use van der Waals radius for atoms and <a href="https://sciencenotes.org/molecule-atom-colors-cpk-colors/">CPK</a> coloring | ```False``` (bool) |
    |  background_color    |  Background color | ```[1.0, 1.0, 1.0]``` (list defining the color white) |
    |  bonds    |  Background color | ```[1.0, 1.0, 1.0]``` (list defining the color white) |
    | window_scale_height, window_scale_width   | Scaling of visualization within canvas        | ```0.5```,  ```0.75``` |
    | options   | a list of strings to be rendered as buttons / options in the front end environment   |
    | fxaa   |   Fast Approximate Anti-Aliasing (<a href="https://github.com/mrdoob/three.js/blob/dev/examples/jsm/shaders/FXAAShader.js">source</a>, <a href="10.1109/ICCRD54409.2022.9730249">overview</a>)  | ```True``` (bool) |
    |  sao   |   Screen space ambient occlusion effect (<a href="https://github.com/mrdoob/three.js/blob/dev/examples/jsm/postprocessing/SAOPass.js">source</a>, <a href="https://people.mpi-inf.mpg.de/~ritschel/SSDO/index.html">overview</a>) |```False``` (bool) |
    |  saoScale    |    | ```100``` |
    |  saoBias    |    | ```0.1``` |
    |  saoIntensity    |    | ```0.1``` |
    |  saoKernelRadius    |    | ```10``` |
    |  saoMinResolution    |    | ```0.5``` |
    |  saoBlur    |    | ```False``` (bool) |
    |  saoBlurRadius    |    | ```50``` |
    |  saoBlurStdDev    |    | ```1.0``` |
    |  saoBlurDepthCutoff    |    | ```0.05``` |
    |  dof   |  Depth of field effect (<a href="https://github.com/mrdoob/three.js/blob/dev/examples/jsm/postprocessing/BokehPass.js">source</a>, <a href="https://people.mpi-inf.mpg.de/~ritschel/SSDO/index.html">overview</a>) |```False``` (bool) |
    |  focus    |    | ```10``` |
    |  aperture    |    | ```0.001``` |
    |  max_blur    |    | ```0.01``` |


    ## Example usage

    For example usage, see the provided example class using <a href="audunsh.github.io/bubblebox">BubbleBox</a>



    """
    # Name of the widget view class in front-end
    _view_name = Unicode('FashionView').tag(sync=True)

    # Name of the widget model class in front-end
    _model_name = Unicode('FashionModel').tag(sync=True)

    # Name of the front-end module containing widget view
    _view_module = Unicode('evince').tag(sync=True)

    # Name of the front-end module containing widget model
    _model_module = Unicode('evince').tag(sync=True)


    # Version of the front-end module containing widget view
    _view_module_version = Unicode(NPM_PACKAGE_RANGE).tag(sync=True)
    # Version of the front-end module containing widget model
    _model_module_version = Unicode(NPM_PACKAGE_RANGE).tag(sync=True)


    # atom variables to sync with front-end
    pos = tl.List([[0,0,0]]).tag(sync=True) # positions of atoms
    radius = tl.List([]).tag(sync=True)     # radius of spheres
    count = tl.Int().tag(sync=True)         # the number of atoms
    init = tl.Bool(False).tag(sync=True)    # trigger for initialization
    masses = tl.List([]).tag(sync=True)     # masses for atoms (only used to get vdw-radius)
    colors = tl.List([]).tag(sync=True)     # colors of atoms
    box = tl.List([]).tag(sync=True)        # optional box 
    bonds = tl.List([]).tag(sync=True)


    """
    Various post-processing effects

    sao - Screen space ambient occlusion
    source  : https://github.com/mrdoob/three.js/blob/dev/examples/jsm/postprocessing/SAOPass.js
    overview: https://people.mpi-inf.mpg.de/~ritschel/SSDO/index.html

    dof - depth of field
    source  : https://github.com/mrdoob/three.js/blob/dev/examples/jsm/postprocessing/BokehPass.js
    overview: https://people.mpi-inf.mpg.de/~ritschel/SSDO/index.html

    fxaa - fast approximate anti-aliasing
    source   - https://github.com/mrdoob/three.js/blob/dev/examples/jsm/shaders/FXAAShader.js
    overview - 10.1109/ICCRD54409.2022.9730249
    """

    # fxaa settings
    fxaa = tl.Bool(False).tag(sync=True)

    # camera / dof settings
    dof = tl.Bool(False).tag(sync=True)
    focus = tl.Float().tag(sync=True)
    aperture = tl.Float().tag(sync=True)
    max_blur = tl.Float().tag(sync=True)

    # sao settings
    sao = tl.Bool(False).tag(sync=True)
    saoScale = tl.Float().tag(sync=True)
    saoBias = tl.Float().tag(sync=True)
    saoIntensity = tl.Float().tag(sync=True)
    saoKernelRadius = tl.Int().tag(sync=True)
    saoMinResolution = tl.Float().tag(sync=True)
    saoBlur = tl.Bool(False).tag(sync=True)
    saoBlurRadius = tl.Int().tag(sync=True)
    saoBlurStdDev = tl.Float().tag(sync=True)
    saoBlurDepthCutoff = tl.Float().tag(sync=True)

    # colorscheme for orbital visualization
    additive = tl.Bool(False).tag(sync=True)

    # general settings
    background_color = tl.List([]).tag(sync=True) #background color


    # two way kernel-frontend communcation
    options = tl.List([]).tag(sync=True)

    kernel_task = tl.Int().tag(sync=True)

    synchronized_text = tl.Unicode('Options').tag(sync=True)

    trigger_advance = tl.Bool(False).tag(sync=True)

    add_new_atom = tl.List([]).tag(sync=True)

    window_scale_height = tl.Float().tag(sync=True)
    window_scale_width = tl.Float().tag(sync=True)

    selection = tl.List([]).tag(sync=True)



    def __init__(self, molecular_system, window_scale_height = 0.5, window_scale_width=0.75, fxaa = True, sao  =False, dof = False, additive = False, background_color = [1.0, 1.0, 1.0], focus = 10, aperture = 0.001, max_blur = 0.01, saoScale = 100 ,saoBias = .1,saoIntensity = .1,saoKernelRadius = 10,saoMinResolution = .5,saoBlur = False,saoBlurRadius = 50,saoBlurStdDev = 1.0,saoBlurDepthCutoff = 0.05, realism = False, radius_scale = 1.0, options  = []):
        super().__init__() # execute init of parent class, append: 

        # general settings
        self.window_scale_height = window_scale_height
        self.window_scale_width = window_scale_width
        self.molecular_system = molecular_system
        self.options = options

        # enable/disable sao + settings
        self.sao = sao
        self.saoScale = saoScale
        self.saoBias = saoBias
        self.saoIntensity = saoIntensity
        self.saoKernelRadius = saoKernelRadius
        self.saoMinResolution = saoMinResolution
        self.saoBlur = saoBlur
        self.saoBlurRadius = saoBlurRadius
        self.saoBlurStdDev = saoBlurStdDev
        self.saoBlurDepthCutoff = saoBlurDepthCutoff

        #enable / disable fxaa 
        self.fxaa = fxaa

        # enable / disable dof
        self.dof = dof 
        self.focus = focus
        self.aperture = aperture
        self.max_blur = max_blur

        # color settings
        self.additive = additive
        self.background_color = background_color

        # access system data from 
        self.pos = molecular_system.pos #.tolist()
        self.count = molecular_system.n_particles
        self.bonds = molecular_system.bonds
        self.box = molecular_system.size.tolist()
        nc = 20
        self.radius = [1.0 for i in range(molecular_system.n_particles)]
        self.colors = np.array((interp1d(np.linspace(0,1,nc), np.random.uniform(0,1,(3, nc)) )(molecular_system.masses/molecular_system.masses.max()).T), dtype = float).tolist()
        if realism:
            self.radius = (radius_scale*get_vwv_radius_from_atomic_number(molecular_system.masses)).tolist()
            self.colors = colorscheme(molecular_system.masses).T.tolist()

        self.masses = molecular_system.masses.tolist()
        self.init = True #trigger frontend init


    # functions synchronized with the frontend widget

    @observe('kernel_task')
    def _observe_kernel_task(self, change):
        """
        This command is executed when triggered from fron-end.
        The ´´´change´´´-variable contains the list of selected atoms.
        """
        self.molecular_system.execute_kernel(change)

    @observe('selection')
    def _execute_kernel(self, change):
        """
        Update the list of selected atoms on the kernel
        """
        self.selection = change

    @observe('add_new_atom')
    def _observe_add_new_atom(self, change):
        """
        Test function
        """
        self.new_atom_observed = True

    @observe('trigger_advance')
    def _observe_trigger_advance(self, change):
        """
        Test function
        """
        pass

    def save(self, filename, title = ""):
        """
        Save a standalone html embedding of the view



        """
        embed.embed_minimal_html(filename, [self], title)

save(filename, title='')

Save a standalone html embedding of the view

Source code in evince/fashionview.py
289
290
291
292
293
294
295
296
def save(self, filename, title = ""):
    """
    Save a standalone html embedding of the view



    """
    embed.embed_minimal_html(filename, [self], title)

colorscheme(masses)

Default CPK-colorscheme for atoms source: https://sciencenotes.org/molecule-atom-colors-cpk-colors/

Source code in evince/fashionview.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def colorscheme(masses):
    """
    Default CPK-colorscheme for atoms
    source: https://sciencenotes.org/molecule-atom-colors-cpk-colors/
    """
    colors = np.array([[255, 217, 204, 194, 255, 144,  48, 255, 144, 179, 171, 138, 191,
        240, 255, 255,  31, 128, 143,  61, 230, 191, 166, 138, 156, 224,
        240,  80, 200, 125, 194, 102, 189, 255, 166,  92, 112,   0, 148,
        148, 115,  84,  59,  36,  10,   0, 192, 255, 166, 102, 158, 212,
        148,  66,  87,   0, 112, 255, 217, 199, 163, 143,  97,  69,  48,
         31,   0,   0,   0,   0,   0,  77,  77,  33,  38,  38,  23, 208,
        255, 184, 166,  87, 158, 171, 117,  66,  66,   0, 112,   0,   0,
          0,   0,   0,  84, 120, 138, 161, 179, 179, 179, 189, 199, 204,
        209, 217, 224, 230, 235],
       [255, 255, 128, 255, 181, 144,  80,  13, 224, 227,  92, 255, 166,
        200, 128, 255, 240, 209,  64, 255, 230, 194, 166, 153, 122, 102,
        144, 208, 128, 128, 143, 143, 128, 161,  41, 184,  46, 255, 255,
        224, 194, 181, 158, 143, 125, 105, 192, 217, 117, 128,  99, 122,
          0, 158,  23, 201, 212, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 230, 212, 191, 171, 194, 166, 148, 125, 102,  84, 208,
        209, 184,  84,  89,  79,  92,  79, 130,   0, 125, 171, 186, 161,
        143, 128, 107,  92,  92,  79,  54,  31,  31,  13,  13,   0,   0,
          0,   0,   0,   0,   0],
       [255, 255, 255,   0, 181, 144, 248,  13,  80, 245, 242,   0, 166,
        160,   0,  48,  31, 227, 212,   0, 230, 199, 171, 199, 199,  51,
        160,  80,  51, 176, 143, 143, 227,   0,  41, 209, 176,   0, 255,
        224, 201, 181, 158, 143, 140, 133, 192, 143, 115, 128, 181,   0,
        148, 176, 143,   0, 255, 199, 199, 199, 199, 199, 199, 199, 199,
        199, 156, 117,  82,  56,  36, 255, 255, 214, 171, 150, 135, 224,
         35, 208,  77,  97, 181,   0,  69, 150, 102,   0, 250, 255, 255,
        255, 255, 255, 242, 227, 227, 212, 212, 186, 166, 135, 102,  89,
         79,  69,  56,  46,  38]])/510.0


    return interp1d(np.arange(1,colors.shape[1]+1), colors,bounds_error=False,fill_value = [1.0,1.0,1.0])(masses)

extract_bonds(b, btype=2)

Extract harmonic oscillator interactions (btype == 2) from a bubblebbox.mdbox object

returns a bonds-list for spotlightviewer

Source code in evince/fashionview.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def extract_bonds(b, btype = 2):
    """
    Extract harmonic oscillator interactions (btype == 2) from 
    a bubblebbox.mdbox object

    returns a bonds-list for spotlightviewer
    """
    bonds = []
    for i in range(b.n_bubbles):
        for j in range(i+1, b.n_bubbles):
            if b.interactions[i,j,0] == 2.0:
                bonds.append([i,j])

    return bonds