diff --git a/aiida_cp2k/parsers/__init__.py b/aiida_cp2k/parsers/__init__.py index 26e133d..4cea789 100644 --- a/aiida_cp2k/parsers/__init__.py +++ b/aiida_cp2k/parsers/__init__.py @@ -6,23 +6,16 @@ ############################################################################### """AiiDA-CP2K output parser.""" -from aiida.common import exceptions -from aiida.engine import ExitCode -from aiida.orm import Dict +import ase +from aiida import common, engine, orm, parsers, plugins -# + -from aiida.parsers import Parser -from aiida.plugins import DataFactory +from .. import utils -from aiida_cp2k import utils +StructureData = plugins.DataFactory("core.structure") +BandsData = plugins.DataFactory("core.array.bands") -# - -StructureData = DataFactory("core.structure") -BandsData = DataFactory("core.array.bands") - - -class Cp2kBaseParser(Parser): +class Cp2kBaseParser(parsers.Parser): """Basic AiiDA parser for the output of CP2K.""" def parse(self, **kwargs): @@ -30,23 +23,24 @@ def parse(self, **kwargs): try: _ = self.retrieved - except exceptions.NotExistent: + except common.NotExistent: return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER exit_code = self._parse_stdout() - if exit_code is not None: - return exit_code + # Even though the simpulation might have failed, we still want to parse the output structure. try: - returned = self._parse_trajectory() - if isinstance(returned, StructureData): - self.out("output_structure", returned) - else: # in case this is an error code - return returned - except exceptions.NotExistent: - pass + last_structure = self._parse_final_structure() + if isinstance(last_structure, StructureData): + self.out("output_structure", last_structure) + except common.NotExistent: + self.logger.warning("No Restart file found in the retrieved folder.") - return ExitCode(0) + if exit_code is not None: + return exit_code + if isinstance(last_structure, engine.ExitCode): + return last_structure + return engine.ExitCode(0) def _parse_stdout(self): """Basic CP2K output file parser.""" @@ -63,19 +57,16 @@ def _parse_stdout(self): # Parse the standard output. result_dict = utils.parse_cp2k_output(output_string) - self.out("output_parameters", Dict(dict=result_dict)) + self.out("output_parameters", orm.Dict(dict=result_dict)) return None - def _parse_trajectory(self): + def _parse_final_structure(self): """CP2K trajectory parser.""" - - from ase import Atoms - fname = self.node.process_class._DEFAULT_RESTART_FILE_NAME # Check if the restart file is present. if fname not in self.retrieved.base.repository.list_object_names(): - raise exceptions.NotExistent( + raise common.NotExistent( "No restart file available, so the output trajectory can't be extracted" ) @@ -85,7 +76,9 @@ def _parse_trajectory(self): except OSError: return self.exit_codes.ERROR_OUTPUT_STDOUT_READ - return StructureData(ase=Atoms(**utils.parse_cp2k_trajectory(output_string))) + return StructureData( + ase=ase.Atoms(**utils.parse_cp2k_trajectory(output_string)) + ) def _check_stdout_for_errors(self, output_string): """This function checks the CP2K output file for some basic errors.""" @@ -169,7 +162,7 @@ def _parse_stdout(self): ) self.out("output_bands", bnds) - self.out("output_parameters", Dict(dict=result_dict)) + self.out("output_parameters", orm.Dict(dict=result_dict)) return None @@ -208,5 +201,5 @@ def _parse_stdout(self): except KeyError: pass - self.out("output_parameters", Dict(dict=result_dict)) + self.out("output_parameters", orm.Dict(dict=result_dict)) return None diff --git a/aiida_cp2k/utils/parser.py b/aiida_cp2k/utils/parser.py index 774f4f1..aca942b 100644 --- a/aiida_cp2k/utils/parser.py +++ b/aiida_cp2k/utils/parser.py @@ -9,6 +9,8 @@ import math import re +import numpy as np + def parse_cp2k_output(fstring): """Parse CP2K output into a dictionary.""" @@ -323,8 +325,6 @@ def _parse_bands_cp2k_greater_81(lines, line_n): def _parse_bands(lines, n_start, cp2k_version): """Parse band structure from the CP2K output.""" - import numpy as np - kpoints = [] labels = [] bands_s1 = [] @@ -377,9 +377,6 @@ def _parse_bands(lines, n_start, cp2k_version): def parse_cp2k_trajectory(content): """CP2K trajectory parser.""" - - import numpy as np - # Parse coordinate section match = re.search(r"\n\s*&COORD\n(.*?)\n\s*&END COORD\n", content, re.DOTALL) coord_lines = [line.strip().split() for line in match.group(1).splitlines()]