Source code for aiida_vasp.parsers.content_parsers.stream

"""
The standard stream parser interface for VASP.

----------------------------------------------
Contains the parsing interfaces to ``parsevasp`` used to parse standard streams
for VASP related notification, warnings and errors.
"""
# pylint: disable=abstract-method
import re

from parsevasp.stream import Stream

from aiida_vasp.parsers.content_parsers.base import BaseFileParser


[docs] class StreamParser(BaseFileParser): """Parser used for parsing errors and warnings from VASP.""" DEFAULT_SETTINGS = {'quantities_to_parse': ['notifications']} PARSABLE_QUANTITIES = { 'notifications': { 'inputs': [], 'name': 'notifications', 'prerequisites': [], } } def _init_from_handler(self, handler): """Initialize a ``parsevasp`` object of ``Stream`` using a file like handler. Parameters ---------- handler : object A file like object that provides the necessary standard stream content to be parsed. """ # First get any special config from the parser settings, else use the default stream_config = None history = False if self._settings is not None: stream_config = self._settings.get('stream_config', None) history = self._settings.get('stream_history', False) try: self._content_parser = Stream( file_handler=handler, logger=self._logger, history=history, config=stream_config ) except SystemExit: self._logger.warning('Parsevasp exited abnormally.') @property def notifications(self): """Fetch the notifications that VASP generated. Returns ------- notifications : list A list of all notifications from VASP. Each entry is a dict with the keys ``name``, ``kind``, ``message`` and ``regex`` containing name of the message, what kind it is (``ERROR`` or ``WARNING``), a description of the notification and the regular expression detected as string values. """ # ``parsevasp`` returns ``VaspStream`` objects, which we cannot serialize. We could serialize this, but # eventually, we would like to move to a dedicated node for the notifications with its own data class. # This should be fixed in AiiDA core and coordinated across many plugins. For now, we convert the relevant info # into dict entries explicitly. notifications = [] for item in self._content_parser.entries: if isinstance(item.regex, type(re.compile(''))): regex = item.regex.pattern else: regex = item.regex notifications.append({'name': item.shortname, 'kind': item.kind, 'message': item.message, 'regex': regex}) return notifications @property def errors(self): """Fetch the errors that VASP generated. Returns ------- errors : list A list of all errors from VASP. Each entry is a dict with the keys ``name``, ``kind``, ``message`` and ``regex`` containing name of the message, what kind it is (``ERROR`` or ``WARNING``), a description of the error and the regular expression detected as string values. """ return [item for item in self._content_parser.entries if item.kind == 'ERROR'] @property def warnings(self): """Fetch the warnings that VASP generated. Returns ------- warnings : list A list of all warnings from VASP. Each entry is a dict with the keys ``name``, ``kind``, ``message`` and ``regex`` containing name of the message, what kind it is (``ERROR`` or ``WARNING``), a description of the error and the regular expression detected as string values. """ return [item for item in self._content_parser.entries if item.kind == 'WARNING'] @property def has_entries(self): """Check if there are notifications from VASP present according to the config after parsning. Returns ------- entries : bool ``True`` if notifications was detected, ``False`` otherwise. """ entries = self._content_parser.has_entries return entries @property def number_of_entries(self): """Find the number of unique notifications from VASP. Returns ------- number_of_entries : int The number of unique notification entries that VASP generated. """ number_of_entries = len(self._content_parser) return number_of_entries