Skip to content

Commit 8edaa6e

Browse files
committed
More robust parsing of xdmf files
Raise ParsingErrors when some expected elements, attributes, or content are not present.
1 parent f996ccf commit 8edaa6e

File tree

1 file changed

+41
-18
lines changed

1 file changed

+41
-18
lines changed

stagpy/stagyyparsers.py

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -660,22 +660,40 @@ def _read_coord_h5(files: List[Path], shapes: List[Tuple[int, ...]],
660660
header['e3_coord'] = header['e3_coord'][:-1]
661661

662662

663+
def _try_get(file: Path, elt: Element, key: str) -> str:
664+
"""Try getting an attribute or raise a ParsingError."""
665+
att = elt.get(key)
666+
if att is None:
667+
raise ParsingError(file, f"Element {elt} has no attribute {key!r}")
668+
return att
669+
670+
671+
def _try_find(file: Path, elt: Element, key: str) -> Element:
672+
"""Try finding a sub-element or raise a ParsingError."""
673+
subelt = elt.find(key)
674+
if subelt is None:
675+
raise ParsingError(file, f"Element {elt} has no sub-element {key!r}")
676+
return subelt
677+
678+
679+
def _try_text(file: Path, elt: Element) -> str:
680+
"""Try getting text of element or raise a ParsingError."""
681+
text = elt.text
682+
if text is None:
683+
raise ParsingError(file, f"Element {elt} has no 'text'")
684+
return text
685+
686+
663687
def _get_dim(xdmf_file: Path, data_item: Element) -> Tuple[int, ...]:
664688
"""Extract shape of data item."""
665-
dims = data_item.get('Dimensions')
666-
if dims is None:
667-
raise ParsingError(
668-
xdmf_file, f"Element {data_item} has no attribute 'Dimensions'")
689+
dims = _try_get(xdmf_file, data_item, 'Dimensions')
669690
return tuple(map(int, dims.split()))
670691

671692

672693
def _get_field(xdmf_file: Path, data_item: Element) -> Tuple[int, ndarray]:
673694
"""Extract field from data item."""
674695
shp = _get_dim(xdmf_file, data_item)
675-
data_text = data_item.text
676-
if data_text is None:
677-
raise ParsingError(
678-
xdmf_file, f"Element {data_item} has no 'text'")
696+
data_text = _try_text(xdmf_file, data_item)
679697
h5file, group = data_text.strip().split(':/', 1)
680698
# Field on yin is named <var>_XXXXX_YYYYY, on yang is <var>2XXXXX_YYYYY.
681699
numeral_part = group[-11:]
@@ -749,20 +767,21 @@ def read_geom_h5(
749767
coord_shape = [] # shape of meshes
750768
twod = None
751769
for elt_subdomain in elt_snap.findall('Grid'):
752-
if elt_subdomain.get('Name').startswith('meshYang'):
770+
elt_name = _try_get(xdmf_file, elt_subdomain, 'Name')
771+
if elt_name.startswith('meshYang'):
753772
header['ntb'] = 2
754773
break # iterate only through meshYin
755-
elt_geom = elt_subdomain.find('Geometry')
774+
elt_geom = _try_find(xdmf_file, elt_subdomain, 'Geometry')
756775
if elt_geom.get('Type') == 'X_Y' and twod is None:
757776
twod = ''
758777
for data_item in elt_geom.findall('DataItem'):
759-
coord = data_item.text.strip()[-1]
778+
coord = _try_text(xdmf_file, data_item).strip()[-1]
760779
if coord in 'XYZ':
761780
twod += coord
762-
data_item = elt_geom.find('DataItem')
781+
data_item = _try_find(xdmf_file, elt_geom, 'DataItem')
782+
data_text = _try_text(xdmf_file, data_item)
763783
coord_shape.append(_get_dim(xdmf_file, data_item))
764-
coord_h5.append(
765-
xdmf_file.parent / data_item.text.strip().split(':/', 1)[0])
784+
coord_h5.append(xdmf_file.parent / data_text.strip().split(':/', 1)[0])
766785
_read_coord_h5(coord_h5, coord_shape, header, twod)
767786
return header, xdmf_root
768787

@@ -840,11 +859,13 @@ def read_field_h5(
840859
data_found = False
841860

842861
for elt_subdomain in xdmf_root[0][0][snapshot].findall('Grid'):
843-
ibk = int(elt_subdomain.get('Name').startswith('meshYang'))
862+
elt_name = _try_get(xdmf_file, elt_subdomain, 'Name')
863+
ibk = int(elt_name.startswith('meshYang'))
844864
for data_attr in elt_subdomain.findall('Attribute'):
845865
if data_attr.get('Name') != fieldname:
846866
continue
847-
icore, fld = _get_field(xdmf_file, data_attr.find('DataItem'))
867+
icore, fld = _get_field(
868+
xdmf_file, _try_find(xdmf_file, data_attr, 'DataItem'))
848869
# for some reason, the field is transposed
849870
fld = fld.T
850871
shp = fld.shape
@@ -907,7 +928,8 @@ def read_tracers_h5(xdmf_file: Path, infoname: str, snapshot: int,
907928
for axis in 'xyz':
908929
tra[axis] = [{}, {}]
909930
for elt_subdomain in xdmf_root[0][0][snapshot].findall('Grid'):
910-
ibk = int(elt_subdomain.get('Name').startswith('meshYang'))
931+
elt_name = _try_get(xdmf_file, elt_subdomain, 'Name')
932+
ibk = int(elt_name.startswith('meshYang'))
911933
if position:
912934
for data_attr in elt_subdomain.findall('Geometry'):
913935
for data_item, axis in zip(data_attr.findall('DataItem'),
@@ -917,7 +939,8 @@ def read_tracers_h5(xdmf_file: Path, infoname: str, snapshot: int,
917939
for data_attr in elt_subdomain.findall('Attribute'):
918940
if data_attr.get('Name') != infoname:
919941
continue
920-
icore, data = _get_field(xdmf_file, data_attr.find('DataItem'))
942+
icore, data = _get_field(
943+
xdmf_file, _try_find(xdmf_file, data_attr, 'DataItem'))
921944
tra[infoname][ibk][icore] = data
922945
for info in tra:
923946
tra[info] = [trab for trab in tra[info] if trab] # remove empty blocks

0 commit comments

Comments
 (0)