paulromano / endf-python

Python ENDF Parser
https://endf-python.readthedocs.io
MIT License
25 stars 6 forks source link

Silent crash in float_endf #6

Closed aidancrilly closed 5 months ago

aidancrilly commented 5 months ago

Hi,

Firstly, thanks for this tool - I am working on using it in my project NeSST (https://github.com/aidancrilly/NeSST).

I just wanted to document this issue I had. Some details, this occurred on a Windows machine, installed without error using pip and MSVC 2022. I could import the library but loading any endf file would silently crash. I suspected this was the pybind'ed C++ so I swapped from using float_endf from the C++ to the py_float_endf. The code then ran without crashing.

Is there a reason to use the C++ version over the python version?

paulromano commented 5 months ago

Hi @aidancrilly! The C++/pybind-ed version is there mostly for performance reasons. If you load a very large ENDF file (or try to parse an entire library), it can make a big difference in performance. If that's not a concern to you though, you should be fine with the Python version. I'll give it a go on Windows to see if I can reproduce the behavior you're seeing. If possible, could you point me to an ENDF file you were having trouble with?

aidancrilly commented 5 months ago

Thanks for taking a look, it was the FENDL-3.2b (https://www-nds.iaea.org/fendl/) ENDF file for deuterium

aidancrilly commented 5 months ago

@paulromano

Perhaps should be a separate issue but using the python endf float converter - this also seems to have problems with files from the BROND library. In particular the tritium file (https://www-nds.iaea.org/exfor/servlet/E4sGetEvaluation?EvalID=118505&req=16765) has zero floats as 0.0 + 0, which trips up the RE.

I swapped to this solution which seems to work for normal ENDF format and this anomaly:

def py_float_endf(input_str : str) -> float:
    # Define the regular expression pattern to match numbers without 'e'
    pattern = r'([-+]?\d*\.\d+|\d+)\s*([-+])\s*(\d+)'

    # Function to replace the matched patterns with exponential notation
    def replace(match):
        num = float(match.group(1))
        sign = match.group(2)
        exp = int(match.group(3))
        return f"{num}e{sign}{exp}"

    # Use re.sub() to replace matched patterns with exponential notation
    result = float(re.sub(pattern, replace, input_str))
    return result

Happy to stick in PR if interested