示例#1
0
def test_empty_log(db_test_app, plugin_name):
    """Check if the lammps log is empty."""
    retrieved = FolderData()
    for filename in [
            'log.lammps',
            'trajectory.lammpstrj',
            '_scheduler-stdout.txt',
            '_scheduler-stderr.txt',
    ]:
        retrieved.put_object_from_filelike(io.StringIO(''), filename)

    calc_node = db_test_app.generate_calcjob_node(plugin_name, retrieved)
    parser = ParserFactory(plugin_name)

    with db_test_app.sandbox_folder() as temp_path:
        with temp_path.open('x-trajectory.lammpstrj', 'w'):
            pass
        results, calcfunction = parser.parse_from_node(  # pylint: disable=unused-variable
            calc_node,
            retrieved_temporary_folder=temp_path.abspath,
        )

    assert calcfunction.is_finished, calcfunction.exception
    assert calcfunction.is_failed, calcfunction.exit_status
    assert (calcfunction.exit_status ==
            calc_node.process_class.exit_codes.ERROR_LOG_PARSING.status)
示例#2
0
def test_stream_history(request, calc_with_retrieved):
    """Test that the stream parser keeps history."""
    file_path = str(
        request.fspath.join('..') + '../../../test_data/stdout/out')

    # turn of everything, except misc
    settings_dict = {
        'parser_settings': {
            'add_trajectory': False,
            'add_bands': False,
            'add_chgcar': False,
            'add_dos': False,
            'add_kpoints': False,
            'add_energies': False,
            'add_misc': ['notifications'],
            'add_structure': False,
            'add_projectors': False,
            'add_born_charges': False,
            'add_dielectrics': False,
            'add_hessian': False,
            'add_dynmat': False,
            'add_wavecar': False,
            'add_site_magnetization': False,
            'stream_config': {
                'random_error': {
                    'kind': 'ERROR',
                    'regex': 'I AM A WELL DEFINED ERROR',
                    'message': 'Okey, this error you do not want.',
                    'suggestion': '',
                    'location': 'STDOUT',
                    'recover': False
                }
            },
            'stream_history': True
        }
    }

    node = calc_with_retrieved(file_path, settings_dict)

    parser_cls = ParserFactory('vasp.vasp')
    result, _ = parser_cls.parse_from_node(
        node, store_provenance=False, retrieved_temporary_folder=file_path)

    misc = result['misc']
    misc_dict = misc.get_dict()
    assert len(misc_dict['notifications']) == 3
    assert misc_dict['notifications'][0]['name'] == 'ibzkpt'
    assert misc_dict['notifications'][0]['kind'] == 'ERROR'
    assert misc_dict['notifications'][0][
        'regex'] == 'internal error in subroutine IBZKPT'
    assert misc_dict['notifications'][1]['name'] == 'random_error'
    assert misc_dict['notifications'][1]['kind'] == 'ERROR'
    assert misc_dict['notifications'][1][
        'regex'] == 'I AM A WELL DEFINED ERROR'
    assert misc_dict['notifications'][2]['name'] == 'random_error'
    assert misc_dict['notifications'][2]['kind'] == 'ERROR'
    assert misc_dict['notifications'][2][
        'regex'] == 'I AM A WELL DEFINED ERROR'
    for item in misc_dict['notifications']:
        assert item['kind'] != 'WARNING'
示例#3
0
def test_parser_nodes(request, calc_with_retrieved):
    """Test a few basic node items of the parser."""
    from aiida.plugins import ParserFactory

    settings_dict = {
        'parser_settings': {
            'add_bands': True,
            'add_kpoints': True,
            'add_misc': ['fermi_level']
        }
    }

    file_path = str(request.fspath.join('..') + '../../../test_data/basic')

    node = calc_with_retrieved(file_path, settings_dict)

    parser_cls = ParserFactory('vasp.vasp')
    result, _ = parser_cls.parse_from_node(
        node, store_provenance=False, retrieved_temporary_folder=file_path)

    misc = result['misc']
    bands = result['bands']
    kpoints = result['kpoints']

    assert isinstance(misc, get_data_class('dict'))
    assert isinstance(bands, get_data_class('array.bands'))
    assert isinstance(kpoints, get_data_class('array.kpoints'))
    assert misc.get_dict()['fermi_level'] == 5.96764939
示例#4
0
def test_misc(request, calc_with_retrieved):
    """Test that it is possible to extract misc from both vasprun and OUTCAR."""
    # turn of everything, except misc
    settings_dict = {
        'parser_settings': {
            'add_trajectory':
            False,
            'add_bands':
            False,
            'add_chgcar':
            False,
            'add_dos':
            False,
            'add_kpoints':
            False,
            'add_energies':
            False,
            'add_misc': [
                'fermi_level', 'maximum_stress', 'maximum_force',
                'total_energies', 'symmetries'
            ],
            'add_structure':
            False,
            'add_projectors':
            False,
            'add_born_charges':
            False,
            'add_dielectrics':
            False,
            'add_hessian':
            False,
            'add_dynmat':
            False,
            'add_wavecar':
            False,
            'add_site_magnetization':
            False,
        }
    }

    file_path = str(
        request.fspath.join('..') + '../../../test_data/disp_details')

    node = calc_with_retrieved(file_path, settings_dict)

    parser_cls = ParserFactory('vasp.vasp')
    result, _ = parser_cls.parse_from_node(
        node, store_provenance=False, retrieved_temporary_folder=file_path)

    misc = result['misc']
    assert isinstance(misc, get_data_class('dict'))
    data = misc.get_dict()
    # We already have a test to check if the quantities from the OUTCAR is correct, so
    # only perform rudimentary checks, and the content comming from the xml file.
    assert data['fermi_level'] == 6.17267267
    assert data['maximum_stress'] == 42.96872956444064
    assert data['maximum_force'] == 0.21326679
    assert data['total_energies']['energy_extrapolated'] == -10.823296
示例#5
0
 def _generate_parser(entry_point_name):
     """Fixture to load a parser class for testing parsers.
     :param entry_point_name: entry point name of the parser class
     :return: the `Parser` sub class
     """
     from aiida.plugins import ParserFactory
     return ParserFactory(entry_point_name)
示例#6
0
def test_missing_log(db_test_app, plugin_name):
    """Check if the log file is produced during calculation."""
    retrieved = FolderData()

    calc_node = db_test_app.generate_calcjob_node(plugin_name, retrieved)
    parser = ParserFactory(plugin_name)
    with db_test_app.sandbox_folder() as temp_path:
        results, calcfunction = parser.parse_from_node(  # pylint: disable=unused-variable
            calc_node,
            retrieved_temporary_folder=temp_path.abspath,
        )

    assert calcfunction.is_finished, calcfunction.exception
    assert calcfunction.is_failed, calcfunction.exit_status
    assert (calcfunction.exit_status ==
            calc_node.process_class.exit_codes.ERROR_LOG_FILE_MISSING.status)
示例#7
0
def _pop_parser_options(calc_job_instance, settings_dict, ignore_errors=True):
    """This deletes any parser options from the settings dictionary. The parser options key is found
    via the get_parser_settings_key() method of the parser class specified as a metadata input."""
    from aiida.plugins import ParserFactory
    from aiida.common import EntryPointError
    try:
        parser_name = calc_job_instance.inputs['metadata']['options']['parser_name']
        ParserClass = ParserFactory(parser_name)
        parser_opts_key = ParserClass.get_parser_settings_key().upper()
        return settings_dict.pop(parser_opts_key, None)
    except (KeyError, EntryPointError, AttributeError) as exc:
        # KeyError: input 'metadata.options.parser_name' is not defined;
        # EntryPointError: there was an error loading the parser class form its entry point
        #   (this will probably cause errors elsewhere too);
        # AttributeError: the parser class doesn't have a method get_parser_settings_key().
        if ignore_errors:
            pass
        else:
            raise exc
示例#8
0
    def parse_from_node(entry_point_name, node, retrieved_temp=None):
        """Parse the outputs directly from the `CalcJobNode`.

        Parameters
        ----------
        entry_point_name : str
            entry point name of the parser class

        """
        return ParserFactory(entry_point_name).parse_from_node(
            node, retrieved_temporary_folder=retrieved_temp)
示例#9
0
def vasp_parser_with_test(calc_with_retrieved):
    """Fixture providing a VaspParser instance coupled to a VaspCalculation."""
    parser, file_path, node = _get_vasp_parser(calc_with_retrieved)
    parser.add_parser_definition('_scheduler-stderr.txt', {
        'parser_class': ExampleFileParser,
        'is_critical': False
    })
    success = parser.parse(retrieved_temporary_folder=file_path)
    try:
        yield parser
    finally:
        parser = ParserFactory('vasp.vasp')(node)
示例#10
0
def validate_parser(parser_name, ctx):
    """Validate the parser.

    :raises InputValidationError: if the parser name does not correspond to a loadable `Parser` class.
    """
    from aiida.plugins import ParserFactory

    if parser_name is not plumpy.UNSPECIFIED:
        try:
            ParserFactory(parser_name)
        except exceptions.EntryPointError as exception:
            raise exceptions.InputValidationError('invalid parser specified: {}'.format(exception))
示例#11
0
def validate_parser(parser_name, _):
    """Validate the parser.

    :return: string with error message in case the inputs are invalid
    """
    from aiida.plugins import ParserFactory

    if parser_name is not plumpy.UNSPECIFIED:
        try:
            ParserFactory(parser_name)
        except exceptions.EntryPointError as exception:
            return 'invalid parser specified: {}'.format(exception)
示例#12
0
def test_missing_traj(db_test_app, plugin_name):
    """Check if the trajectory file is produced during calculation."""
    retrieved = FolderData()
    retrieved.put_object_from_filelike(io.StringIO(get_log()), 'log.lammps')
    retrieved.put_object_from_filelike(io.StringIO(''),
                                       '_scheduler-stdout.txt')
    retrieved.put_object_from_filelike(io.StringIO(''),
                                       '_scheduler-stderr.txt')

    calc_node = db_test_app.generate_calcjob_node(plugin_name, retrieved)
    parser = ParserFactory(plugin_name)
    with db_test_app.sandbox_folder() as temp_path:
        results, calcfunction = parser.parse_from_node(  # pylint: disable=unused-variable
            calc_node,
            retrieved_temporary_folder=temp_path.abspath,
        )

    assert calcfunction.is_finished, calcfunction.exception
    assert calcfunction.is_failed, calcfunction.exit_status
    assert (calcfunction.exit_status ==
            calc_node.process_class.exit_codes.ERROR_TRAJ_FILE_MISSING.status)
示例#13
0
def validate_parser(parser_name: Any, _: Any) -> Optional[str]:
    """Validate the parser.

    :return: string with error message in case the inputs are invalid
    """
    from aiida.plugins import ParserFactory

    try:
        ParserFactory(parser_name)
    except exceptions.EntryPointError as exception:
        return f'invalid parser specified: {exception}'

    return None
示例#14
0
    def parse_from_node(entry_point_name, node, retrieved_temp=None):
        """Parse the outputs directly from the `CalcJobNode`.

        Parameters
        ----------
        entry_point_name : str
            entry point name of the parser class

        """
        from aiida.plugins import ParserFactory

        return parse_from_node(
            ParserFactory(entry_point_name), node, retrieved_temp=retrieved_temp
        )
示例#15
0
    def get_parser_class(self):
        """Return the output parser object for this calculation or None if no parser is set.

        :return: a `Parser` class.
        :raises `aiida.common.exceptions.EntryPointError`: if the parser entry point can not be resolved.
        """
        from aiida.plugins import ParserFactory

        parser_name = self.get_option('parser_name')

        if parser_name is not None:
            return ParserFactory(parser_name)

        return None
示例#16
0
def test_run_error(db_test_app, plugin_name):
    """Check if the parser runs without producing errors."""
    retrieved = FolderData()
    retrieved.put_object_from_filelike(
        io.StringIO(get_log()),
        'log.lammps',
    )
    retrieved.put_object_from_filelike(
        io.StringIO(get_traj_force()),
        'x-trajectory.lammpstrj',
    )
    retrieved.put_object_from_filelike(
        io.StringIO('ERROR description'),
        '_scheduler-stdout.txt',
    )
    retrieved.put_object_from_filelike(
        io.StringIO(''),
        '_scheduler-stderr.txt',
    )

    calc_node = db_test_app.generate_calcjob_node(plugin_name, retrieved)
    parser = ParserFactory(plugin_name)

    with db_test_app.sandbox_folder() as temp_path:
        with temp_path.open('x-trajectory.lammpstrj', 'w') as handle:
            handle.write(get_traj_force())
        results, calcfunction = parser.parse_from_node(  # pylint: disable=unused-variable
            calc_node,
            retrieved_temporary_folder=temp_path.abspath,
        )

    print(get_calcjob_report(calc_node))

    assert calcfunction.is_finished, calcfunction.exception
    assert calcfunction.is_failed, calcfunction.exit_status
    assert (calcfunction.exit_status ==
            calc_node.process_class.exit_codes.ERROR_LAMMPS_RUN.status)
示例#17
0
    def get_parser_cls(entry_point_name):
        """load a parser class

        Parameters
        ----------
        entry_point_name : str
            entry point name of the parser class

        Returns
        -------
        aiida.parsers.parser.Parser

        """

        return ParserFactory(entry_point_name)
示例#18
0
def vasp_parser_with_test(calc_with_retrieved):
    """Fixture providing a VaspParser instance coupled to a VaspCalculation."""
    from aiida.plugins import ParserFactory
    from aiida.plugins import CalculationFactory

    settings_dict = {
        # 'ADDITIONAL_RETRIEVE_LIST': CalculationFactory('vasp.vasp')._ALWAYS_RETRIEVE_LIST,
        'parser_settings': {
            'add_custom': {
                'link_name': 'custom_node',
                'type': 'dict',
                'quantities': ['quantity2', 'quantity_with_alternatives']
            }
        }
    }

    file_path = str(
        os.path.abspath(os.path.dirname(__file__)) +
        '/../../test_data/test_relax_wc/out')

    node = calc_with_retrieved(file_path, settings_dict)

    parser = ParserFactory('vasp.vasp')(node)
    parser.add_file_parser('_scheduler-stderr.txt', {
        'parser_class': ExampleFileParser,
        'is_critical': False
    })
    parser.add_parsable_quantity(
        'quantity_with_alternatives',
        {
            'inputs': [],
            'prerequisites': [],
        },
    )
    success = parser.parse(retrieved_temporary_folder=file_path)
    try:
        yield parser
    finally:
        parser = ParserFactory('vasp.vasp')(node)
示例#19
0
def _get_vasp_parser(calc_with_retrieved):
    """Return vasp parser before parsing"""
    settings_dict = {
        # 'ADDITIONAL_RETRIEVE_LIST': CalculationFactory('vasp.vasp')._ALWAYS_RETRIEVE_LIST,
        'parser_settings': {
            'add_custom': {
                'link_name': 'custom_node',
                'type': 'dict',
                'quantities': ['quantity2', 'quantity_with_alternatives']
            }
        }
    }
    file_path = str(
        os.path.abspath(os.path.dirname(__file__)) +
        '/../../test_data/basic_run')
    node = calc_with_retrieved(file_path, settings_dict)
    parser = ParserFactory('vasp.vasp')(node)
    return parser, file_path, node
示例#20
0
 def _generate_parser(entry_point_name):
     return ParserFactory(entry_point_name)
示例#21
0
def test_structure(request, calc_with_retrieved):
    """Test that the structure from vasprun and POSCAR is the same."""
    from aiida.plugins import ParserFactory

    # turn of everything, except structure
    settings_dict = {
        'parser_settings': {
            'add_trajectory': False,
            'add_bands': False,
            'add_chgcar': False,
            'add_dos': False,
            'add_kpoints': False,
            'add_energies': False,
            'add_misc': False,
            'add_structure': True,
            'add_projectors': False,
            'add_born_charges': False,
            'add_dielectrics': False,
            'add_hessian': False,
            'add_dynmat': False,
            'add_wavecar': False,
            'add_site_magnetization': False,
            'file_parser_set': 'default'
        }
    }

    file_path = str(request.fspath.join('..') + '../../../test_data/basic')

    node = calc_with_retrieved(file_path, settings_dict)

    parser_cls = ParserFactory('vasp.vasp')
    result, _ = parser_cls.parse_from_node(
        node, store_provenance=False, retrieved_temporary_folder=file_path)

    # First fetch structure from vasprun

    structure_vasprun = result['structure']
    assert isinstance(structure_vasprun, get_data_class('structure'))

    # Then from POSCAR/CONTCAR
    file_path = str(
        request.fspath.join('..') + '../../../test_data/basic_poscar')

    node = calc_with_retrieved(file_path, settings_dict)

    parser_cls = ParserFactory('vasp.vasp')
    result, _ = parser_cls.parse_from_node(
        node, store_provenance=False, retrieved_temporary_folder=file_path)

    structure_poscar = result['structure']

    assert isinstance(structure_poscar, get_data_class('structure'))
    assert np.array_equal(np.round(structure_vasprun.cell, 7),
                          np.round(structure_poscar.cell, 7))
    positions_vasprun = []
    positions_poscar = []
    for site in structure_vasprun.sites:
        pos = np.round(np.asarray(site.position), 7)
        positions_vasprun.append(pos)
    for site in structure_poscar.sites:
        pos = np.round(np.asarray(site.position), 7)
        positions_poscar.append(pos)
    positions_vasprun = np.asarray(positions_vasprun)
    positions_poscar = np.asarray(positions_poscar)
    assert np.array_equal(positions_vasprun, positions_poscar)
示例#22
0
def test_stream(misc_input, config, request, calc_with_retrieved):
    """Test that the stream parser works and gets stored on a node."""
    file_path = str(
        request.fspath.join('..') + '../../../test_data/stdout/out')

    # turn of everything, except misc
    settings_dict = {
        'parser_settings': {
            'add_trajectory': False,
            'add_bands': False,
            'add_chgcar': False,
            'add_dos': False,
            'add_kpoints': False,
            'add_energies': False,
            'add_misc': misc_input,
            'add_structure': False,
            'add_projectors': False,
            'add_born_charges': False,
            'add_dielectrics': False,
            'add_hessian': False,
            'add_dynmat': False,
            'add_wavecar': False,
            'add_site_magnetization': False,
            'stream_config': config
        }
    }

    node = calc_with_retrieved(file_path, settings_dict)

    parser_cls = ParserFactory('vasp.vasp')
    result, _ = parser_cls.parse_from_node(
        node, store_provenance=False, retrieved_temporary_folder=file_path)

    if misc_input == []:
        # Test empty misc specification, yields no misc output node
        with pytest.raises(KeyError) as error:
            misc = result['misc']
    else:
        misc = result['misc']
        misc_dict = misc.get_dict()
        if config is not None:
            if 'random_error' in config:
                assert len(misc_dict['notifications']) == 2
                assert misc_dict['notifications'][0]['name'] == 'ibzkpt'
                assert misc_dict['notifications'][0]['kind'] == 'ERROR'
                assert misc_dict['notifications'][0][
                    'regex'] == 'internal error in subroutine IBZKPT'
                assert misc_dict['notifications'][1]['name'] == 'random_error'
                assert misc_dict['notifications'][1]['kind'] == 'ERROR'
                assert misc_dict['notifications'][1][
                    'regex'] == 'I AM A WELL DEFINED ERROR'
            if 'random_warning' in config:
                assert len(misc_dict['notifications']) == 2
                assert misc_dict['notifications'][0]['name'] == 'ibzkpt'
                assert misc_dict['notifications'][0]['kind'] == 'ERROR'
                assert misc_dict['notifications'][0][
                    'regex'] == 'internal error in subroutine IBZKPT'
                assert misc_dict['notifications'][1][
                    'name'] == 'random_warning'
                assert misc_dict['notifications'][1]['kind'] == 'WARNING'
                assert misc_dict['notifications'][1][
                    'regex'] == 'I AM A WELL DEFINED WARNING'
        else:
            assert len(misc_dict['notifications']) == 1
            assert misc_dict['notifications'][0]['name'] == 'ibzkpt'
            assert misc_dict['notifications'][0]['kind'] == 'ERROR'
            assert misc_dict['notifications'][0][
                'regex'] == 'internal error in subroutine IBZKPT'
示例#23
0
    def test_kkrimp_parser_entry_point(self):
        from aiida.plugins import ParserFactory
        from aiida_kkr.parsers.kkrimp import KkrimpParser

        parser = ParserFactory('kkr.kkrimpparser')
        assert parser == KkrimpParser
示例#24
0
"""Test for the `Parser` base class."""
from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

import io

from aiida import orm
from aiida.backends.testbase import AiidaTestCase
from aiida.common import LinkType
from aiida.engine import CalcJob
from aiida.parsers import Parser
from aiida.plugins import CalculationFactory, ParserFactory

ArithmeticAddCalculation = CalculationFactory('arithmetic.add')  # pylint: disable=invalid-name
ArithmeticAddParser = ParserFactory('arithmetic.add')  # pylint: disable=invalid-name


class CustomCalcJob(CalcJob):
    """`CalcJob` implementation with output namespace and additional output node that should be passed to parser."""
    @classmethod
    def define(cls, spec):
        super(CustomCalcJob, cls).define(spec)
        spec.input('inp', valid_type=orm.Data)
        spec.output('output', pass_to_parser=True)
        spec.output_namespace('out.space', dynamic=True)

    def prepare_for_submission(self):  # pylint: disable=arguments-differ
        pass

示例#25
0
def validate_calc_job(inputs):
    """Validate the entire set of inputs passed to the `CalcJob` constructor.

    Reasons that will cause this validation to raise an `InputValidationError`:

     * No `Computer` has been specified, neither directly in `metadata.computer` nor indirectly through the `Code` input
     * The specified computer is not stored
     * The `Computer` specified in `metadata.computer` is not the same as that of the specified `Code`
     * The `metadata.options.parser_name` does not correspond to a loadable `Parser` class.
     * The `metadata.options.resources` are invalid for the `Scheduler` of the specified `Computer`.

    :raises `~aiida.common.exceptions.InputValidationError`: if inputs are invalid
    """
    from aiida.plugins import ParserFactory

    code = inputs['code']
    computer_from_code = code.computer
    computer_from_metadata = inputs['metadata'].get('computer', None)

    if not computer_from_code and not computer_from_metadata:
        raise exceptions.InputValidationError(
            'no computer has been specified in `metadata.computer` nor via `code`.'
        )

    if computer_from_code and not computer_from_code.is_stored:
        raise exceptions.InputValidationError(
            'the Computer<{}> is not stored'.format(computer_from_code))

    if computer_from_metadata and not computer_from_metadata.is_stored:
        raise exceptions.InputValidationError(
            'the Computer<{}> is not stored'.format(computer_from_metadata))

    if computer_from_code and computer_from_metadata and computer_from_code.uuid != computer_from_metadata.uuid:
        raise exceptions.InputValidationError(
            'Computer<{}> explicitly defined in `metadata.computer is different from '
            'Computer<{}> which is the computer of Code<{}> defined as the `code` input.'
            .format(computer_from_metadata, computer_from_code, code))

    # At this point at least one computer is defined and if both they are the same so we just pick one
    computer = computer_from_metadata if computer_from_metadata else computer_from_code

    options = inputs['metadata'].get('options', {})
    parser_name = options.get('parser_name', None)
    resources = options.get('resources', None)

    if parser_name is not None:
        try:
            ParserFactory(parser_name)
        except exceptions.EntryPointError as exception:
            raise exceptions.InputValidationError(
                'invalid parser specified: {}'.format(exception))

    scheduler = computer.get_scheduler()  # pylint: disable=no-member
    def_cpus_machine = computer.get_default_mpiprocs_per_machine()  # pylint: disable=no-member

    if def_cpus_machine is not None:
        resources['default_mpiprocs_per_machine'] = def_cpus_machine

    try:
        scheduler.create_job_resource(**resources)
    except (TypeError, ValueError) as exception:
        raise exceptions.InputValidationError(
            'invalid resources for the scheduler of the specified computer<{}>: {}'
            .format(computer, exception))
def test_siesta_parser_entry_point():
    from aiida.plugins import ParserFactory
    siesta_parser = ParserFactory('siesta.parser')
    assert siesta_parser is not None
示例#27
0
    def test_fleur_parser_entry_point(self):
        from aiida.plugins import ParserFactory
        from aiida_fleur.parsers.fleur import FleurParser

        parser = ParserFactory('fleur.fleurparser')
        assert parser == FleurParser
示例#28
0
    def test_voronoi_parser_entry_point(self):
        from aiida.plugins import ParserFactory
        from aiida_kkr.parsers.voro import VoronoiParser

        parser = ParserFactory('kkr.voroparser')
        assert parser == VoronoiParser