Source code for sknano.core.atoms._poav_atoms

# -*- coding: utf-8 -*-
"""
===============================================================================
Atoms class for POAV analysis (:mod:`sknano.core.atoms._poav_atoms`)
===============================================================================

An `Atoms` class for POAV analysis

.. currentmodule:: sknano.core.atoms._poav_atoms

"""
from __future__ import absolute_import, division, print_function
import six
from six.moves import zip
__docformat__ = 'restructuredtext en'

#import importlib
import numpy as np

from sknano.core.math import vector as vec
from ._kdtree_atoms import KDTAtoms
from ._poav_atom import POAV1, POAV2, POAVR

__all__ = ['POAVAtoms']


[docs]class POAVAtoms(KDTAtoms): """An `Atoms` sub-class for POAV analysis. Sub-class of `KDTAtoms` class, and a container class for lists of :class:`~sknano.core.atoms.POAVAtom` instances. Parameters ---------- atoms : {None, sequence, `POAVAtoms`}, optional if not `None`, then a list of `POAVAtom` instance objects or an existing `POAVAtoms` instance object. copylist : bool, optional perform shallow copy of atoms list deepcopy : bool, optional perform deepcopy of atoms list """ _atomattrs = KDTAtoms._atomattrs + ['POAV1', 'POAV2', 'POAVR'] def __init__(self, atoms=None, copylist=True, deepcopy=False): super(POAVAtoms, self).__init__(atoms=atoms, copylist=copylist, deepcopy=deepcopy)
[docs] def compute_POAVs(self): """Compute `POAV1`, `POAV2`, `POAVR`.""" super(POAVAtoms, self).update_attrs() POAV_classes = {'POAV1': POAV1, 'POAV2': POAV2, 'POAVR': POAVR} for atom in self: # the central atom must have 3 bonds for POAV analysis. if atom.bonds.Nbonds == 3: for POAV_name, POAV_class in six.iteritems(POAV_classes): setattr(atom, POAV_name, POAV_class(atom.bonds)) for atom in self: # the central atom must have 3 bonds for POAV analysis. if atom.bonds.Nbonds == 3: for POAV_name in ('POAV1', 'POAV2', 'POAVR'): POAV = getattr(atom, POAV_name) sigma_pi_angles = [] pyramidalization_angles = [] misalignment_angles = [] for bond, NN in zip(atom.bonds, atom.NN): # first compute the pyramidalization angle sigma_pi_angle = vec.angle(POAV.Vpi, bond.vector) if sigma_pi_angle < np.pi / 2: sigma_pi_angle = np.pi - sigma_pi_angle sigma_pi_angles.append(sigma_pi_angle) pyramidalization_angles.append( sigma_pi_angle - np.pi / 2) # the bonded atom must have a POAV to compute the # misalignment angles if getattr(NN, POAV_name) is not None: NN_POAV = getattr(NN, POAV_name) # compute vector that is orthogonal to the plane # defined by the bond vector and the POAV of the # center atom. nvec = vec.cross(bond.vector, POAV.Vpi) # the misalignment angle is the angle between the # nearest neighbor's POAV and the plane defined by # the bond vector and the POAV of the center atom, # which is pi/2 minus the angle between # the NN POAV and the normal vector to the plane # computed above. misalignment_angles.append(np.abs( np.pi / 2 - vec.angle(NN_POAV.Vpi, nvec))) else: misalignment_angles.append(np.nan) POAV.pyramidalization_angles = pyramidalization_angles POAV.misalignment_angles = misalignment_angles POAV.sigma_pi_angles = sigma_pi_angles
[docs] def update_attrs(self): """Alisas for :meth:`POAVAtoms.compute_POAVs`""" self.compute_POAVs()
@property def POAV1(self): """List of :class:`~sknano.core.atoms.POAVAtom` :class:`POAV1` \ :attr:`~sknano.core.atoms.POAVAtom.POAV1` attribute.""" return [atom.POAV1 for atom in self if atom.POAV1 is not None] @property def POAV2(self): """List of :class:`~sknano.core.atoms.POAVAtom` :class:`POAV2` \ :attr:`~sknano.core.atoms.POAVAtom.POAV2` attribute.""" return [atom.POAV2 for atom in self if atom.POAV2 is not None] @property def POAVR(self): """List of :class:`~sknano.core.atoms.POAVAtom` :class:`POAVR` \ :attr:`~sknano.core.atoms.POAVAtom.POAVR` attribute.""" return [atom.POAVR for atom in self if atom.POAVR is not None]
[docs] def get_POAV_attr(self, POAV_class, attr): """Return list of :class:`~sknano.core.atoms.POAVAtom` :class:`POAV1` \ :class:`POAV2` or :class:`POAVR` attribute. Parameters ---------- POAV_class : :class:`~python:str` attr : :class:`~python:str` Returns ------- :class:`~python:list` """ return [getattr(getattr(atom, POAV_class), attr) for atom in self if getattr(atom, POAV_class) is not None]