def to_ao(self, mo_operator): """ Transform an operator from this orbital basis into the AO basis Given the matrix elements :math:`\hat O_{ij}` of an operator over orbital basis indices :math:`i,j`, returns the operator's matrix elements :math:`\hat O_{\mu \nu}` over orbital indices :math:`\mu, \nu`: ..math:: \hat O_{\mu \nu} = \left \langle \mu \right| \hat O \left| \nu \right \rangle = \sum_{i,j,\lambda,\kappa}S_{\mu \lambda} C_{i \lambda} O_{ij} C_{j \kappa} S_{\kappa \nu} where :math:`S_{\mu \nu} = \left \langle \mu | \nu \right \rangle` is the AO overlap matrix and :math:`C_{i \mu}` is the expansion coefficient for AO basis function :math:`\mu` in molecular orbital _i_. Args: mo_operator (u.Array): matrix elements of the operator in this orbital basis Returns: u.Array: matrix elements of the operator in the AO basis """ units = u.get_units(mo_operator) s = self.wfn.aobasis.overlaps o_ao = s.dot(self.coeffs.T).dot(mo_operator).dot(self.coeffs).dot(s) return o_ao * units
def _validate(self, change): import pint self._validated_value = None self._error_msg = False # Check that we can parse this try: val = u.ureg(change['new']) except (pint.UndefinedUnitError, pint.DimensionalityError, pint.compat.tokenize.TokenError): self._error_msg = "Failed to parse '%s'" % self.textbox.value except Exception as e: # unfortunately, pint's parser sometimes raises bare exception class if e.__class__ != Exception: raise # this isn't what we want self._error_msg = "Failed to parse '%s'" % self.textbox.value else: # Check dimensionality valdim = u.get_units(val).dimensionality if self.dimensionality is not None and valdim != self.dimensionality: self._error_msg = "Requires dimensionality %s" % self.dimensionality if not self._error_msg: self.validated.value = '<span title="Valid quantity">%s</span>' % self.VALID self._validated_value = val else: self.validated.value = '<span title="%s">%s</span>' % ( self._error_msg, self.INVALID)
def from_ao(self, ao_operator): """ Transform an operator into this orbital basis from the ao basis Given the matrix elements :math:`\hat O_{\mu \nu}` of an operator over AO basis indices :math:`\mu,\nu`, returns the operator's matrix elements :math:`\hat O_{ij}` over orbital indices :math:`i,j`: ..math:: \hat O_{ij} = \left \langle i \right| \hat O \left| j \right \rangle = \sum_{\mu \nu}C_{i \mu} O_{\mu \nu} C_{j \nu} where :math:`C_{i \mu}` is the expansion coefficient for AO basis function :math:`\mu` in molecular orbital _i_. Args: ao_operator (u.Array): matrix elements of the operator in the ao basis Returns: u.Array: matrix elements of the operator in this orbital basis Note: Assumes that this set of orbitals is orthogonal """ # Dot doesn't place nice with units, so we need to pass them explicitly ao_units = u.get_units(ao_operator) return self.coeffs.dot(ao_operator.dot(self.coeffs.T)) * ao_units
def _validate(self, change): import pint self._validated_value = None self._error_msg = False # Check that we can parse this try: val = u.ureg(change['new']) except (pint.UndefinedUnitError, pint.DimensionalityError, pint.compat.tokenize.TokenError): self._error_msg = "Failed to parse '%s'" % self.textbox.value except Exception as e: # unfortunately, pint's parser sometimes raises bare exception class if e.__class__ != Exception: raise # this isn't what we want self._error_msg = "Failed to parse '%s'" % self.textbox.value else: # Check dimensionality valdim = u.get_units(val).dimensionality if self.dimensionality is not None and valdim != self.dimensionality: self._error_msg = "Requires dimensionality %s" % self.dimensionality if not self._error_msg: self.validated.value = '<span title="Valid quantity">%s</span>' % self.VALID self._validated_value = val else: self.validated.value = '<span title="%s">%s</span>' % (self._error_msg, self.INVALID)
def draw_atom_vectors(self, vecs, rescale_to=1.75, scale_factor=None, opacity=0.85, radius=0.11, **kwargs): """ Draw a 3D vector on each atom Args: vecs (Matrix[shape=(*,3)]): list of vectors for each atom rescale_to (Scalar[length]): vectors so the largest is this long scale_factor (Scalar[length/units]): factor for conversion between input units and length kwargs (dict): keyword arguments for self.draw_arrow """ kwargs['radius'] = radius kwargs['opacity'] = opacity if vecs.shape == (self.mol.ndims, ): vecs = vecs.reshape(self.mol.num_atoms, 3) assert vecs.shape == (self.mol.num_atoms, 3), '`vecs` must be a num_atoms X 3 matrix or' \ ' 3*num_atoms vector' assert not np.allclose(vecs, 0.0), "Input vectors are 0." # strip units and scale the vectors appropriately if scale_factor is not None: # scale all arrows by this quantity if (u.get_units(vecs) / scale_factor).dimensionless: # allow implicit scale factor scale_factor = scale_factor / self.DISTANCE_UNITS vecarray = vecs / scale_factor try: arrowvecs = vecarray.value_in(self.DISTANCE_UNITS) except AttributeError: arrowvecs = vecarray else: # rescale the maximum length arrow length to rescale_to try: vecarray = vecs.magnitude unit = vecs.getunits() except AttributeError: vecarray = vecs unit = '' lengths = np.sqrt((vecarray * vecarray).sum(axis=1)) scale = (lengths.max() / rescale_to ) # units of [vec units] / angstrom if hasattr(scale, 'defunits'): scale = scale.defunits() arrowvecs = vecarray / scale print('Arrow scale: {q:.3f} {unit} per {native}'.format( q=scale, unit=unit, native=self.DISTANCE_UNITS)) shapes = [] for atom, vecarray in zip(self.mol.atoms, arrowvecs): if mathutils.norm(vecarray) < 0.2: continue shapes.append( self.draw_arrow(atom.position, vector=vecarray, **kwargs)) return shapes
def draw_atom_vectors(self, vecs, rescale_to=1.75, scale_factor=None, opacity=0.85, radius=0.11, **kwargs): """ For displaying atom-centered vector data (e.g., momenta, forces) :param rescale_to: rescale to this length (in angstroms) (not used if scale_factor is passed) :param scale_factor: Scaling factor for arrows: dimensions of [vecs dimensions] / [length] :param kwargs: keyword arguments for self.draw_arrow """ kwargs['radius'] = radius kwargs['opacity'] = opacity if vecs.shape == (self.mol.ndims, ): vecs = vecs.reshape(self.mol.num_atoms, 3) assert vecs.shape == (self.mol.num_atoms, 3), '`vecs` must be a num_atoms X 3 matrix or' \ ' 3*num_atoms vector' assert not np.allclose(vecs, 0.0), "Input vectors are 0." # strip units and scale the vectors appropriately if scale_factor is not None: # scale all arrows by this quantity if (u.get_units(vecs) / scale_factor).dimensionless: # allow implicit scale factor scale_factor = scale_factor / self.DISTANCE_UNITS vecarray = vecs / scale_factor try: arrowvecs = vecarray.value_in(self.DISTANCE_UNITS) except AttributeError: arrowvecs = vecarray else: # rescale the maximum length arrow length to rescale_to try: vecarray = vecs.magnitude unit = vecs.getunits() except AttributeError: vecarray = vecs unit = '' lengths = np.sqrt((vecarray * vecarray).sum(axis=1)) scale = (lengths.max() / rescale_to ) # units of [vec units] / angstrom if hasattr(scale, 'defunits'): scale = scale.defunits() arrowvecs = vecarray / scale print 'Arrow scale: {q:.3f} {unit} per {native}'.format( q=scale, unit=unit, native=self.DISTANCE_UNITS) shapes = [] for atom, vecarray in zip(self.mol.atoms, arrowvecs): if vecarray.norm() < 0.2: continue shapes.append( self.draw_arrow(atom.position, vector=vecarray, **kwargs)) return shapes
def draw_atom_vectors(self, vecs, rescale_to=1.75, scale_factor=None, opacity=0.85, radius=0.11, **kwargs): """ Draw a 3D vector on each atom Args: vecs (Matrix[shape=(*,3)]): list of vectors for each atom rescale_to (Scalar[length]): vectors so the largest is this long scale_factor (Scalar[length/units]): factor for conversion between input units and length kwargs (dict): keyword arguments for self.draw_arrow """ kwargs['radius'] = radius kwargs['opacity'] = opacity if vecs.shape == (self.mol.ndims,): vecs = vecs.reshape(self.mol.num_atoms, 3) assert vecs.shape == (self.mol.num_atoms, 3), '`vecs` must be a num_atoms X 3 matrix or' \ ' 3*num_atoms vector' assert not np.allclose(vecs, 0.0), "Input vectors are 0." # strip units and scale the vectors appropriately if scale_factor is not None: # scale all arrows by this quantity if (u.get_units(vecs)/scale_factor).dimensionless: # allow implicit scale factor scale_factor = scale_factor/self.DISTANCE_UNITS vecarray = vecs/scale_factor try: arrowvecs = vecarray.value_in(self.DISTANCE_UNITS) except AttributeError: arrowvecs = vecarray else: # rescale the maximum length arrow length to rescale_to try: vecarray = vecs.magnitude unit = vecs.getunits() except AttributeError: vecarray = vecs unit = '' lengths = np.sqrt((vecarray*vecarray).sum(axis=1)) scale = (lengths.max()/rescale_to) # units of [vec units] / angstrom if hasattr(scale, 'defunits'): scale = scale.defunits() arrowvecs = vecarray/scale print('Arrow scale: {q:.3f} {unit} per {native}'.format(q=scale, unit=unit, native=self.DISTANCE_UNITS)) shapes = [] for atom, vecarray in zip(self.mol.atoms, arrowvecs): if mathutils.norm(vecarray) < 0.2: continue shapes.append(self.draw_arrow(atom.position, vector=vecarray, **kwargs)) return shapes
def __init__(self, value=None, units=None, **kwargs): super(UnitText, self).__init__(layout=ipy.Layout(display='flex', flex_flow='row wrap'), **kwargs) self.textbox = ipy.Text() self.textbox.observe(self._validate, 'value') self._error_msg = None if units is not None: self.dimensionality = u.get_units(units).dimensionality else: self.dimensionality = None self._validated_value = None self.validated = ipy.HTML(self.INVALID) self.children = [self.textbox, self.validated] self._is_valid = False if value is not None: self.value = value
def draw_atom_vectors(self, vecs, rescale_to=1.75, scale_factor=None, opacity=0.85, radius=0.11, **kwargs): """ For displaying atom-centered vector data (e.g., momenta, forces) :param rescale_to: rescale to this length (in angstroms) (not used if scale_factor is passed) :param scale_factor: Scaling factor for arrows: dimensions of [vecs dimensions] / [length] :param kwargs: keyword arguments for self.draw_arrow """ kwargs['radius'] = radius kwargs['opacity'] = opacity if vecs.shape == (self.mol.ndims,): vecs = vecs.reshape(self.mol.num_atoms, 3) assert vecs.shape == (self.mol.num_atoms, 3), '`vecs` must be a num_atoms X 3 matrix or' \ ' 3*num_atoms vector' assert not np.allclose(vecs, 0.0), "Input vectors are 0." # strip units and scale the vectors appropriately if scale_factor is not None: # scale all arrows by this quantity if (u.get_units(vecs)/scale_factor).dimensionless: # allow implicit scale factor scale_factor = scale_factor / self.DISTANCE_UNITS vecarray = vecs / scale_factor try: arrowvecs = vecarray.value_in(self.DISTANCE_UNITS) except AttributeError: arrowvecs = vecarray else: # rescale the maximum length arrow length to rescale_to try: vecarray = vecs.magnitude unit = vecs.getunits() except AttributeError: vecarray = vecs unit = '' lengths = np.sqrt((vecarray * vecarray).sum(axis=1)) scale = (lengths.max() / rescale_to) # units of [vec units] / angstrom if hasattr(scale,'defunits'): scale = scale.defunits() arrowvecs = vecarray / scale print 'Arrow scale: {q:.3f} {unit} per {native}'.format(q=scale, unit=unit, native=self.DISTANCE_UNITS) shapes = [] for atom, vecarray in zip(self.mol.atoms, arrowvecs): if vecarray.norm() < 0.2: continue shapes.append(self.draw_arrow(atom.position, vector=vecarray, **kwargs)) return shapes
def _validate(self, change): self._validated_value = None self._error_msg = False # Check that we can parse this try: val = u.ureg(change['new']) except: # parsing failed, pint just raises generic "Exception" self._error_msg = "Failed to parse '%s'" % self.textbox.value else: # Check dimensionality valdim = u.get_units(val).dimensionality if self.dimensionality is not None and valdim != self.dimensionality: self._error_msg = "Requires dimensionality %s" % self.dimensionality if not self._error_msg: self.validated.value = '<span title="Valid quantity">%s</span>' % self.VALID self._validated_value = val else: self.validated.value = '<span title="%s">%s</span>' % ( self._error_msg, self.INVALID)
def test_getunits_doctests(): assert units.get_units(1.0 * units.angstrom) == units.MdtUnit('angstrom') assert units.get_units(np.array([1.0, 2, 3.0])) == units.MdtUnit('dimensionless') assert units.get_units([[1.0 * units.dalton, 3.0 * units.eV], ['a'], 'gorilla']) == units.MdtUnit('amu')