Skip to content

Raw Database Parser

This module handles the initial parsing of raw ASCII position-based ENDL tables (EADL, EEDL, EPDL) for Germanium and formats them into python dictionaries.

process_db

EPICS2023 Database Builder Module.

This script parses raw position-based ENDL ASCII data files (EADL, EEDL, EPDL) for Germanium (Z=32), optimizes the data structures into fast NumPy arrays, and serializes the result into a clean Python pickle file for simulation use.

U = lambda : 1000.0 * float(x) module-attribute

Indexes Layout: 0) Yi - incident particle designator (0: whole atom, 7: photon, 9: electron) 1) Yo - outgoing particle designator (0: none, 7: photon, 8: positron, 9: electron, 19: recoil) 2) C - reaction descriptor 3) I - reaction property

Data_to_Arrays(D)

Recursively converts standard Python lists into fast NumPy arrays.

Walks down the 5-layer nested dictionary and performs in-place modification of all data terminal tables.

Parameters:

Name Type Description Default
D dict

The nested data dictionary to transform.

required
Source code in process_db.py
def Data_to_Arrays(D):
    """
    Recursively converts standard Python lists into fast NumPy arrays.

    Walks down the 5-layer nested dictionary and performs in-place modification
    of all data terminal tables.

    Parameters
    ----------
    D : dict
        The nested data dictionary to transform.
    """
    for Yi in D:
        for Yo in D[Yi]:
            for C in D[Yi][Yo]:
                for I_prop in D[Yi][Yo][C]:
                    for S in D[Yi][Yo][C][I_prop]:
                        for k, v in D[Yi][Yo][C][I_prop][S].items():
                            D[Yi][Yo][C][I_prop][S][k] = np.array(v)

EPICS2023(list_of_files, tables)

Parses ENDL-formatted data files and extracts tables based on active descriptors.

Parameters:

Name Type Description Default
list_of_files list of str

File paths for EADL, EEDL, and EPDL database sheets.

required
tables dict

A combined translation dictionary containing parsing lambdas or 'skip' flags.

required

Returns:

Type Description
tuple(int, float, dict)

Z (Atomic Number), M (Atomic Mass), and the raw nested data hierarchy.

Source code in process_db.py
def EPICS2023(list_of_files, tables):
    """
    Parses ENDL-formatted data files and extracts tables based on active descriptors.

    Parameters
    ----------
    list_of_files : list of str
        File paths for EADL, EEDL, and EPDL database sheets.
    tables : dict
        A combined translation dictionary containing parsing lambdas or 'skip' flags.

    Returns
    -------
    tuple (int, float, dict)
        Z (Atomic Number), M (Atomic Mass), and the raw nested data hierarchy.
    """
    DATA = {}
    for f in list_of_files:
        with open(f, 'r') as fp:
            print(f"{10*'+-'} Reading Data from {f} {10*'-+'}")
            H = fp.readline(), fp.readline()
            Z, M = int(H[0][0:3]), float(H[0][13:24])
            while H[0]:
                Yi, Yo = int(H[0][7:9]), int(H[0][10:12])
                C, I_prop = int(H[1][0:2]), int(H[1][2:5])
                S, X = int(H[1][5:8]), int(float(H[1][21:32]))
                S = 0 if S == 0 else X
                print(f'Yi = {Yi:2d} Yo={Yo:2d} C={C:2d} I={I_prop:3d} S={S:2d}', end='')
                key = (Yi, Yo, C, I_prop)
                if tables[key] != 'skip':
                    if Yi not in DATA.keys():
                        DATA[Yi] = {}
                    if Yo not in DATA[Yi].keys():
                        DATA[Yi][Yo] = {}
                    if C not in DATA[Yi][Yo].keys():
                        DATA[Yi][Yo][C] = {}
                    if I_prop not in DATA[Yi][Yo][C].keys():
                        DATA[Yi][Yo][C][I_prop] = {}
                    if S not in DATA[Yi][Yo][C][I_prop].keys():
                        DATA[Yi][Yo][C][I_prop][S] = {}
                else:
                    print(' (skipped)')

                D = fp.readline().rstrip('\r\n')
                while D != blank_marker:
                    if tables[key] != 'skip':
                        D = D.replace('D', 'e')
                        row = [float(D[i:16+i]) for i in range(0, len(D), 16)]
                        col = tables[key](row).items()
                        if not DATA[Yi][Yo][C][I_prop][S]:
                            DATA[Yi][Yo][C][I_prop][S] = {k: [v] for k, v in col}
                        else:
                            for k, v in col:
                                DATA[Yi][Yo][C][I_prop][S][k].append(v)
                    D = fp.readline().rstrip('\r\n')
                H = fp.readline(), fp.readline()
                if tables[key] != 'skip':
                    In = DATA[Yi][Yo][C][I_prop][S]
                    Tu = tuple(In.keys())
                    Ou = f"  {Tu}: [{len(In[Tu[0]])}] "
                    print(Ou)
    return Z, M, DATA

Shift_E(D)

Forces strict monotonic increase of energy thresholds for spline safety.

Modifies adjacent identical energy boundaries near atomic shell transitions by a small fractional value to ensure compatibility with cubic splines.

Parameters:

Name Type Description Default
D dict

The global multi-level interaction dataset.

required
Source code in process_db.py
def Shift_E(D):
    """
    Forces strict monotonic increase of energy thresholds for spline safety.

    Modifies adjacent identical energy boundaries near atomic shell transitions
    by a small fractional value to ensure compatibility with cubic splines.

    Parameters
    ----------
    D : dict
        The global multi-level interaction dataset.
    """
    E = D[7][0][73][0][0]['Eγ']
    for i in range(len(E)-1):
        if E[i] == E[i+1]:
            D[7][0][73][0][0]['Eγ'][i] = 0.9999 * E[i]
            D[7][0][73][0][0]['Eγ'][i+1] = 1.0001 * E[i+1]

Split_Arrays(T)

Splits multi-dimensional distribution tables over discrete incident energy values.

Parameters:

Name Type Description Default
T dict

A table structure with 3 equivalent-length data lists.

required

Returns:

Type Description
dict

A reassigned layout mapped by unique isolated baseline variables.

Source code in process_db.py
def Split_Arrays(T):
    """
    Splits multi-dimensional distribution tables over discrete incident energy values.

    Parameters
    ----------
    T : dict
        A table structure with 3 equivalent-length data lists.

    Returns
    -------
    dict
        A reassigned layout mapped by unique isolated baseline variables.
    """
    D = {}
    K = list(T.keys())
    U = sorted(list(set(T[K[0]])))
    A = np.swapaxes(np.array([T[K[0]], T[K[1]], T[K[2]]]), 0, 1)
    for u in U:
        D[u] = {K[1]: A[A[:, 0] == u, 1], K[2]: A[A[:, 0] == u, 2]}
    return D