Source code for sknano.core.atoms._atom

# -*- coding: utf-8 -*-
"""
============================================================================
Base class for structure data atom (:mod:`sknano.core.atoms._atom`)
============================================================================

.. currentmodule:: sknano.core.atoms._atom

"""
from __future__ import absolute_import, division, print_function

__docformat__ = 'restructuredtext en'

from functools import total_ordering

import numbers

from sknano.core.refdata import atomic_masses, atomic_mass_symbol_map, \
    atomic_numbers, atomic_number_symbol_map, element_symbols, element_names

__all__ = ['Atom']


@total_ordering
[docs]class Atom(object): """Base class for abstract representation of structure atom. Parameters ---------- element : {str, int}, optional A string representation of the element symbol or an integer specifying an element atomic number :math:`\\boldsymbol{Z}`. """ _atomattrs = ['symbol', 'Z', 'm'] # private class var __hash__ = object.__hash__ def __init__(self, element=None, m=None): # set mass first because the element.setter method may check mass value if m is None: m = 0 self.m = m self.element = element def __str__(self): """Return nice string representation of `Atom`.""" return repr(self) def __repr__(self): """Return canonical string representation of `Atom`.""" return "Atom(element={!r}, m={!r})".format(self.element, self.m) def __eq__(self, other): """Test equality of two `Atom` object instances.""" if self is other: return True else: for p in self._atomattrs: if getattr(self, p) != getattr(other, p): return False return True def __lt__(self, other): """Test if `self` is *less than* `other`.""" return self.Z < other.Z #def __mul__(self, other): # """Multiply atom @property def Z(self): """Atomic number :math:`Z`. Returns ------- int Atomic number :math:`Z`. """ return self._Z @Z.setter def Z(self, value): """Set atomic number :math:`Z`. Parameters ---------- value : int Atomic number :math:`Z`. """ if not (isinstance(value, numbers.Real) and int(value) > 0): raise ValueError('Expected a real, positive integer.') try: Z = int(value) idx = Z - 1 symbol = element_symbols[idx] m = atomic_masses[symbol] except KeyError: print('unrecognized element number: {}'.format(value)) else: self._Z = atomic_numbers[symbol] self._m = m self._symbol = symbol @property def element(self): """Element symbol. Returns ------- str Symbol of chemical element. """ return self._symbol @element.setter def element(self, value): """Set element symbol.""" if isinstance(value, numbers.Number): try: Z = int(value) idx = Z - 1 symbol = element_symbols[idx] m = atomic_masses[symbol] except KeyError: print('unrecognized element number: {}'.format(value)) else: self._Z = atomic_numbers[symbol] self._m = m else: m = self.m int_half_m = int(m / 2) if value in element_symbols: symbol = value elif value in element_names: symbol = element_symbols[element_names.index(value)] elif m in atomic_mass_symbol_map: symbol = atomic_mass_symbol_map[m] elif int_half_m in atomic_number_symbol_map: symbol = atomic_number_symbol_map[int_half_m] else: symbol = 'X' try: self._Z = atomic_numbers[symbol] self._m = atomic_masses[symbol] except KeyError: self._Z = 0 self._symbol = symbol @property def symbol(self): """Element symbol. Returns ------- str Element symbol. """ return self._symbol @property def m(self): """Atomic mass :math:`m_a` in atomic mass units. Returns ------- float Atomic mass :math:`m_a` in atomic mass units. """ return self._m @m.setter def m(self, value): self._m = value
[docs] def todict(self): """Return `dict` of `Atom` constructor parameters.""" return dict(element=self.element, m=self.m)