Source code for moldesign.widgets.orbitals

# Copyright 2016 Autodesk Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import collections

import ipywidgets as ipy

from moldesign.uibase.selector import SelectionGroup, Selector, create_value_selector
from moldesign.viewer import GeometryViewer


[docs]class OrbitalViewer(SelectionGroup): def __init__(self, mol, **kwargs): """ :param mol: a molecule with A) orbitals, and B) an energy model with calculate_orbital_grid :param kwargs: kwargs for the viewer :return: """ self.viewer = GeometryViewer(mol=mol, **kwargs) self.viewer.wfns = [mol.wfn] self.uipane = OrbitalUIPane(self, height=int(self.viewer.height)-50) hb = ipy.HBox([self.viewer, self.uipane]) super(OrbitalViewer, self).__init__([hb])
[docs]class OrbitalUIPane(Selector, ipy.Box): # TODO: deal with orbitals not present in all frames of a trajectory # TODO: deal with orbital properties (occupation and energy) changing over a trajectory def __init__(self, viz, **kwargs): self.viz = viz kwargs.setdefault('width', 325) self.type_dropdown = ipy.Dropdown(options=self.viz.viewer.wfn.orbitals.keys()) initial_orb = 'canonical' if initial_orb not in self.type_dropdown.options: initial_orb = self.type_dropdown.options.iterkeys().next() self.type_dropdown.value = initial_orb self.type_dropdown.observe(self.new_orb_type, 'value') self.orblist = ipy.Select(options={None: None}, width=str(kwargs['width'])+'px', height=str(int(kwargs['height']) - 75)+'px') self.isoval_selector = create_value_selector(ipy.FloatSlider, value_selects='orbital_isovalue', min=0.0, max=0.075, value=0.01, step=0.00075, width=kwargs['width'], description='Isovalue', readout_format='.4f') self.orb_resolution = ipy.Text(description='Orbital resolution', width=75) self.orb_resolution.value = '40' # string because it's required for the 'on_submit' method self.change_resolution() self.orb_resolution.on_submit(self.change_resolution) children = [self.type_dropdown, self.orblist, self.isoval_selector, self.orb_resolution] super(OrbitalUIPane, self).__init__(children, **kwargs) self.new_orb_type() self.orblist.observe(self.new_orbital_selection, 'value')
[docs] def new_orbital_selection(self, *args): self.fire_selection_event({'orbname': (self.type_dropdown.value, self.orblist.value)})
[docs] def handle_selection_event(self, *args): # TODO: update the selected orbitals if something actually else triggers this pass
[docs] def new_orb_type(self, *args): """Create list of available orbitals when user selects a new type """ wfn = self.viz.viewer.wfn newtype = self.type_dropdown.value neworbs = wfn.orbitals[newtype] orblist = collections.OrderedDict() orblist[None] = None for i, orb in enumerate(neworbs): if hasattr(orb, 'unicode_name'): orbname = orb.unicode_name else: orbname = orb.name meta = '' if orb.energy is not None: meta = '{:.02fP}'.format(orb.energy.defunits()) if orb.occupation is not None: if meta: meta += ', ' meta += 'occ %.2f' % orb.occupation if meta: desc = '%d. %s (%s)' % (i, orbname, meta) else: desc = '%d. %s' % (i, orbname) orblist[desc] = i self.orblist.value = None self.orblist.options = orblist
[docs] def change_resolution(self, *args): viewer = self.viz.viewer viewer.orbital_spec['npts'] = int(self.orb_resolution.value) if viewer.current_orbital is not None: viewer.draw_orbital(viewer.current_orbital, render=True, **viewer.orbital_spec)