diff --git a/moldesign/helpers/widgets.py b/moldesign/helpers/widgets.py index 1b84124..5c4fe97 100644 --- a/moldesign/helpers/widgets.py +++ b/moldesign/helpers/widgets.py @@ -59,7 +59,7 @@ def not_installed_method(*args, **kwargs): try: - from nbmolviz.uibase import Logger, display_log + from nbmolviz.uielements import Logger, display_log exports_names('Logger', 'display_log') except ImportError: diff --git a/moldesign/molecules/bonds.py b/moldesign/molecules/bonds.py index 6a2ae59..c0f6063 100644 --- a/moldesign/molecules/bonds.py +++ b/moldesign/molecules/bonds.py @@ -25,6 +25,7 @@ from . import toplevel from .. import units as u from .. import mathutils +from .. import geom @toplevel @@ -95,6 +96,12 @@ def order(self, order): if atom.molecule is self.molecule: atom.bond_graph[nbr] = order + @property + def exists(self): + """ bool: whether or not this bond exists + """ + return self.order is not None + @property def type(self): return self.a1.symbol + self.SYMBOLS.get(self.order, u'?ΜΆ') + self.a2.symbol @@ -129,6 +136,11 @@ def partner(self, atom): def length(self): return self.a1.distance(self.a2) + @length.setter + def length(self, value): + geom.set_distance(self.a1, self.a2, value, + adjustmol=self.exists and not self.is_cyclic) + @property def name(self): """ str: name of the bond """ @@ -151,6 +163,26 @@ def molecule(self): def midpoint(self): return (self.a1.position + self.a2.position) / 2.0 + @property + def is_cyclic(self): + """ + bool: True if this bond is in one or more rings + """ + visited = set([self.a2]) + + def check_for_cycles(atom): + visited.add(atom) + for nbr in atom.bond_graph: + if nbr is self.a2 and atom is not self.a1: + return True + if nbr not in visited: + in_cycle = check_for_cycles(nbr) + if in_cycle: + return True + return False # if here, not in a cycle + check_for_cycles(self.a1) + + def align(self, other, centered=True): """ Rotates the entire molecule to align this bond with another object. diff --git a/moldesign/orbitals/wfn.py b/moldesign/orbitals/wfn.py index c7daa14..926a741 100644 --- a/moldesign/orbitals/wfn.py +++ b/moldesign/orbitals/wfn.py @@ -19,7 +19,7 @@ import numpy as np import copy -from . import MolecularOrbitals +from . import Orbital, MolecularOrbitals from ..utils import DotDict @@ -73,8 +73,12 @@ def __init__(self, mol, num_electrons, self.positions = positions.copy() if self.aobasis is not None: - self.orbitals['atomic'] = self.aobasis self.aobasis.wfn = self + atomic_orbs = [Orbital(c, basis=self.aobasis, wfn=self, name=bf.name) + for c,bf in zip(np.identity(len(self.aobasis)), self.aobasis)] + self.orbitals.atomic = MolecularOrbitals(atomic_orbs, wfn=self, + basis=self.aobasis, + orbtype='atomic') for orb in self.aobasis.orbitals: orb.wfn = self diff --git a/moldesign/units/quantity.py b/moldesign/units/quantity.py index 1c10e2f..8c9d481 100644 --- a/moldesign/units/quantity.py +++ b/moldesign/units/quantity.py @@ -125,7 +125,10 @@ def __deepcopy__(self, memo): return result def __hash__(self): - return hash((self._magnitude, str(self.units))) + m = self._magnitude + if isinstance(m, np.ndarray) and m.shape == (): + m = float(m) + return hash((m, str(self.units))) def __setitem__(self, key, value): from . import array as quantityarray