Skip to content

EPICS2023 Database Preparation

This section covers the extraction and optimization of atomic data from the EPICS2023 (EADL, EEDL, EPDL) datasets provided by IAEA.

EPICS2023 Database Preparation

This section covers the extraction and optimization of atomic data from the EPICS2023 (EADL, EEDL, EPDL) datasets.

Source Databases Download

The raw ENDF ASCII data files for Germanium (Z=32) must be downloaded directly from the official IAEA Nuclear Data Section data paths. You can fetch the exact element files using the following direct links:

After downloading, save these files as EADL.dat, EEDL.dat, and EPDL.dat respectively in the project root directory before running the database builder script.

Core Extraction Functions

The following functions parse raw position-based ENDL tables, convert them to fast NumPy structures, and enforce energy monotonicity for cubic spline interpolations.

process_db.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

process_db.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)

process_db.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]

process_db.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