Source code for sknano.generators._base

# -*- coding: utf-8 -*-
"""
===============================================================================
Structure generator base module (:mod:`sknano.generators._base`)
===============================================================================

.. currentmodule:: sknano.generators._base

"""
from __future__ import absolute_import, division, print_function
from __future__ import unicode_literals
__docformat__ = 'restructuredtext en'

# from abc import ABCMeta, abstractmethod

import copy
import os

from sknano.core.atoms import StructureAtom as Atom, StructureAtoms as Atoms
from sknano.io import default_structure_format, supported_structure_formats

__all__ = ['Atom', 'Atoms', 'GeneratorBase', 'BulkGeneratorBase',
           'STRUCTURE_GENERATORS']


#: Tuple of structure generator classes.
STRUCTURE_GENERATORS = ('FullereneGenerator',
                        'GrapheneGenerator',
                        'PrimitiveCellGrapheneGenerator',
                        'ConventionalCellGrapheneGenerator',
                        'BilayerGrapheneGenerator',
                        'UnrolledSWNTGenerator',
                        'SWNTGenerator',
                        'SWNTBundleGenerator',
                        'MWNTGenerator',
                        'MWNTBundleGenerator',
                        'AlphaQuartzGenerator',
                        'DiamondStructureGenerator',
                        'FCCStructureGenerator',
                        'GoldGenerator',
                        'CopperGenerator',
                        'CaesiumChlorideStructureGenerator',
                        'RocksaltStructureGenerator',
                        'ZincblendeStructureGenerator',
                        'MoS2Generator')


[docs]class GeneratorBase: """Base structure generator class.""" def __init__(self, *args, autogen=True, **kwargs): super().__init__(*args, **kwargs) if autogen: self.generate()
[docs] def generate(self): """Common :meth:`~GeneratorBase.generate` method structure \ generators.""" self.structure_data.clear() for atom in self.crystal_cell: self.atoms.append(Atom(**atom.todict()))
[docs] def save(self, fname=None, outpath=None, structure_format=None, deepcopy=True, center_centroid=True, center_com=False, region_bounds=None, filter_condition=None, rotation_parameters=None, **kwargs): """Save structure data. Parameters ---------- fname : {None, str}, optional file name string outpath : str, optional Output path for structure data file. structure_format : {None, str}, optional chemical file format of saved structure data. Must be one of: - `xyz` - `data` If `None`, then guess based on `fname` file extension or default to `xyz` format. center_centroid : bool, optional Center centroid on origin. center_com : bool, optional Center center-of-mass on origin. region_bounds : :class:`GeometricRegion`, optional An instance of a :class:`~sknano.core.geometric_regions.GeometricRegion` having a method :meth:`~sknano.core.geometric_regions.GeometricRegion.contains` to filter the atoms not contained within the `GeometricRegion`. filter_condition : array_like, optional """ if fname.endswith(supported_structure_formats) and \ structure_format is None: for ext in supported_structure_formats: if fname.endswith(ext): structure_format = ext break elif structure_format is None or \ structure_format not in supported_structure_formats or \ (not fname.endswith(supported_structure_formats) and structure_format not in supported_structure_formats): structure_format = default_structure_format if not fname.endswith(structure_format): fname += '.' + structure_format self.fname = fname if outpath is not None: fpath = os.path.join(outpath, fname) else: fpath = os.path.join(os.getcwd(), fname) self.fpath = fpath # self._structure_format = structure_format if deepcopy: atoms = copy.deepcopy(self.atoms) else: atoms = self.atoms[:] if any([kw in kwargs for kw in ('center_CM', 'center_center_of_mass')]): if 'center_CM' in kwargs: center_com = kwargs['center_CM'] del kwargs['center_CM'] else: center_com = kwargs['center_center_of_mass'] del kwargs['center_center_of_mass'] if center_centroid: atoms.center_centroid() elif center_com: atoms.center_com() if region_bounds is not None: atoms.clip_bounds(region_bounds) if filter_condition is not None: atoms.filter(filter_condition) # atoms = atoms.filtered(filter_condition) rotation_kwargs = ['rotation_angle', 'angle', 'rot_axis', 'axis', 'anchor_point', 'deg2rad', 'degrees', 'rot_point', 'from_vector', 'to_vector', 'transform_matrix'] if rotation_parameters is None and \ any([kw in kwargs for kw in rotation_kwargs]): rotation_parameters = {kw: kwargs[kw] for kw in rotation_kwargs if kw in kwargs} if 'rotation_angle' in rotation_parameters: rotation_parameters['angle'] = \ rotation_parameters['rotation_angle'] del rotation_parameters['rotation_angle'] if 'rot_axis' in rotation_parameters: rotation_parameters['axis'] = rotation_parameters['rot_axis'] del rotation_parameters['rot_axis'] if 'deg2rad' in rotation_parameters: rotation_parameters['degrees'] = rotation_parameters['deg2rad'] del rotation_parameters['deg2rad'] kwargs = {k: v for k, v in kwargs.items() if k not in rotation_kwargs} if rotation_parameters is not None and \ isinstance(rotation_parameters, dict): self.rotate(**rotation_parameters) getattr(self, 'write_' + structure_format)( fname=fname, outpath=outpath, structure=self, **kwargs)
# StructureWriter.write(fname=fname, outpath=outpath, # structure_format=structure_format, # structure=self.structure)
[docs]class BulkGeneratorBase(GeneratorBase): """Base class for the *bulk structure generator* classes."""
[docs] def save(self, fname=None, scaling_matrix=None, **kwargs): if fname is not None: if scaling_matrix is not None: fname = '_'.join((fname, 'x'.join(map(str, scaling_matrix)))) super().save(fname=fname, **kwargs)