-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsp_parser.py
104 lines (79 loc) · 2.86 KB
/
sp_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"""Parsers provided by aiida_mlip."""
from pathlib import Path
from aiida.common import exceptions
from aiida.engine import ExitCode
from aiida.orm import Dict, SinglefileData
from aiida.orm.nodes.process.process import ProcessNode
from aiida.plugins import CalculationFactory
from ase.io import read
from aiida_mlip.helpers.converters import convert_numpy
from aiida_mlip.parsers.base_parser import BaseParser
SinglepointCalc = CalculationFactory("mlip.sp")
class SPParser(BaseParser):
"""
Parser class for parsing output of calculation.
Parameters
----------
node : aiida.orm.nodes.process.process.ProcessNode
ProcessNode of calculation.
Methods
-------
__init__(node: aiida.orm.nodes.process.process.ProcessNode)
Initialize the SPParser instance.
parse(**kwargs: Any) -> int:
Parse outputs, store results in the database.
Returns
-------
int
An exit code.
Raises
------
exceptions.ParsingError
If the ProcessNode being passed was not produced by a SinglepointCalc.
"""
def __init__(self, node: ProcessNode):
"""
Check that the ProcessNode being passed was produced by a `Singlepoint`.
Parameters
----------
node : aiida.orm.nodes.process.process.ProcessNode
ProcessNode of calculation.
"""
super().__init__(node)
if not issubclass(node.process_class, SinglepointCalc):
raise exceptions.ParsingError("Can only parse `Singlepoint` calculations")
def parse(self, **kwargs) -> int:
"""
Parse outputs, store results in the database.
Parameters
----------
**kwargs : Any
Any keyword arguments.
Returns
-------
int
An exit code.
"""
exit_code = super().parse(**kwargs)
if exit_code != ExitCode(0):
return exit_code
xyz_output = (self.node.inputs.out).value
# Check that folder content is as expected
files_retrieved = self.retrieved.list_object_names()
files_expected = {xyz_output}
if not files_expected.issubset(files_retrieved):
self.logger.error(
f"Found files '{files_retrieved}', expected to find '{files_expected}'"
)
return self.exit_codes.ERROR_MISSING_OUTPUT_FILES
# Add output file to the outputs
self.logger.info(f"Parsing '{xyz_output}'")
with self.retrieved.open(xyz_output, "rb") as handle:
self.out("xyz_output", SinglefileData(file=handle, filename=xyz_output))
content = read(
Path(self.node.get_remote_workdir(), xyz_output), format="extxyz"
)
results = convert_numpy(content.todict())
results_node = Dict(results)
self.out("results_dict", results_node)
return ExitCode(0)