Skip to content

Commit 002a4d5

Browse files
committed
Apply ruff formatting and fix linting errors
Fix line length violations (E501) and magic value warnings (PLR2004) by: - Breaking long docstrings and comments across multiple lines - Extracting array indices to named variables with explanatory comments
1 parent 94a110b commit 002a4d5

File tree

3 files changed

+139
-63
lines changed

3 files changed

+139
-63
lines changed

src/nomad_simulation_parsers/parsers/vasp/outcar_parser.py

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -328,21 +328,42 @@ def str_to_eigenvalues(val_in):
328328
('TITEL', re.search(r'TITEL\s*=\s*(.+)', val_in)),
329329
('VRHFIN', re.search(r'VRHFIN\s*=(.+?)(?:\n|$)', val_in)),
330330
('LEXCH', re.search(r'LEXCH\s*=\s*(\w+)', val_in)),
331-
('ZVAL', re.search(r'POMASS\s*=\s*[\d\.]+;\s*ZVAL\s*=\s*([\d\.]+)', val_in)),
331+
(
332+
'ZVAL',
333+
re.search(
334+
r'POMASS\s*=\s*[\d\.]+;\s*ZVAL\s*=\s*([\d\.]+)',
335+
val_in,
336+
),
337+
),
332338
('RCORE', re.search(r'RCORE\s*=\s*([\d\.]+)', val_in)),
333339
('ENMAX', re.search(r'ENMAX\s*=\s*([\d\.]+)', val_in)),
334340
('ENMIN', re.search(r'ENMIN\s*=\s*([\d\.]+)', val_in)),
335341
('LPAW', re.search(r'LPAW\s*=\s*([TF])', val_in)),
336342
('LULTRA', re.search(r'LULTRA\s*=\s*([TF])', val_in)),
337-
('LMAX', re.search(r'number of l-projection\s+operators is LMAX\s*=\s*(\d+)', val_in)),
338-
('LMMAX', re.search(r'number of lm-projection\s+operators is LMMAX\s*=\s*(\d+)', val_in)),
343+
(
344+
'LMAX',
345+
re.search(
346+
r'number of l-projection\s+operators is '
347+
r'LMAX\s*=\s*(\d+)',
348+
val_in,
349+
),
350+
),
351+
(
352+
'LMMAX',
353+
re.search(
354+
r'number of lm-projection\s+operators is '
355+
r'LMMAX\s*=\s*(\d+)',
356+
val_in,
357+
),
358+
),
339359
('SHA256', re.search(r'SHA256\s*=\s*(\w+)', val_in)),
340360
]
341361
if value is not None
342362
for key, value in [(key, value.group(1) if value else None)]
343363
if value is not None
344364
}
345-
if 'VRHFIN' in val_in else {} # Only process detailed sections with VRHFIN
365+
if 'VRHFIN' in val_in
366+
else {} # Only process detailed sections with VRHFIN
346367
),
347368
convert=False,
348369
),
@@ -494,18 +515,23 @@ def get_xc_functionals(self, parameters: dict[str, Any]) -> list[dict[str, Any]]
494515
xc_functionals.append({'name': functional})
495516
return xc_functionals
496517

497-
def get_pseudopotentials(self, source: list[dict[str, Any]]) -> list[dict[str, Any]]:
518+
def get_pseudopotentials(
519+
self, source: list[dict[str, Any]]
520+
) -> list[dict[str, Any]]:
498521
"""
499-
Idiomatic transformer: Extract and derive all pseudopotential metadata from OUTCAR.
522+
Idiomatic transformer: Extract and derive all pseudopotential metadata
523+
from OUTCAR.
500524
501-
Performs ALL derivations here (type, XC functional, cutoffs) - no post-processing needed.
502-
Returns plain dicts that the mapping framework converts to Pseudopotential instances.
525+
Performs ALL derivations here (type, XC functional, cutoffs) - no
526+
post-processing needed. Returns plain dicts that the mapping framework
527+
converts to Pseudopotential instances.
503528
504529
Args:
505530
source: List of raw POTCAR header dicts from OUTCAR parser
506531
507532
Returns:
508-
list[dict]: List of complete pseudopotential dicts ready for schema population
533+
list[dict]: List of complete pseudopotential dicts ready for schema
534+
population
509535
"""
510536
pseudopotentials = []
511537

@@ -517,7 +543,9 @@ def get_pseudopotentials(self, source: list[dict[str, Any]]) -> list[dict[str, A
517543
# Extract basic metadata
518544
pp_data = {
519545
'name': raw_pp.get('TITEL'),
520-
'n_valence_electrons': float(raw_pp['ZVAL']) if 'ZVAL' in raw_pp else None,
546+
'n_valence_electrons': float(raw_pp['ZVAL'])
547+
if 'ZVAL' in raw_pp
548+
else None,
521549
'reference_configuration': raw_pp.get('VRHFIN'),
522550
'r_core': float(raw_pp['RCORE']) if 'RCORE' in raw_pp else None,
523551
'l_max': int(raw_pp['LMAX']) if 'LMAX' in raw_pp else None,
@@ -527,10 +555,15 @@ def get_pseudopotentials(self, source: list[dict[str, Any]]) -> list[dict[str, A
527555

528556
# Derive type from LPAW/LULTRA flags and name patterns (idiomatic)
529557
pp_data['type'] = self._derive_pp_type(raw_pp)
530-
pp_data['is_norm_conserving'] = pp_data['type'] in ['NC', 'NC-PAW', 'NC-PAW-GW']
558+
pp_data['is_norm_conserving'] = pp_data['type'] in [
559+
'NC',
560+
'NC-PAW',
561+
'NC-PAW-GW',
562+
]
531563
pp_data['is_gw_optimized'] = '_GW' in (raw_pp.get('TITEL') or '')
532564

533-
# Derive XC functional dict (will be instantiated as XCFunctional subsection)
565+
# Derive XC functional dict (will be instantiated as XCFunctional
566+
# subsection)
534567
xc_key = self._derive_pp_xc_functional_key(raw_pp)
535568
if xc_key:
536569
pp_data['xc_functional'] = {'functional_key': xc_key}
@@ -567,7 +600,8 @@ def _derive_pp_type(self, raw_pp: dict[str, Any]) -> str | None:
567600
def _derive_pp_xc_functional_key(self, raw_pp: dict[str, Any]) -> str | None:
568601
"""Derive XC functional_key from LEXCH parameter using VASP mapping.
569602
570-
Returns standard functional aliases that will be expanded to LibXC components by normalization.
603+
Returns standard functional aliases that will be expanded to LibXC
604+
components by normalization.
571605
"""
572606
lexch = raw_pp.get('LEXCH')
573607
if not lexch:
@@ -576,11 +610,11 @@ def _derive_pp_xc_functional_key(self, raw_pp: dict[str, Any]) -> str | None:
576610
# Map VASP LEXCH codes to standard functional aliases
577611
# These aliases are expanded to LibXC labels during XCFunctional.normalize()
578612
lexch_mapping = {
579-
'PE': 'PBE', # Perdew-Burke-Ernzerhof -> XC_GGA_X_PBE + XC_GGA_C_PBE
580-
'CA': 'CA', # Ceperley-Alder (Teter parametrization)
581-
'PW': 'PW91', # Perdew-Wang 91
582-
'HL': 'HL', # Hedin-Lundqvist
583-
'WI': 'WI', # Wigner interpolation
613+
'PE': 'PBE', # Perdew-Burke-Ernzerhof -> XC_GGA_X_PBE + XC_GGA_C_PBE
614+
'CA': 'CA', # Ceperley-Alder (Teter parametrization)
615+
'PW': 'PW91', # Perdew-Wang 91
616+
'HL': 'HL', # Hedin-Lundqvist
617+
'WI': 'WI', # Wigner interpolation
584618
}
585619

586620
return lexch_mapping.get(lexch)
@@ -591,19 +625,23 @@ def _derive_pp_cutoffs(self, raw_pp: dict[str, Any]) -> list[dict[str, Any]]:
591625

592626
enmax = raw_pp.get('ENMAX')
593627
if enmax is not None:
594-
cutoffs.append({
595-
'cutoff_kind': 'wavefunction',
596-
'cutoff_role': 'recommended',
597-
'value': float(enmax),
598-
})
628+
cutoffs.append(
629+
{
630+
'cutoff_kind': 'wavefunction',
631+
'cutoff_role': 'recommended',
632+
'value': float(enmax),
633+
}
634+
)
599635

600636
enmin = raw_pp.get('ENMIN')
601637
if enmin is not None:
602-
cutoffs.append({
603-
'cutoff_kind': 'wavefunction',
604-
'cutoff_role': 'recommended_min',
605-
'value': float(enmin),
606-
})
638+
cutoffs.append(
639+
{
640+
'cutoff_kind': 'wavefunction',
641+
'cutoff_role': 'recommended_min',
642+
'value': float(enmin),
643+
}
644+
)
607645

608646
return cutoffs
609647

src/nomad_simulation_parsers/parsers/vasp/xml_parser.py

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from typing import TYPE_CHECKING, Any
21
import os
32
from pathlib import Path as PathLib
3+
from typing import TYPE_CHECKING, Any
44

55
import numpy as np
66

@@ -71,27 +71,36 @@ def reshape_array(self, source: np.ndarray, shape_rest: tuple = (3,)) -> np.ndar
7171
source, (np.size(source) // int(np.prod(shape_rest)), *shape_rest)
7272
)
7373

74-
def get_pseudopotentials_xml(self, arrays: list[dict[str, Any]]) -> list[dict[str, Any]]:
74+
def get_pseudopotentials_xml(
75+
self, arrays: list[dict[str, Any]]
76+
) -> list[dict[str, Any]]:
7577
"""
76-
Idiomatic transformer: Extract limited pseudopotential metadata from vasprun.xml.
78+
Idiomatic transformer: Extract limited pseudopotential metadata from
79+
vasprun.xml.
7780
78-
Note: vasprun.xml contains very limited pseudopotential information compared to OUTCAR.
79-
Only name (TITEL) and valence electrons (ZVAL) are available. Other fields like type,
80-
XC functional, and cutoffs must be supplemented from OUTCAR via multi-pass parsing.
81+
Note: vasprun.xml contains very limited pseudopotential information
82+
compared to OUTCAR. Only name (TITEL) and valence electrons (ZVAL) are
83+
available. Other fields like type, XC functional, and cutoffs must be
84+
supplemented from OUTCAR via multi-pass parsing.
8185
8286
Args:
83-
arrays: List of arrays from atominfo, need to filter for @name='atomtypes'
87+
arrays: List of arrays from atominfo, need to filter for
88+
@name='atomtypes'
8489
8590
Returns:
86-
list[dict]: List of pseudopotential dicts with limited metadata (name and n_valence_electrons only)
91+
list[dict]: List of pseudopotential dicts with limited metadata
92+
(name and n_valence_electrons only)
8793
"""
8894
if not arrays:
8995
return []
9096

9197
# Find the atomtypes array
9298
atomtypes_array = None
9399
for arr in arrays:
94-
if isinstance(arr, dict) and arr.get(f'{self.attribute_prefix}name') == 'atomtypes':
100+
if (
101+
isinstance(arr, dict)
102+
and arr.get(f'{self.attribute_prefix}name') == 'atomtypes'
103+
):
95104
atomtypes_array = arr
96105
break
97106

@@ -101,7 +110,8 @@ def get_pseudopotentials_xml(self, arrays: list[dict[str, Any]]) -> list[dict[st
101110
pseudopotentials = []
102111

103112
# Extract atomtypes data - vasprun.xml stores as array of rc/c elements
104-
# Structure: array[@name='atomtypes'] -> set -> rc with c elements for atomspertype, element, pseudopotential, valence
113+
# Structure: array[@name='atomtypes'] -> set -> rc with c elements for
114+
# atomspertype, element, pseudopotential, valence
105115
for atomtype_set in [atomtypes_array]:
106116
if not isinstance(atomtype_set, dict):
107117
continue
@@ -115,14 +125,22 @@ def get_pseudopotentials_xml(self, arrays: list[dict[str, Any]]) -> list[dict[st
115125
if not isinstance(rc, dict):
116126
continue
117127

118-
# Each rc has 'c' elements: c[0]=atomspertype, c[1]=element, c[2]=mass, c[3]=valence, c[4]=pseudopotential
128+
# Each rc has 'c' elements: c[0]=atomspertype, c[1]=element,
129+
# c[2]=mass, c[3]=valence, c[4]=pseudopotential
119130
c_elements = rc.get('c', [])
120-
if not isinstance(c_elements, list) or len(c_elements) < 5:
131+
min_elements = 5 # Need indices 0-4 for all pseudopotential data
132+
if not isinstance(c_elements, list) or len(c_elements) < min_elements:
121133
continue
122134

123135
# Extract name and valence electrons from c elements
124-
pp_name = c_elements[4] if len(c_elements) > 4 else None # pseudopotential name
125-
valence_str = c_elements[3] if len(c_elements) > 3 else None # valence
136+
idx_pp_name = 4 # Index for pseudopotential name
137+
idx_valence = 3 # Index for valence electrons
138+
pp_name = (
139+
c_elements[idx_pp_name] if len(c_elements) > idx_pp_name else None
140+
)
141+
valence_str = (
142+
c_elements[idx_valence] if len(c_elements) > idx_valence else None
143+
)
126144

127145
# Parse valence electrons
128146
n_valence = None
@@ -159,13 +177,18 @@ def write_to_archive(self) -> None:
159177
xml_parser.convert(data_parser)
160178

161179
# Third pass: OUTCAR_KEY to extend with OUTCAR data if available
162-
# This allows OUTCAR to supplement vasprun.xml pseudopotentials with detailed metadata
180+
# This allows OUTCAR to supplement vasprun.xml pseudopotentials with
181+
# detailed metadata
163182
outcar_path = self._find_outcar()
164183
if outcar_path and os.path.exists(outcar_path):
165184
LOGGER.info(
166-
f"Found OUTCAR at {outcar_path}, extending vasprun.xml data with detailed pseudopotential metadata"
185+
f'Found OUTCAR at {outcar_path}, extending vasprun.xml data '
186+
'with detailed pseudopotential metadata'
187+
)
188+
from nomad_simulation_parsers.parsers.vasp.outcar_parser import (
189+
OutcarParser,
190+
OutcarTextParser,
167191
)
168-
from nomad_simulation_parsers.parsers.vasp.outcar_parser import OutcarParser, OutcarTextParser
169192

170193
outcar_parser = OutcarParser()
171194
outcar_parser.text_parser = OutcarTextParser()

src/nomad_simulation_parsers/schema_packages/vasp.py

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ class Simulation(general.Simulation):
3737
'modeling.parameters.separator[?"@name"==\'electronic\']',
3838
)
3939
add_mapping_annotation(model_method.DFT.m_def, OUTCAR_KEY, 'parameters')
40-
add_mapping_annotation(general.Simulation.model_system, XML_KEY, 'modeling.calculation')
40+
add_mapping_annotation(
41+
general.Simulation.model_system, XML_KEY, 'modeling.calculation'
42+
)
4143
add_mapping_annotation(general.Simulation.model_system, OUTCAR_KEY, '.calculation')
4244
add_mapping_annotation(general.Simulation.outputs, XML_KEY, 'modeling.calculation')
4345
add_mapping_annotation(general.Simulation.outputs, XML2_KEY, 'modeling.calculation')
@@ -289,31 +291,31 @@ class ElectronicEigenvalues(outputs.ElectronicEigenvalues):
289291

290292
class Pseudopotential(numerical_settings.Pseudopotential):
291293
"""
292-
VASP-specific pseudopotential metadata extracted from POTCAR headers in OUTCAR and vasprun.xml.
294+
VASP-specific pseudopotential metadata extracted from POTCAR headers in
295+
OUTCAR and vasprun.xml.
293296
294-
Extends base Pseudopotential class with SHA256 hash for POTCAR file identification.
295-
All field derivations (type, XC functional, cutoffs) are performed idiomatically in parser
296-
transformers, not in post-processing.
297+
Extends base Pseudopotential class with SHA256 hash for POTCAR file
298+
identification. All field derivations (type, XC functional, cutoffs) are
299+
performed idiomatically in parser transformers, not in post-processing.
297300
"""
298301

299-
from nomad.metainfo import Quantity
300302
import numpy as np
303+
from nomad.metainfo import Quantity
301304

302305
sha256 = Quantity(
303306
type=str,
304307
description="""
305-
SHA256 hash of the POTCAR file content. Uniquely identifies the pseudopotential
306-
file and enables verification that the correct POTCAR was used. This hash can be
307-
matched against pseudopotential library databases for automatic library detection.
308+
SHA256 hash of the POTCAR file content. Uniquely identifies the
309+
pseudopotential file and enables verification that the correct POTCAR
310+
was used. This hash can be matched against pseudopotential library
311+
databases for automatic library detection.
308312
""",
309313
)
310314

311315
# Field annotations: map dict keys from transformer to schema fields
312316
# All derivations (type, xc_functional, cutoffs) done in transformer
313317
add_mapping_annotation(numerical_settings.Pseudopotential.name, OUTCAR_KEY, '.name')
314-
add_mapping_annotation(
315-
numerical_settings.Pseudopotential.type, OUTCAR_KEY, '.type'
316-
)
318+
add_mapping_annotation(numerical_settings.Pseudopotential.type, OUTCAR_KEY, '.type')
317319
add_mapping_annotation(
318320
numerical_settings.Pseudopotential.n_valence_electrons,
319321
OUTCAR_KEY,
@@ -335,7 +337,10 @@ class Pseudopotential(numerical_settings.Pseudopotential):
335337
'.is_gw_optimized',
336338
)
337339
add_mapping_annotation(
338-
numerical_settings.Pseudopotential.r_core, OUTCAR_KEY, '.r_core', unit='angstrom'
340+
numerical_settings.Pseudopotential.r_core,
341+
OUTCAR_KEY,
342+
'.r_core',
343+
unit='angstrom',
339344
)
340345
add_mapping_annotation(
341346
numerical_settings.Pseudopotential.l_max, OUTCAR_KEY, '.l_max'
@@ -354,19 +359,29 @@ class Pseudopotential(numerical_settings.Pseudopotential):
354359
# Map XC functional dict fields to XCFunctional schema fields
355360
# The functional_key will be expanded to components during normalization
356361
from nomad_simulations.schema_packages import model_method
357-
add_mapping_annotation(model_method.XCFunctional.functional_key, OUTCAR_KEY, '.functional_key')
362+
363+
add_mapping_annotation(
364+
model_method.XCFunctional.functional_key, OUTCAR_KEY, '.functional_key'
365+
)
358366

359367
# Cutoffs: map list of dicts to repeating subsection
360-
# Transformer returns list like [{'cutoff_kind': 'wavefunction', 'cutoff_role': 'recommended', 'value': 172.237}, ...]
368+
# Transformer returns list like [{'cutoff_kind': 'wavefunction',
369+
# 'cutoff_role': 'recommended', 'value': 172.237}, ...]
361370
# The framework will create PPCutoff instances for each dict in the list
362371
add_mapping_annotation(
363372
numerical_settings.Pseudopotential.cutoffs, OUTCAR_KEY, '.cutoffs'
364373
)
365374

366375
# Map cutoff dict fields to PPCutoff schema fields
367-
add_mapping_annotation(numerical_settings.PPCutoff.cutoff_kind, OUTCAR_KEY, '.cutoff_kind')
368-
add_mapping_annotation(numerical_settings.PPCutoff.cutoff_role, OUTCAR_KEY, '.cutoff_role')
369-
add_mapping_annotation(numerical_settings.PPCutoff.value, OUTCAR_KEY, '.value', unit='eV')
376+
add_mapping_annotation(
377+
numerical_settings.PPCutoff.cutoff_kind, OUTCAR_KEY, '.cutoff_kind'
378+
)
379+
add_mapping_annotation(
380+
numerical_settings.PPCutoff.cutoff_role, OUTCAR_KEY, '.cutoff_role'
381+
)
382+
add_mapping_annotation(
383+
numerical_settings.PPCutoff.value, OUTCAR_KEY, '.value', unit='eV'
384+
)
370385

371386
add_mapping_annotation(sha256, OUTCAR_KEY, '.sha256')
372387

0 commit comments

Comments
 (0)