Accelerated Parsing and Writing
The parsing and writing functionality of the
EndfParserPy class is implemented
in pure Python, which guarantees smooth functioning
on a wide variety of platforms as long as a Python interpreter
is available. However, the disadvantage is slow execution
speed compared to parsers implemented in compiled
languages, such as C++. The speed disadvantage is
exacerbated by the fact that endf-parserpy implements
at its core an interpreter for ENDF recipe files
which contain the necessary information to properly parse and write
ENDF-6 formatted files. Understandably, the implementation of
an interpreter in an interpreted language (Python) is even
slower than a direct implementation of the specific instructions
required for parsing and writing ENDF-6 files in Python.
For this reason, parsing and writing functionality is also
provided by C++ functions shipped with the endf-parserpy
package. During the installation via pip install or equivalent
means, an attempt is made to compile the C++ source code to
Python modules if pre-compiled binary wheels for your platform are not
available. Provided that a binary exists for your platform or the
compilation from source is successful, you can benefit
from accelerated parsing and writing of ENDF-6 files by using
the EndfParserCpp class.
The interface of the EndfParserCpp class
closely mirrors the one of the EndfParserPy class,
providing most of the same initialization options. The following
code snippet demonstrates the reading and writing of an ENDF-6 file:
from endf_parserpy import EndfParserCpp
parser = EndfParserCpp()
endf_dict = parser.parsefile('input.endf')
# here you can modify endf_dict in some way
parser.writefile('output.endf', endf_dict)
As can be seen, the same functions as for the
EndfParserPy class are available
and hence the EndfParserCpp class can
be used as a drop-in replacement. Be aware that the
logging output is less verbose in case of an error and
that some initialization options are not available.
One of these options is recipes that allows users
to provide their custom format extensions.
In the following, we will explain how a user can generate their
own C++ module with parsing and writing functions based on their
own recipe files.
Generating C++ code from ENDF recipes
To follow this section properly, basic knowledge of using
a C++ compiler, such as clang or the GNU C++ compiler,
is likely required. The aim of this section is to provide a
starting point for expert users to compile their own ENDF format parsers
but a detailed explanation of all possible pitfalls in the process
is beyond the scope of this document.
We assume that your recipes are available in a nested dictionary
where the keys of the first level are the MF numbers (of type int)
and the keys of the second level the MT numbers (of type int).
The recipes themselves are stored in strings. Consult the
available ENDF-6 recipes
to remind yourself of their form. The section on
mappings by ENDF recipes is also helpful
in this regard. For the sake of illustration, we will just use the
ENDF recipes shipped with this package:
from endf_parserpy.endf_recipes.endf6_ext import endf_recipe_dictionary
Now, you can use the create_project_files function to generate the
module code for parsing and writing files that conform to the format
description stored in the endf_recipe_dictionary:
from endf_parserpy.compiler.compiler import create_project_files
create_project_files(
"endf_parser_project", "cpp_endf", recipes=endf_recipe_dictionary,
path_exist_ok=False, overwrite_files=False
)
This code will create a directory endf_parser_project with a
simple example CMakeLists.txt file and a C++ source file named
cpp_endf.cpp. For an impression how the generated C++ source code looks
like, have a look at this example C++ source file.
Provided that the pybind11 header files
are available on your system, you can use your favorite C++ compiler
(supporting the C++11 standard) to generate a dynamic library that
can be imported in Python. If everything is correctly configured, the following
instructions on the command line can be used to compile the source code:
cd endf_parserpy_project/build
cmake ..
make
The result of the successful compilation is a file named similar to
cpp_endf.cpython-39-x86_64-linux-gnu.so in the build directory.
Being still in this directory, you can start an interactive Python session
and test whether the module can be imported:
from cpp_endf import (
parse_endf,
parse_endf_file,
write_endf,
write_endf_file
)
Here are a couple of examples how these functions can be used:
endf_dict = parse_endf_file("input.endf")
endf_dict = parse_endf_file("input.endf", exclude=(3,), parse_opts={"accept_spaces": False})
endf_string = write_endf(endf_dict, write_opts={"abuse_signpos": True})
endf_dict2 = parse_endf(endf_string)
write_endf_file("output.endf", endf_dict, write_opts={"prefer_noexp": True})
The available keys for the parse_opts and write_opts dictionary can be found
in the documentation of the EndfParserCpp class.
Furthermore, all functions are endowed with an include and exclude
argument that behaves exactly the same way as for the member methods of the
EndfParserCpp class.
In fact, this class is only a thin wrapper around the C++ module functions.