Source code for sknano.io._base
# -*- coding: utf-8 -*-
"""
=============================================================================
Base classes for structure data (:mod:`sknano.io._base`)
=============================================================================
.. currentmodule:: sknano.io._base
"""
from __future__ import absolute_import, division, print_function
from __future__ import unicode_literals
__docformat__ = 'restructuredtext en'
from abc import ABCMeta, abstractmethod
from sknano.core import get_fpath
from sknano.core.atoms import StructureAtom as Atom, StructureAtoms as Atoms
from sknano.core.crystallography import StructureData
# from sknano.utils.analysis import StructureAnalyzer
from sknano.version import version
default_comment_line = \
'Structure data generated using scikit-nano version {}'.format(version)
default_structure_format = 'xyz'
supported_structure_formats = ('xyz', 'data', 'dump')
__all__ = ['Atom', 'Atoms',
'StructureIO',
'StructureReader',
'StructureWriter',
'StructureConverter',
'StructureIOError',
'StructureFormatSpec',
'default_comment_line',
'default_structure_format',
'supported_structure_formats']
[docs]class StructureIO(StructureData):
"""Base class for structure data file input and output.
Parameters
----------
fpath : {None, str}, optional
"""
def __init__(self, fpath=None, fname=None, **kwargs):
super().__init__()
self.comment_line = default_comment_line
if fpath is None and fname is not None:
fpath = fname
self.fpath = fpath
self.kwargs = kwargs
@property
def comment_line(self):
"""Comment line."""
return self._comment_line
@comment_line.setter
def comment_line(self, value):
"""Set the comment line string.
Parameters
----------
value : str
"""
if not isinstance(value, str):
raise TypeError('Expected a string.')
self._comment_line = value
@comment_line.deleter
def comment_line(self):
del self._comment_line
def __deepcopy__(self, memo):
from copy import deepcopy
cp = self.__class__(None)
memo[id(self)] = cp
for attr in dir(self):
if not attr.startswith('_'):
setattr(cp, attr, deepcopy(getattr(self, attr), memo))
return cp
[docs]class StructureReader:
"""Structure data reader base class."""
@classmethod
[docs] def read(cls, fpath, structure_format=None, **kwargs):
"""Read structure data from file.
Parameters
----------
fpath : str
structure_format : {None, str}
"""
if (structure_format is None and fpath.endswith('.data')) or \
structure_format == 'data':
from ._lammps_data_format import DATAReader
return DATAReader(fpath, **kwargs)
elif (structure_format is None and fpath.endswith('.dump')) or \
structure_format == 'dump':
from ._lammps_dump_format import DUMPReader
return DUMPReader(fpath, **kwargs)
elif (structure_format is None and fpath.endswith('.xyz')) or \
structure_format == 'xyz':
from ._xyz_format import XYZReader
return XYZReader.read(fpath)
else:
raise StructureIOError("Unable to determine `structure_format`")
[docs]class StructureWriter:
"""Structure data writer base class."""
@classmethod
[docs] def write(cls, fname=None, structure_format=None, **kwargs):
"""Write structure data to file.
Parameters
----------
fname : str, optional
structure_format : {None, str}, optional
"""
if fname is None and structure_format is None:
structure_format = default_structure_format
if fname is None:
fname = get_fpath(fname='structure_data', ext=structure_format,
add_fnum=True)
if (structure_format is None and fname.endswith('.data')) or \
structure_format == 'data':
from ._lammps_data_format import DATAWriter
DATAWriter.write(fname=fname, **kwargs)
elif (structure_format is None and fname.endswith('.dump')) or \
structure_format == 'dump':
from ._lammps_dump_format import DUMPWriter
DUMPWriter.write(fname=fname, **kwargs)
# elif (structure_format is None and fname.endswith('.xyz')) or \
# structure_format == 'xyz':
else:
from ._xyz_format import XYZWriter
XYZWriter.write(fname=fname, **kwargs)
[docs]class StructureConverter(metaclass=ABCMeta):
"""Abstract base class for converting structure data.
Parameters
----------
infile : str
outfile : str
"""
def __init__(self, infile=None, outfile=None, **kwargs):
self.infile = infile
self.outfile = outfile
self.kwargs = kwargs
@abstractmethod
[docs] def convert(self):
"""Convert structure data from one format to another format."""
raise NotImplementedError('Subclasses of `StructureConverter` need '
'to implement the `convert` method.')
[docs]class StructureIOError(Exception):
"""Base class for `StructureIO` errors."""
pass