Source code for sknano.core.atoms.cn_atoms

# -*- coding: utf-8 -*-
"""
===============================================================================
Atom classes with a coordination number (:mod:`sknano.core.atoms.cn_atoms`)
===============================================================================

.. currentmodule:: sknano.core.atoms.cn_atoms

"""
from __future__ import absolute_import, division, print_function
from __future__ import unicode_literals

__docformat__ = 'restructuredtext en'

from collections import Counter
from operator import attrgetter
import numbers

import numpy as np

from .atoms import Atom, Atoms

__all__ = ['CNAtom', 'CNAtoms']


[docs]class CNAtom(Atom): """An `Atom` class with a coordination number attribute. Parameters ---------- CN : {int}, optional Coordination number. """ def __init__(self, *args, CN=0, **kwargs): super().__init__(*args, **kwargs) self.CN = CN self.fmtstr = super().fmtstr + ", CN={CN!r}" # def __eq__(self, other): # return np.allclose(self.CN, other.CN) and super().__eq__(other) # def __lt__(self, other): # return (self.CN < other.CN and super().__le__(other)) or \ # (self.CN <= other.CN and super().__lt__(other)) def __eq__(self, other): if not self._is_valid_operand(other): return NotImplemented return np.allclose(self.CN, other.CN) and super().__eq__(other) def __le__(self, other): if not self._is_valid_operand(other): return NotImplemented if self.CN > other.CN or not super().__le__(other): return False return True def __lt__(self, other): if not self._is_valid_operand(other): return NotImplemented if self.CN >= other.CN or not super().__lt__(other): return False return True def __ge__(self, other): if not self._is_valid_operand(other): return NotImplemented if self.CN < other.CN or not super().__ge__(other): return False return True def __gt__(self, other): if not self._is_valid_operand(other): return NotImplemented if self.CN <= other.CN or not super().__gt__(other): return False return True def __dir__(self): attrs = super().__dir__() attrs.append('CN') return attrs @property def CN(self): """Return `CNAtom` coordination number.""" return self._CN @CN.setter def CN(self, value): """Set `CNAtom` coordination number.""" if not isinstance(value, numbers.Number): raise TypeError('Expected a number.') self._CN = int(value)
[docs] def todict(self): """Return :class:`~python:dict` of :class:`CNAtom` constructor \ parameters.""" super_dict = super().todict() super_dict.update(dict(CN=self.CN)) return super_dict
[docs]class CNAtoms(Atoms): """An `Atoms` sub-class for `CNAtom`\ s. A container class for :class:`~sknano.core.atoms.CNAtom` objects. Parameters ---------- atoms : {None, sequence, `CNAtoms`}, optional if not `None`, then a list of `CNAtom` instance objects or an existing `CNAtoms` instance object. """ @property def __atom_class__(self): return CNAtom def sort(self, key=attrgetter('CN'), reverse=False): super().sort(key=key, reverse=reverse) @property def coordination_numbers(self): """:class:`~numpy:numpy.ndarray` of :attr:`CNAtom.CN`\ s.""" return np.asarray([atom.CN for atom in self]) @property def coordination_number_counts(self): """Coordination number counts. Returns ------- :class:`~python:collections.Counter` :class:`~python:collections.Counter` of :attr:`~CNAtoms.coordination_numbers`. """ return Counter(self.coordination_numbers) @property def coordination_counts(self): """Alias for :attr:`~CNAtoms.coordination_number_counts`.""" return self.coordination_number_counts @property def CN_counts(self): """Alias for :attr:`~CNAtoms.coordination_number_counts`.""" return self.coordination_number_counts