Skip to content

Commit a715135

Browse files
authored
Extend parsers (#19)
* Add system quantities to qe * Add output quantities to qe * Extend octopus parser * Extend ams parser
1 parent 69ff501 commit a715135

File tree

14 files changed

+2701
-66
lines changed

14 files changed

+2701
-66
lines changed

src/nomad_simulation_parsers/parsers/ams/file_parser.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ def str_to_labels_positions(val_in):
2424
unit = val.pop(0)[0].lower()
2525
unit = ureg.bohr if unit.startswith('bohr') else ureg.angstrom
2626
val = np.transpose(val)
27-
return val[1], np.array(val[2:5].T, dtype=np.dtype(np.float64)) * unit
27+
return [
28+
list(val[1]),
29+
np.array(val[2:5].T, dtype=np.dtype(np.float64)) * unit,
30+
]
2831

2932
def str_to_lattice_vectors(val_in):
3033
val = [v.split()[-3:] for v in val_in.strip().splitlines()]
@@ -697,8 +700,8 @@ def to_band_energy_ranges(val_in):
697700
Quantity(
698701
'forces_total',
699702
rf'Gradients \(hartree/bohr\)\s+'
700-
rf'Index.+\s+((?:\d+ +[A-Z][a-z]*'
701-
rf' +{RE_FLOAT} +{RE_FLOAT} +{RE_FLOAT}\s+)+)',
703+
rf'Index.+\s+'
704+
rf'((?:\d+ +[A-Z][a-z]* +{RE_FLOAT} +{RE_FLOAT} +{RE_FLOAT}\s+)+)',
702705
str_operation=str_to_forces,
703706
),
704707
Quantity(
@@ -1253,8 +1256,7 @@ def parse_results(self) -> None:
12531256
)
12541257

12551258
def parse_properties(self) -> None:
1256-
if properties := self.data.get('Properties'):
1257-
return
1259+
properties = self.data.get('Properties', {})
12581260

12591261
nspin = self.data.get('General', {}).get('nspin', 1)
12601262

@@ -1342,7 +1344,9 @@ def parse_properties(self) -> None:
13421344
)
13431345
bottom_conduction_band = band_structure.get('BottomConductionBand')
13441346
band_gap['energy_lowest_unoccupied'] = (
1345-
(bottom_conduction_band * ureg.hartree) if not None else None
1347+
(bottom_conduction_band * ureg.hartree)
1348+
if bottom_conduction_band is not None
1349+
else None
13461350
)
13471351
self._results['band_gap'] = band_gap
13481352

src/nomad_simulation_parsers/parsers/ams/parser.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import os
12
from importlib import reload
3+
from typing import Any
24

5+
import numpy as np
36
from nomad.datamodel import EntryArchive
47
from nomad.parsing.file_parser import ArchiveWriter
58
from nomad.parsing.file_parser.mapping_parser import MetainfoParser, TextParser
@@ -8,9 +11,11 @@
811
from nomad_simulations.schema_packages.general import Program, Simulation
912
from structlog.stdlib import BoundLogger
1013

14+
from nomad_simulation_parsers.parsers.utils.general import search_files
1115
from nomad_simulation_parsers.schema_packages import ams
1216

1317
from .file_parser import OutParser
18+
from .file_parser import RKFParser as RKFTextParser
1419

1520
LOGGER = get_logger(__name__)
1621

@@ -21,6 +26,44 @@ class MainfileParser(TextParser):
2126
def logger(self):
2227
return LOGGER
2328

29+
def get_xc_functionals(self, source: dict[str, Any]) -> list[str]:
30+
xc_functionals = []
31+
for xc_type in ['LDA', 'GGA', 'MGGA']:
32+
functionals = source.get(xc_type, '').split()
33+
kind = ['XC'] if len(functionals) == 1 else ['X', 'C']
34+
for n, functional in enumerate(functionals):
35+
xc_functionals.append(
36+
f'{xc_type}_{kind[n]}_{functional.rstrip("x").rstrip("c").upper()}'
37+
)
38+
return xc_functionals
39+
40+
def get_contributions(self, source: dict[str, Any]) -> list[dict[str, Any]]:
41+
return [
42+
dict(name=key, value=val) for key, val in source.items() if val is not None
43+
]
44+
45+
def get_eigenvalues(
46+
self, source: dict[str, Any] | list[np.ndarray]
47+
) -> list[dict[str, np.ndarray]]:
48+
energies = source.get('energies', []) if isinstance(source, dict) else []
49+
occupations = (
50+
source.get('occupations', []) if isinstance(source, dict) else source[2]
51+
)
52+
nspin = max(len(energies), len(occupations))
53+
eigenvalues = [dict() for _ in range(nspin)]
54+
for n, energy in enumerate(energies):
55+
eigenvalues[n]['eigenvalues'] = energy
56+
for n, occupations in enumerate(occupations):
57+
eigenvalues[n]['occupations'] = occupations
58+
return [eig for eig in eigenvalues if eig]
59+
60+
61+
class RKFParser(MainfileParser):
62+
# TODO temporary fix for structlog unable to propagate logger
63+
@property
64+
def logger(self):
65+
return LOGGER
66+
2467

2568
# TODO temporary fix for structlog unable to propagate logger
2669
class AMSMetainfoParser(MetainfoParser):
@@ -32,6 +75,7 @@ def logger(self):
3275
class AMSArchiveWriter(ArchiveWriter):
3376
mainfile_parser = MainfileParser(text_parser=OutParser())
3477
metainfo_parser = AMSMetainfoParser()
78+
rkf_parser = RKFParser(text_parser=RKFTextParser())
3579

3680
def write_to_archive(self):
3781
# reload schema package to use correct annotations
@@ -41,8 +85,17 @@ def write_to_archive(self):
4185
self.archive.data = Simulation(program=Program(name='AMS'))
4286
self.metainfo_parser.data_object = self.archive.data
4387

44-
self.mainfile_parser.filepath = self.mainfile
45-
self.mainfile_parser.convert(self.metainfo_parser)
88+
rkf_files = search_files('ams.rkf', os.path.dirname(self.mainfile))
89+
self.parser = self.mainfile_parser
90+
self.parser.filepath = self.mainfile
91+
if rkf_files:
92+
if len(rkf_files) > 1:
93+
self.logger.warning('Multiple ams.rkf files found.')
94+
self.parser = self.rkf_parser
95+
self.parser.filepath = rkf_files[0]
96+
self.parser.data_object.parse()
97+
98+
self.parser.convert(self.metainfo_parser)
4699

47100

48101
class AMSParser(MatchingParser):

src/nomad_simulation_parsers/parsers/octopus/file_parsers.py renamed to src/nomad_simulation_parsers/parsers/octopus/file_parser.py

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -184,18 +184,10 @@ def str_to_line(val_in: str) -> list[str]:
184184
)
185185
]
186186

187-
@property
188-
def mainfile(self):
189-
return super().mainfile
190-
191-
@mainfile.setter
192-
def mainfile(self, val):
193-
# TODO pylint complains when inheriting property
194-
# self._results = None
195-
# self._file_handler = None
196-
# self._mainfile = os.path.abspath(val) if val is not None else val
197-
super().mainfile = val
198-
super().__init__()
187+
def reset(self):
188+
super().reset()
189+
self._info = None
190+
self._keys_mapping = dict()
199191

200192
def evaluate_value(self, value: Any) -> Any:
201193
"""
@@ -357,10 +349,10 @@ def get_coordinates(self) -> tuple[str, np.ndarray]:
357349
val = self.info.get('Coordinates', self.info.get('ReducedCoordinates', [[]]))[0]
358350

359351
for v in val:
360-
if isinstance(v, str):
361-
symbols.append(v.strip())
362-
else:
352+
if v[0].isdecimal() or not isinstance(v, str):
363353
coordinates.append(v)
354+
else:
355+
symbols.append(v.strip())
364356

365357
coordinates = np.array(coordinates, dtype=float)
366358
coordinates.shape = (len(symbols), 3)

0 commit comments

Comments
 (0)