def read(cls, source, format=None, **kwargs): """ Class method to read Atoms object from file `source` according to `format` If `format` is None, filetype is inferred from filename. Returns a new Atoms instance; to read into an existing Atoms object, use the read_from() method. If `source` corresponds to a known format then it used to construct an appropriate iterator from the :attr:`AtomsReaders` dictionary. See :ref:`fileformats` for a list of supported file formats. If `source` corresponds to an unknown format then it is expected to be an iterator returning :class:`Atoms` objects. """ if isinstance(source, basestring) and '@' in os.path.basename(source): source, frame = source.split('@') if source.endswith('.db'): source = source + '@' + frame format = 'db' else: frame = parse_slice(frame) if 'frame' in kwargs: raise ValueError( "Conflicting frame references given: kwarg frame=%r and @-reference %r" % (kwargs['frame'], frame)) if not isinstance(frame, int): raise ValueError( "Frame @-reference %r does not resolve to single frame" % frame) kwargs['frame'] = frame from quippy.io import AtomsReaders filename, source, format = infer_format(source, format, AtomsReaders) opened = False if format in AtomsReaders: source = AtomsReaders[format](source, format=format, **kwargs) opened = True if isinstance(source, basestring): raise IOError("Don't know how to read from file '%s'" % source) if not hasattr(source, '__iter__'): raise IOError('Cannot read from %r - not an iterator' % source) at = iter(source).next() if not isinstance(at, cls): raise ValueError('Object %r read from %r is not Atoms instance' % (at, source)) if opened and hasattr(source, 'close'): source.close() if filename is not None: at.filename = filename return at
def write(self, dest=None, format=None, properties=None, prefix=None, progress=False, progress_width=80, update_interval=None, show_value=True, **kwargs): """ Write all frames to `dest`. If `format` is not given it is inferred from the file extension of `dest` (see :ref:`fileformats`). If `properties` is present, it should be a list of property names to include in the output file, e.g. `['species', 'pos']`. `progress`, `progress_width`, `update_interval` and `show_value` are used to control a textual progress bar. The extra arguments in `*args` and `**kwargs` are passed along to the underlying writer routine constructed for writing to `dest`. See :ref:`fileformats` for a list of supported file formats. """ opened = False if dest is None: dest = self.source filename, dest, format = infer_format(dest, format, AtomsWriters) if progress: from progbar import ProgressBar pb = ProgressBar(0,len(self),progress_width,showValue=show_value) update_interval = update_interval or max(1, len(self)/progress_width) if format in AtomsWriters: dest = AtomsWriters[format](dest, **kwargs) if not hasattr(dest, 'write'): raise ValueError("Don't know how to write to destination \"%s\" in format \"%s\"" % (dest, format)) res = [] for i, a in enumerate(self): write_kwargs = {} if properties is not None: write_kwargs['properties'] = properties if prefix is not None: write_kwargs['prefix'] = prefix try: res.append(dest.write(a, **write_kwargs)) except TypeError: raise ValueError('destination does not support specifying arguments %r' % write_kwargs) if progress and i % update_interval == 0: pb(i) if opened: dest.close() # Special case for writing to a string if format == 'string': return ''.join(res) else: if res is not None and not all(el is None for el in res): return res
def write(self, dest=None, format=None, properties=None, prefix=None, **kwargs): """ Write this :class:`Atoms` object to `dest`. If `format` is absent it is inferred from the file extension or type of `dest`, as described for the :meth:`read` method. If `properties` is present, it should be a list of property names to include in the output file, e.g. `['species', 'pos']`. See :ref:`fileformats` for a list of supported file formats. """ if dest is None: # if filename is missing, save back to file from # which we loaded configuration if hasattr(self, 'filename'): dest = self.filename else: raise ValueError("No 'dest' and Atoms has no stored filename") from quippy.io import AtomsWriters filename, dest, format = infer_format(dest, format, AtomsWriters) opened = filename is not None if format in AtomsWriters: dest = AtomsWriters[format](dest, **kwargs) if not hasattr(dest, 'write'): raise ValueError( 'Don\'t know how to write to "%s" in format "%s"' % (dest, format)) write_kwargs = {} if properties is not None: write_kwargs['properties'] = properties if prefix is not None: write_kwargs['prefix'] = prefix try: res = dest.write(self, **write_kwargs) except TypeError: raise ValueError('destination %r doesn\'t support arguments %r' % (dest, write_kwargs)) if opened and hasattr(dest, 'close'): dest.close() return res
def AtomsWriter(dest, format=None, **kwargs): """ Returns a file-like object for writing Atoms to `dest` which should be either a filename or an initiliased output object. If `format` is not given it is inferred from the file extension of `dest`. Example usage:: out = AtomsWriter('out_file.xyz') for at in seq: out.write(at) out.close() """ filename, dest, format = infer_format(dest, format, AtomsWriters) if format in AtomsWriters: writer = AtomsWriters[format](dest, **kwargs) return writer else: raise ValueError("Don't know how to write Atoms to format %r" % format)
def __init__(self, source, format=None, start=None, stop=None, step=None, cache_mem_limit=-1, rename=None, **kwargs): def file_exists(f): return f == "stdin" or os.path.exists(f) or len(glob.glob(f)) > 0 self.source = source self.format = format self._start = start self._stop = stop self._step = step self.cache_mem_limit = cache_mem_limit logging.debug('AtomsReader memory limit %r' % self.cache_mem_limit) self._source_len = None self._cache_dict = {} self._cache_list = [] self._cache_mem_usage = [] self.opened = False self.reader = source self.rename = rename if isinstance(self.reader, basestring): if '@' in self.reader: self.reader, frames = self.reader.split('@') frames = parse_slice(frames) if start is not None or stop is not None or step is not None: raise ValueError( 'Conflicting frame references start=%r stop=%r step=%r and @-sytnax %r' % (start, stop, step, frames)) if isinstance(frames, int): if frames >= 0: frames = slice(frames, frames + 1, +1) else: frames = slice(frames, frames - 1, -1) self._start, self._stop, self._step = frames.start, frames.stop, frames.step self.filename = self.reader self.opened = True if self.reader in AtomsReaders: if format is None: format = self.reader elif format != 'string': self.reader = os.path.expanduser(self.reader) glob_list = sorted(glob.glob(self.reader)) if (len(glob_list) == 0): raise IOError("input file '%s' not found" % self.reader) if len(glob_list) > 1: self.reader = glob_list else: self.reader = glob_list[0] filename, self.reader, new_format = infer_format( self.reader, format, AtomsReaders) if format is None: format = new_format # special cases if source is a list or tuple of filenames or Atoms objects is_filename_sequence = False is_list_of_atoms = False if isinstance(self.reader, list) or isinstance(self.reader, tuple): is_filename_sequence = True is_list_of_atoms = True for item in self.reader: if '@' in item: item = item[:item.index('@')] if not isinstance(item, basestring) or not file_exists(item): is_filename_sequence = False if not isinstance(item, Atoms): is_list_of_atoms = False if is_filename_sequence: self.reader = AtomsSequenceReader(self.reader, format=format, **kwargs) elif is_list_of_atoms: # dummy reader which copies from an existing list or tuple of Atoms objects self.reader = [at.copy() for at in self.reader] else: if format is None: format = self.reader.__class__ if format in AtomsReaders: self.reader = AtomsReaders[format](self.reader, **kwargs) # check if reader is still a string or list of strings - indicates missing files or unknown format if isinstance(self.reader, basestring): raise IOError("Cannot read Atoms from file %s" % self.reader) elif isinstance(self.reader, list): is_list_of_strings = True for item in self.reader: if not isinstance(item, basestring): is_list_of_strings = False break if is_list_of_strings: raise IOError("Cannot read Atoms from files %s" % self.reader) if isinstance(self.reader, AtomsReader): self.reader = AtomsReaderCopier(self.reader) if not hasattr(self.reader, '__iter__'): # call Atoms constructor - this has beneficial side effect of making a copy self.reader = [Atoms(self.reader)]