-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add basic fortran binary file parser
- Loading branch information
Showing
13 changed files
with
23,189 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
"""List of parsers for binary file formats.""" | ||
from __future__ import annotations | ||
|
||
from collections.abc import Callable | ||
from .cst_esp_file_parser import parse_cst_esp_file | ||
|
||
|
||
#: Dictionary of available parsers. | ||
PARSERS: dict[str, Callable] = { | ||
"cst_esp": parse_cst_esp_file, | ||
} | ||
|
||
#: Names of parsers/parsable file extensions (without ``"."``). | ||
CASTEP_OUTPUT_NAMES: tuple[str, ...] = tuple(PARSERS.keys()) | ||
|
||
#: Names of parsable file extensions. | ||
CASTEP_FILE_FORMATS: tuple[str, ...] = tuple(f".{typ}" for typ in CASTEP_OUTPUT_NAMES) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
"""Parser for cst_esp files.""" | ||
from __future__ import annotations | ||
|
||
from typing import BinaryIO, TypedDict | ||
|
||
from ..utilities.utility import to_type | ||
from .fortran_bin_parser import binary_file_reader | ||
|
||
|
||
class ESPData(TypedDict): | ||
"""Data from electrostatic potential.""" | ||
|
||
#: Number of spins in run. | ||
n_spins: int | ||
#: Grid size sampled at. | ||
grid: int | ||
#: ESP Data. | ||
esp: tuple[tuple[tuple[complex, ...]]] | ||
#: MGGA | ||
mgga: tuple[tuple[tuple[complex, ...]]] | ||
|
||
|
||
def parse_cst_esp_file(cst_esp_file: BinaryIO) -> ESPData: | ||
"""Parse castep `cst_esp` files. | ||
Parameters | ||
---------- | ||
cst_esp_file : BinaryIO | ||
File to parse. | ||
Returns | ||
------- | ||
ESPData | ||
Parsed data. | ||
""" | ||
dtypes = {"n_spins": int, "grid": int} | ||
|
||
accum = {"esp": []} | ||
|
||
reader = binary_file_reader(cst_esp_file) | ||
for (key, typ), datum in zip(dtypes.items(), reader): | ||
accum[key] = to_type(datum, typ) | ||
|
||
prev_nx = None | ||
curr = [] | ||
for datum in reader: | ||
nx, ny = to_type(datum[:8], int) | ||
if prev_nx != nx and curr: | ||
accum["esp"].append(curr) | ||
curr = [] | ||
curr.append(to_type(datum[8:], complex)) | ||
prev_nx = nx | ||
|
||
accum["esp"].append(curr) | ||
|
||
size = accum["grid"][0] | ||
if len(accum["esp"]) > size: # Have MGGA pot | ||
accum["esp"], accum["mgga"] = accum["esp"][:size], accum["esp"][size:] | ||
|
||
return accum |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
"""General parser for the Fortran Unformatted file format.""" | ||
from os import SEEK_CUR | ||
from typing import BinaryIO, Generator | ||
|
||
FortranBinaryReader = Generator[bytes, int, None] | ||
|
||
def binary_file_reader(file: BinaryIO) -> FortranBinaryReader: | ||
"""Yield the elements of a Fortran unformatted file.""" | ||
while bin_size := file.read(4): | ||
size = int.from_bytes(bin_size, "big") | ||
data = file.read(size) | ||
skip = yield data | ||
file.read(4) | ||
if skip: # NB. Send proceeds to yield. | ||
# `True` implies rewind 1 | ||
if skip < 0 or skip is True: | ||
for _ in range(abs(skip)): | ||
# Rewind to record size before last read | ||
file.seek(-size-12, SEEK_CUR) | ||
size = int.from_bytes(file.read(4), "big") | ||
|
||
# Rewind one extra (which will be yielded) | ||
file.seek(-size-8, SEEK_CUR) | ||
else: | ||
for _ in range(skip): | ||
size = int.from_bytes(file.read(4), "big") | ||
file.seek(size+4, SEEK_CUR) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.