diff --git a/src/DataLib/fendl32B_retrofit/fendl3_retrofit.py b/src/DataLib/fendl32B_retrofit/fendl3_retrofit.py new file mode 100644 index 0000000..0b452e9 --- /dev/null +++ b/src/DataLib/fendl32B_retrofit/fendl3_retrofit.py @@ -0,0 +1,439 @@ +# Import packages +import tendl_preprocessing as tpp +from logging_config import logger +import groupr_tools +import argparse +import asyncio +import pandas as pd +import reaction_data as rxd +import subprocess +from pathlib import Path + +def fendl_args(): + """ + Configure Argument Parser for the FENDL 3.2-b/TENDL 2017 retroffiting, + including options for user input of GENDF files that have already + been processed using the NJOY GROUPR module or downloading and + processing TENDL/PENDF files from the TENDL 2017 database. + + Note: If the user opts to select the "Loclal file input" option, + they must ensure that the GENDF file is properly formatted and + contains activation, and not transport data, themselves. + + Arguments: + None + + Returns: + args (argparse.Namespace): Argparse object that contains the user + specified arguments for executing the program. + """ + + parser = argparse.ArgumentParser() + + parser.add_argument( + '--paths', '-p', required = False, nargs='*', + help= ''' + Path(s) to the local GENDF file(s) or the repository in which + they are located. + + If left empty, then corresponding ENDF and + PENDF files will be downloaded and processed into properly + formatted GENDF files. + ''') + parser.add_argument( + '--element', '-e', required=False, nargs='*', + help= ''' + Chemical symbol(s) for selected element(s) (i.e. Ti). + + To iterate over all elements, either type "all" or leave empty. + ''') + parser.add_argument( + '--mass_number', '-a', required= False, nargs = '*', + help= '''Mass number for selected isotope (i.e. 48). If the target is + an isomer, type "m" after the mass number (i.e. 48m). + + To automatically iterate over all of the isotopes for the + target element, type "all" or leave empty. + ''') + + args = parser.parse_args() + return args + +def prepare_ls_commands(args, gendf_dir, element): + """ + Create a list of commands to be run with a subprocess.run() executable to + be used to search for GENDF files in a given directory for a + particular element. This can either be targetted for individual files + specified by the mass number for an isotope, whose data is stored in + a GENDF file, or all files for the element in the directory. + + Arguments: + args (argparse.Namespace): Argparse object that contains user-declared + parameters, from which the only one accessed is mass_number, to + determine whether to prepare a search command for a pre-defined + list of files or to search for any and all files for the element. + gendf_dir (str): Path for the directory containing the relevant GENDF + file(s). + element (str): Chemical name of the target element. + + Returns: + commands (list of str): List of all "ls" search commands to be run + with the subprocess module, corresponding to the desired files to + be processed. + """ + + commands = [] + A_vals = args.mass_number + + if not A_vals or A_vals == ['all']: + ls_command = (f'ls {Path(gendf_dir) / f"*{element}*"}', None) + commands.append(ls_command) + else: + for A in A_vals: + A = A.zfill(3) + ls_command = (f'ls {Path(gendf_dir) / f"*{element}{A}*"}', A) + commands.append(ls_command) + + return commands + +def run_ls_command(command): + """ + Use subprocess.run() to execute an "ls" command to search for a particular + GENDF file or multiple GENDF files. This function streamlines usage of + subprocess by making it only necessary to input the searching command, + without having to specify the other run() parameters. + + Arguments: + command (str): Shell command to be used by subprocess.run() to search + for a GENDF file or GENDF files using "ls". + + Returns: + ls_output (list of str): List of the relative file paths to all of the + GENDF files found from the "ls" command. + """ + + ls_output = subprocess.run( + command, # Execute the ocmmand using subprocess.run + shell=True, # Run the command in the shell + check=True, # Raise exception if returns non-zero code + stdout=subprocess.PIPE, # Capture the standard output + stderr=subprocess.PIPE, # Capture the standard error + universal_newlines=True # Return the output as a string, not bytes + ).stdout.strip().split("\n") + + return ls_output + +def warn_missing_file(error, element, A): + """ + Identify and log a warning if the file for a partiular isotope is not + found when the run_ls_command() function is executed. Rather than + raise an error to the terminal, it will just be logged as a warning + so that if the user is searching for multiple elements and a suitable + isotope exists for one but not the other, it will not cause the + execution to fail, but rather just to make note of the case and warn + the user to double check whether or not that file was supposed to + exist. + + Arguments: + error (subprocess.CalledProcessError): A subprocess error object that + signifies that the execution of the command was unsuccessful and + returns a non-zero exit status. + element (str): Chemical name of the target element. + A (str): Mass number of the target isotope, including the letter "m" + at the end if the target is a nuclear isomer. + + Returns: + None + """ + + if error.returncode == 2: # Error code for CalledProcessError + + logger.warning(error.stderr.strip()) + specific_message = f'{element}{A or ""}' + + warning_message = ( + f'If there is a GENDF file for {element}' + f'{f" with mass number {A}" if A is not None else ""},' + ' then make sure it is properly named and ' + f'formatted with the string "{specific_message}" ' + 'included in the file\'s name.' + ) + logger.warning(warning_message) + else: + raise + +def search_files_for_element(args, gendf_dir, element): + """ + Generate and iterate through the GENDF file search commands produced from + prepare_ls_commands() to either store the file paths in a cumulative + list or to log missing files and tally the number of warnings from a + given run. + + Arguments: + args (argparse.Namespace): Argparse object that contains user-declared + parameters, which is read in the prepare_ls_commands() function. + gendf_dir (str): Path for the directory containing the relevant GENDF + file(s). + element (str): Chemical name of the target element. + + Returns: + element_gendf_paths (list of str): List containing all of the relative + file paths for the target element's GENDF files in the selected + directory. + warnings (int): Count of the number of isotopes searched for that do + not have findable GENDF files in the selected directory. + """ + + warnings = 0 + element_gendf_paths = [] + + commands = prepare_ls_commands(args, gendf_dir, element) + + for command, A in commands: + try: + ls_output = run_ls_command(command) + element_gendf_paths.extend(ls_output) + except subprocess.CalledProcessError as e: + warn_missing_file(e, element, A) + warnings += 1 + + return element_gendf_paths, warnings + +def search_gendf_directory(args, gendf_dir=None, gendf_paths_from_arg=None): + """ + Iterate through all of the user-selected elements from the argparser to + find and store all of the corresponding GENDF files that fit elements + and mass numbers specified. If none of the elements have GENDF files + that can be found, an Exception will be raised. + + Arguments: + args (argparse.Namespace): Argparse object that contains user-declared + parameters. + gendf_dir (str, optional): Path for the directory containing the + relevant GENDF file(s). Either this or gendf_paths_from_arg + must be defined. Defaults to None. + gendf_paths_from_arg (list of str, optional): List containing only the + path for the directory containing the relevant GENDF file(s). + Either this or gendf_dir must be defined. Defaults to None. + + Returns: + all_gendf_paths (list of str): List containing all of the file + paths to the GENDF files to be analyzed. + """ + + gendf_dir = gendf_dir or gendf_paths_from_arg[0] + elements = groupr_tools.elements.keys( + ) if args.element == ['all'] or not args.element else args.element + missing_elements = 0 + + all_gendf_paths = [] + + for element in elements: + element_gendf_paths, warnings = search_files_for_element(args, + gendf_dir, + element) + + if warnings == len(prepare_ls_commands(args, gendf_dir, element)): + logger.error(f'No GENDF files found for {element}.') + missing_elements += 1 + + all_gendf_paths.extend(element_gendf_paths) + + if missing_elements == len(elements): + raise Exception( + 'No GENDF files found for any of the selected elements.' + ) + else: + logger.info( + f'All files to be processed: {", ".join(all_gendf_paths)}' + ) + + return all_gendf_paths + +def iterate_MTs(MTs, file_obj, mt_dict, pKZA): + """ + Iterate through all of the MTs present in a given GENDF file to extract + the necessary data to be able to run ALARA. + + Arguments: + MTs (list of int): List of reaction types present in the GENDF file. + file_obj (ENDFtk.tree.File or None): ENDFtk file object containing the + contents for a specific material's cross-section data. + mt_dict (dict): Dictionary formatted data structure for mt_table.csv + pKZA (int): Parent KZA identifier. + + Returns: + gendf_data (pandas.core.frame.DataFrame): Pandas DataFrame containing + parent KZA values, daughter KZA values, emitted particles, + counts of the number of non-zero groups in the Vitamin-J groupwise + structure, and the cross-section values for those groups. + """ + + cross_sections_by_MT = [] + emitted_particles_list = [] + dKZAs = [] + groups = [] + + for MT in MTs: + sigma_list = tpp.extract_cross_sections(file_obj, MT) + dKZA = pKZA - mt_dict[str(MT)]['delKZA'] + emitted_particles = mt_dict[str(MT)]['Emitted Particles'] + cross_sections_by_MT.append(sigma_list) + dKZAs.append(dKZA) + emitted_particles_list.append(emitted_particles) + groups.append(len(sigma_list)) + + gendf_data = pd.DataFrame({ + 'Parent KZA' : [pKZA] * len(dKZAs), + 'Daughter KZA' : dKZAs, + 'Emitted Particles' : emitted_particles_list, + 'Non-Zero Groups' : groups, + 'Cross Sections' : cross_sections_by_MT + }) + + return gendf_data + + +def handle_local_file_input(mt_dict, cumulative_data, + gendf_paths, gendf_dir, args): + """ + Method for extracting and analyzing data from preprocessed GENDF files + that are saved locally. The data extracted is stored in a Pandas + DataFrame. + + Arguments: + mt_dict (dict): Dictionary formatted data structure for mt_table.csv, + along with changes in KZA and emitted_particles. + cumulative_data (pandas.core.frame.DataFrame): Empty Pandas DataFrame + in which to cumulatively store data extracted from GENDF files. + gendf_paths (list of str): List containing all of the file paths to + the GENDF files to be analyzed. + gendf_dir (str): Path for the directory containing the relevant GENDF + file(s). + args (argparse.Namespace): Argparse object that contains the user + specified arguments for executing the program. + + Returns: + cumulative_data (pandas.core.frame.DataFrame): Cumulatively filled + Pandas DataFrame containing all of the data extracted from the + GENDF file(s). + """ + + if not gendf_paths: + gendf_paths = args.paths + + if not isinstance(gendf_paths, list): + gendf_paths = [gendf_paths] + + # If the user inputs a path to a directory containing GENDF files for the + # local file option, then search for the GENDF files of the element(s) + if gendf_dir or Path(gendf_paths[0]).is_dir(): + gendf_paths = search_gendf_directory(args, gendf_dir, gendf_paths) + + for gendf_path in gendf_paths: + + pKZA, A, element = tpp.extract_gendf_pkza(gendf_path) + matb, MTs, file_obj = tpp.extract_endf_specs(gendf_path, 'gendf') + + logger.info(f"GENDF file path: {gendf_path}") + logger.info(f"Parent KZA (pKZA): {pKZA}") + logger.info(f'MTs: {MTs}') + + gendf_data = iterate_MTs(MTs, file_obj, mt_dict, pKZA) + cumulative_data = pd.concat([cumulative_data, gendf_data], + ignore_index= True) + + logger.info( + f'Finished iterating for {element}-{A}{" "*20}{"-"*49}' + ) + + return cumulative_data + +def handle_TENDL_downloads(args, mt_dict): + """ + Method for downloading ENDF/PENDF files from the TENDL 2017 database, + using the NJOY GROUPR module to convert these to a group-wise file, + and then extracting and analyzing the resultant data. + + Arguments: + args (argparse.Namespace): Argparse object that contains the user + specified arguments for executing the program. + mt_dict (dict): Dictionary formatted data structure for mt_table.csv, + along with changes in KZA and emitted_particles. + + Returns: + gendf_paths (list of str): List containing all of the file paths to + the GENDF files that were processed from ENDF/PENDF files by NJOY. + gendf_dir (str): Path for the directory containing the GENDF file(s). + + """ + + elements = groupr_tools.elements.keys( + ) if args.element == ['all'] or not args.element else args.element + + A_vals = args.mass_number + + gendf_paths = [] + + for element in elements: + if A_vals == ['all'] or not A_vals: + A_vals = asyncio.run(tpp.identify_tendl_isotopes(element)) + logger.info( + f'All isotopes of {element} in the TENDL database: {A_vals}' + ) + + for A in A_vals: + endf_path = tpp.download_tendl(element, A, 'endf') + pendf_path = tpp.download_tendl(element, A, 'pendf') + + material_id, MTs = tpp.extract_endf_specs(endf_path, 'endf') + + card_deck = groupr_tools.groupr_input_file_format(material_id, + MTs, + element, + A, + mt_dict) + groupr_tools.groupr_input_file_writer(card_deck, MTs) + + gendf_path, gendf_dir = groupr_tools.run_njoy(card_deck, element, + A, material_id) + + gendf_paths.extend(gendf_path) + + groupr_tools.njoy_file_cleanup() + + return gendf_paths, gendf_dir + +############################################################################## + +def fendl3_2b_retrofit(): + """ + Main method when run as a command line script. + """ + + # Initialize arguments, DataFrame to store data, and load in MT reference + args = fendl_args() + cumulative_data = rxd.initialize_dataframe() + gendf_paths = [] + gendf_dir = None + mt_dict, dir = rxd.process_mt_table('mt_table.csv') + + # Conditionally download and process files from the TENDL 2017 database + if not args.paths: + gendf_paths, gendf_dir = handle_TENDL_downloads(args, mt_dict) + + # Extract and store data from GENDF files + cumulative_data = handle_local_file_input(mt_dict, + cumulative_data, + gendf_paths = gendf_paths, + gendf_dir = gendf_dir, + args = args) + + # Save to CSV + cumulative_data.to_csv(f'{dir}/gendf_data.csv', index=False) + logger.info('Saved extracted GENDF data to gendf_data.csv') + +############################################################################## + +if __name__ == '__main__': + fendl3_2b_retrofit() \ No newline at end of file diff --git a/src/DataLib/fendl32B_retrofit/groupr_tools.py b/src/DataLib/fendl32B_retrofit/groupr_tools.py new file mode 100644 index 0000000..ceb6b66 --- /dev/null +++ b/src/DataLib/fendl32B_retrofit/groupr_tools.py @@ -0,0 +1,298 @@ +# Import packages +import subprocess +from logging_config import logger +from pathlib import Path +from reaction_data import establish_directory + +# Define constants +NENDF = 20 # unit for endf tape +NPEND = 21 # unit for pendf tape +NGOUT1 = 0 # unit for input gout tape (default=0) +NGOUT2 = 31 # unit for output gout tape (default=0) +IGN = 17 # neutron group structure option (corresponding to Vitamin J) +IGG = 0 # gamma group structure option +IWT = 11 # weight function option (corresponding to Vitamin E) +LORD = 0 # Legendre order +NTEMP = 1 # number of temperatures (default=1) +NSIGZ = 1 # number of sigma zeroes (default=1) +IPRINT = 1 # long print option (0/1=minimum/maximum) --(default=1) +ISMOOTH = 1 # switch on/off smoother operation (1/0, default=1=on) +TEMP = 293.16 # temperature in Kelvin +SIGZ = 0 # sigma zero values (including infinity) +MFD = 3 # file to be processed +MATD = 0 # next mat number to be processed +DIR = establish_directory() + +# Dictionary of elements in the Periodic Table +elements = [ + 'H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', + 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar', 'K', 'Ca', + 'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', + 'Ga', 'Ge', 'As', 'Se', 'Br', 'Kr', 'Rb', 'Sr', 'Y', 'Zr', + 'Nb', 'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', + 'Sb', 'Te', 'I', 'Xe', 'Cs', 'Ba', 'La', 'Ce', 'Pr', 'Nd', + 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', 'Er', 'Tm', 'Yb', + 'Lu', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg', + 'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn', 'Fr', 'Ra', 'Ac', 'Th', + 'Pa', 'U', 'Np', 'Pu', 'Am', 'Cm', 'Bk', 'Cf', 'Es', 'Fm', + 'Md', 'No', 'Lr', 'Rf', 'Db', 'Sg', 'Bh', 'Hs', 'Mt', 'Ds', + 'Rg', 'Cn', 'Nh', 'Fl', 'Mc', 'Lv', 'Ts', 'Og' +] +elements = dict(zip(elements, range(1, len(elements)+1))) + +def format_card(card_number, card_content, MTs): + """ + Format individual "cards" for the NJOY input cards to run with GROUPR. + Formatting and terminology based on the NJOY user manual: + (https://github.com/njoy/NJOY2016-manual/raw/master/njoy16.pdf) + + Arguments: + card_number (int): Individual identifier of "card" in input "deck". + card_content (list): Values to be written on each individual "card". + MTs (list of int): List of reaction types (MT's) present in the + ENDF/PENDF files. + + Returns: + card_str (str): Concatenated string of an individual "card's" + contents. + """ + + # Initialize string and concatenate contents of the card with it + card_str = '' + gen_str = ' ' + ' '.join(map(str, card_content)) + if card_number == 9: + card_str = ' ' + '/\n '.join(card_content) + '/\n' + elif card_number == 4: + card_str += gen_str + '\n' + else: + card_str += gen_str + '/\n' + return card_str + +def groupr_input_file_format(matb, MTs, element, A, mt_dict): + + """" + Format the input "deck" to run NJOY from individually formatted cards. + Most parameters are predefined as constants, as necessary for a GROUPR + run to write a group-wise file (GENDF) based on the ENDF and PENDF + files with a Vitamin-J 175 group structure and a Vitamin-E weighting + function. Other parameters are isotope specific, such as "matb", which + corresponds to the NJOY naming convention for the material ID, which + are separately extracted from the ENDF file to be referenced. + + Formatting and terminology based on the NJOY user manual: + (https://github.com/njoy/NJOY2016-manual/raw/master/njoy16.pdf) + + Arguments: + matb (int): Unique material ID extracted from the ENDF base file. + MTs (list of int): List of reaction types (MT's) present in the + ENDF/PENDF files. + element (str): Chemical symbol for element of interest. + A (str or int): Mass number for selected isotope. + If the target is an isomer, "m" after the mass number, + so A must be input as a string. + mt_dict (dict): Reference dictionary containing reaction information + for each MT number pre-defined in the ENDF manual. + (https://www.oecd-nea.org/dbdata/data/manual-endf/endf102_MT.pdf) + + Returns: + cards (dict): Dictionary containing each "card" identified by its card + number. + """ + + cards = {} + + cards[1] = [NENDF, NPEND, NGOUT1, NGOUT2] + # matb -- (already defined) -- material to be processed + cards[2] = [matb, IGN, IGG, IWT, LORD, NTEMP, NSIGZ, IPRINT] + Z = str(elements[element]).zfill(2) + title = f'"{Z}-{element}-{A} for TENDL 2017"' + cards[3] = [title] + cards[4] = [TEMP] + cards[5] = [SIGZ] + mtd = MTs # sections to be processed + cards[9] = [] + for MT in MTs: + # Description of section to be processed + mtname = mt_dict[str(MT)]['Reaction'] + card9_line = f'{MFD} {MT} "{mtname}"' + cards[9].append(card9_line) + cards[10] = [MATD] + + return cards + +def groupr_input_file_writer(cards, MTs): + """" + Write out the NJOY GROUPR input card by formatting each card line by line. + + Arguments: + cards (dict): Dictionary containing each "card" identified by its card + number. + MTs (list of int): List of reaction types (MT's) present in the + ENDF/PENDF files. + + Returns: + None + """ + + # Write the input deck to the groupr.inp file + with open(f'{DIR}/groupr.inp', 'w') as f: + f.write('groupr\n') + for card_num, card in cards.items(): + f.write(format_card(card_num, card, MTs)) + f.write(' 0/\nstop') + +def set_gendf_saving(save_directory, element, A): + """ + Establish the save path for the GENDF file in the desired directory. + + Arguments: + save_directory (str): Folder in which to save the GENDF file. + element (str): Chemical symbol for element of interest. + A (str or int): Mass number for selected isotope. + + Returns: + gendf_path (str): File path to the newly created GENDF file. + """ + + # Create save_directory if it does not already exist + save_directory = Path(save_directory) + if not save_directory.exists(): + save_directory.mkdir(parents = True) + + gendf_path = f'{save_directory}/tendl_2017_{element}{A.zfill(3)}.gendf' + return gendf_path + +def text_insertion(string, identifier, new_text, file_lines): + """ + (Add docstring) + """ + + index = string.rfind(identifier) + line_number = string[:index].count('\n') + file_lines.insert(line_number + 1, new_text) + return file_lines + +def ensure_gendf_markers(gendf_path, matb): + """ + Edit the GENDF files produced from an NJOY GROUPR run to include file and + section records that are not automatically written out to the file by + NJOY. Missing these records will not cause errors, but will raise + messages when they are read by ENDFtk, which expects these markers, so + this method ensures that they are present. Edits will only be made if + the SEND record for MF1 or the FEND record for MF3 are not present. + The formatting for these records can be found at: + https://t2.lanl.gov/nis/endf/intro06.html + + Arguments: + gendf_path (str): File path to the newly created GENDF file. + matb (int): Unique material ID for the material in the GENDF file. + + Returns: + None + """ + + # In ENDF-6 formatted files, there are 66 characters/columns of whitespace + # before the values in record-keeping lines + whitespace = ' ' * 66 + + # Define identifiers and corresponding new lines + mf1_identifier = f'{matb} 1451 ' + mf3_identifier = f'{matb} 3 099999' + matb = str(matb).zfill(4) + mf1_SEND_RECORD = f'{whitespace}{matb} 1 099999' + mf3_FEND_RECORD = f'{whitespace}{matb} 0 0 0' + + with open(gendf_path, 'r') as gendf_file: + file_str = gendf_file.read() + file_lines = file_str.splitlines() + + updates = [ + (mf3_identifier, mf3_FEND_RECORD), + (mf1_identifier, mf1_SEND_RECORD) + ] + + for identifier, new_line in updates: + last_line_index = file_str.rfind(identifier) + line_number = file_str[:last_line_index].count('\n') + file_lines.insert(line_number + 1, new_line) + + new_file_str = '\n'.join(file_lines) + '\n' + + with open(gendf_path, 'w') as gendf_file: + gendf_file.write(new_file_str) + +def run_njoy(cards, element, A, matb): + """ + Use subprocess to run NJOY given a pre-written input card to convert a + pair of ENDF and PENDF files to a GENDF file and save it locally. + + Arguments: + cards (dict): Dictionary containing each "card" + identified by its card number. + element (str): Chemical symbol for element of interest. + A (str or int): Mass number for selected isotope. + If the target is an isomer, "m" after the mass number, + so A must be input as a string. + matb (int): Unique material ID for the material in the files. + + Returns: + gendf_path (str): File path to the newly created GENDF file. + """ + + # Define the input files + INPUT = f'{DIR}/groupr.inp' + OUTPUT = f'{DIR}/groupr.out' + + # Run NJOY + result = subprocess.run(['njoy'], input=open(INPUT).read(), + text= True, capture_output=True) + with open(OUTPUT, 'w') as output_file: + output_file.write(result.stdout) + + # If the run is successful, log out the output + # and make a copy of the file as a .GENDF file + if result.stderr == '': + output = subprocess.run(['cat', 'output'], + capture_output=True, text = True) + title = cards[3][0][1:-1] + title_index = output.stdout.find(title) + logger.info( + 'Selected output of the latest NJOY run: \n' + f'\n{output.stdout[:title_index + len(title)]}\n' + ) + + save_directory = f'{DIR}/gendf_files' + gendf_path = set_gendf_saving(save_directory, element, A) + subprocess.run(['cp', 'tape31', gendf_path]) + ensure_gendf_markers(gendf_path, matb) + + return gendf_path, save_directory + else: + logger.error(result.stderr) + +def njoy_file_cleanup(output_path = f'{DIR}/njoy_ouput'): + """ + Clean up repository from unnecessary intermediate files from NJOY run. + + Arguments: + output_path (str, optional): The save path for the NJOY output. + Defaults to f'{DIR}/njoy_output', which will save the file in the + same directory as all other saved files from the script run. + + Returns: + None + """ + + njoy_files = [f'{DIR}/groupr.inp', f'{DIR}/groupr.out', + 'tape20', 'tape21', 'tape31'] + for file in njoy_files: + if file == f'{DIR}/groupr.out': + with open(file, 'r') as f: + groupr_out = f.read() + logger.info( + f'GROUPR run-specific analytics: \n {groupr_out}' + ) + + subprocess.run(['rm', file]) + subprocess.run(['mv', 'output', output_path]) + logger.info(f'Full NJOY output can be found at {output_path}') \ No newline at end of file diff --git a/src/DataLib/fendl32B_retrofit/logging_config.py b/src/DataLib/fendl32B_retrofit/logging_config.py new file mode 100644 index 0000000..9fee38a --- /dev/null +++ b/src/DataLib/fendl32B_retrofit/logging_config.py @@ -0,0 +1,80 @@ +# Import packages +import logging +import textwrap +from reaction_data import establish_directory + +class CustomFormatter(logging.Formatter): + """ + Custom formatter to handle log messages and enforce character limits. + """ + + def format(self, record): + """ + Format a log record, applying line splitting based on message length. + + Arguments: + record (logging.LogRecord): The log record to be formatted. + + Returns: + str: The formatted log message. + """ + + # Format the timestamp and levelname + prefix = super().format(record) + + # Check if the record has a special flag indicating different format + if hasattr(record, 'use_default_format') and record.use_default_format: + # Just return the default formatted message without line splitting + return f'{prefix} {record.msg}\n' + + message_lines = textwrap.fill(record.msg, initial_indent=prefix + ' ', + subsequent_indent=' '*len(prefix) + ' ', + width=79, break_long_words=False) + + return f'{message_lines}\n' + +class CustomFilter(logging.Filter): + """ + Custom filter to apply different formatting based on a condition. + """ + + def filter(self, record): + """ + Determine if a log record should use default formatting based on its + content. + + Arguments: + record (logging.LogRecord): The log record to be checked and + potentially modified. + + Returns: + bool: Always returns True, allowing the log record to be processed + by the file handler. + """ + + njoy_flag = '*' * 77 + if njoy_flag in record.msg: + # Set a flag in the record to use default formatting + record.use_default_format = True + else: + # Ensure default formatting is applied for other messages + record.use_default_format = False + return True + +# Configure logger +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + +# Ensure that logger is saved in the same directory as the mt_table.csv file +dir = establish_directory() +file_handler = logging.FileHandler(f'{dir}/fendl3_retrofit.log', mode='w') +file_handler.setLevel(logging.INFO) + +formatter = CustomFormatter('%(asctime)s - %(levelname)s') +file_handler.setFormatter(formatter) + +custom_filter = CustomFilter() +file_handler.addFilter(custom_filter) + +logger.addHandler(file_handler) +logger.propagate = False \ No newline at end of file diff --git a/src/DataLib/fendl32B_retrofit/mt_table.csv b/src/DataLib/fendl32B_retrofit/mt_table.csv new file mode 100644 index 0000000..ae25ad0 --- /dev/null +++ b/src/DataLib/fendl32B_retrofit/mt_table.csv @@ -0,0 +1,538 @@ +MT,Reaction,Description +1,"(n, total)",Neutron total cross sections. +2,"(z,z0)",Elastic scattering cross section for incident particles. +3,"(z, nonelas.)",Nonelastic neutron cross section. +4,"(z,n)",Production of one neutron in the exit channel. +5,"(z,anything)",Sum of all reactions not given explicitly in another MT number. This is a partial reaction to be added to obtain MT=1 +10,"(z,contin.)",Total continuum reaction; includes all continuum reactions and excludes all discrete reactions. +11,"(z,2nd)","Production of two neutrons and a deuteron, plus a residua" +16,"(z,2n)","Production of two neutrons and a residual1. Sum of MT=875-891, if they are present" +17,"(z,3n)",Production of three neutrons and a residual +18,"(z,fission)","Particle-induced fission (sum of MT 19, 20, 21 and 38, if present)." +19,"(n,f)",First-chance neutron-induced fission +20,"(n,nf)",Second-chance neutron-induced fission +21,"(n,2nf)",Third-chance neutron-induced fission +22,"(z,nα)","Production of a neutron and an alpha particle, plus a residual" +23,"(n,n3α)","Production of a neutron and three alpha particles, plus a residua" +24,"(z,2nα)","Production of two neutrons and an alpha particle, plus a residual" +25,"(z,3nα)","Production of three neutrons and an alpha particle, plus a residual" +27,"(n,abs)",Absorption; sum of MT=18 and MT=102 through MT=117 +28,"(z,np)","Production of a neutron and a proton, plus a residual." +29,"(z,n2α)","Production of a neutron and two alpha particles, plus a residual." +30,"(z,2n2α)","Production of two neutrons and two alpha particles, plus a residual." +32,"(z,nd)","Production of a neutron and a deuteron, plus a residual." +33,"(z,nt) ","Production of a neutron and a triton, plus a residual." +34,"(z,n3He)","Production of a neutron and a 3He particle, plus a residual." +35,"(z,nd2α)","Production of a neutron, a deuteron, and 2 alpha particles, plus a residual." +36,"(z,nt2α)","Production of a neutron, a triton, and 2 alpha particles, plus a residual." +37,"(z,4n)","Production of 4 neutrons, plus a residual" +38,"(n,3nf)",Fourth-chance fission cross section +41,"(z,2np)","Production of 2 neutrons and a proton, plus a residual." +42,"(z,3np)","Production of 3 neutrons and a proton, plus a residual." +44,"(z,n2p)","Production of a neutron and 2 protons, plus a residual." +45,"(z,npα)","Production of a neutron, a proton, and an alpha particle, plus a residual." +50,"(y,n0)","Production of a neutron, leaving the residual nucleus in the ground state." +51,"(z,n1)","Production of a neutron, with residual in the 1st excited state." +52,"(z,n2)","Production of a neutron, with residual in the 2nd excited state" +53,"(z,n3)",... +54,"(z,n4)",... +55,"(z,n5)",... +56,"(z,n6)",... +57,"(z,n7)",... +58,"(z,n8)",... +59,"(z,n9)",... +60,"(z,n10)",... +61,"(z,n11)",... +62,"(z,n12)",... +63,"(z,n13)",... +64,"(z,n14)",... +65,"(z,n15)",... +66,"(z,n16)",... +67,"(z,n17)",... +68,"(z,n18)",... +69,"(z,n19)",... +70,"(z,n20)",... +71,"(z,n21)",... +72,"(z,n22)",... +73,"(z,n23)",... +74,"(z,n24)",... +75,"(z,n25)",... +76,"(z,n26)",... +77,"(z,n27)",... +78,"(z,n28)",... +79,"(z,n29)",... +80,"(z,n30)",... +81,"(z,n31)",... +82,"(z,n32)",... +83,"(z,n33)",... +84,"(z,n34)",... +85,"(z,n35)",... +86,"(z,n36)",... +87,"(z,n37)",... +88,"(z,n38)",... +89,"(z,n39)",... +90,"(z,n40)",... +91,"(z,nc)",Production of a neutron in the continuum not included in the above discrete representation. +101,"(n,disap)",Neutron disappearance; equal to sum of MT=102-117. +102,"(z,γ)",Radiative capture. +103,"(z,p)","Production of a proton, plus a residual. Sum of MT=600-649, if they are present." +104,"(z,d)","Production of a deuteron, plus a residual. Sum of MT=650-699, if they are present." +105,"(z,t)","Production of a triton, plus a residual. Sum of MT=700-749, if they are present." +106,"(z,3He)","Production of a 3He particle plus a residual. Sum of MT=750-799, if they are present." +107,"(z,α)","Production of an alpha particle, plus a residual. Sum of MT=800-849, if they are present." +108,"(z,2α)","Production of 2 alpha particles, plus a residual." +109,"(z,3α)","Production of 3 alpha particles, plus a residual." +111,"(z,2p)","Production of 2 protons, plus a residual." +112,"(z,pα)","Production a proton and an alpha particle, plus a residual." +113,"(z,t2α)","Production of a triton and 2 alpha particles, plus a residual." +114,"(z,d2α)","Production of a deuteron and 2 alpha particles, plus a residual." +115,"(z,pd)","Production of proton and a deuteron, plus a residual." +116,"(z,pt)","Production of proton and a triton, plus a residual." +117,"(z,dα)","Production of deuteron and an alpha particle, plus a residual." +151,"(n,RES)",Resonance parameters that can be used to calculate cross sections at different temperatures in the resolved and unresolved energy regions. +201,"(z,Xn)",Total neutron production. +202,"(z,Xγ)",Total gamma production. +203,"(z,Xp)",Total proton production. +204,"(z,Xd)",Total deuteron production. +205,"(z,Xt)",Total triton production +206,"(z,X3He)",Total 3He production. +207,"(z,Xα)",Total alpha particle production. +208,"(z,Xπ +)",Total π + production. +209,"(z,Xπ 0 )",Total π 0 production. +210,"(z,Xπ −)",Total π − production. +211,"(z,Xµ +)",Total µ + production. +212,"(z,Xµ −)",Total µ − production. +213,"(z,Xκ +)",Total κ + production. +214,"(z,Xκ 0 long)",Total κ 0 long production. +215,"(z,Xκ 0 short)",Total κ 0 short production. +216,"(z,Xκ −)",Total κ − production. +217,"(z,Xp−)",Total anti-proton production. +218,"(z,Xn−)",Total anti-neutron production. +251,"(n,...)","µ, average cosine of the scattering angle (laboratory system) for elastic scattering of neutrons." +252,"(n,...)","ξ, average logarithmic energy decrement for elastic scattering of neutrons." +253,"(n,...)","γ, average of the square of the logarithmic energy decrement divided by twice the average logarithmic energy decrement, for elastic scattering of neutrons." +301,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +302,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +303,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +304,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +305,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +306,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +307,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +308,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +309,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +310,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +311,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +312,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +313,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +314,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +315,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +316,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +317,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +318,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +319,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +320,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +321,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +322,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +323,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +324,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +325,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +326,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +327,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +328,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +329,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +330,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +331,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +332,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +333,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +334,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +335,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +336,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +337,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +338,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +339,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +340,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +341,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +342,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +343,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +344,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +345,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +346,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +347,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +348,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +349,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +350,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +351,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +352,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +353,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +354,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +355,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +356,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +357,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +358,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +359,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +360,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +361,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +362,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +363,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +364,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +365,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +366,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +367,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +368,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +369,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +370,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +371,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +372,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +373,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +374,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +375,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +376,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +377,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +378,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +379,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +380,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +381,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +382,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +383,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +384,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +385,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +386,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +387,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +388,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +389,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +390,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +391,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +392,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +393,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +394,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +395,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +396,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +397,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +398,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +399,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +400,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +401,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +402,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +403,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +404,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +405,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +406,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +407,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +408,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +409,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +410,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +411,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +412,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +413,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +414,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +415,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +416,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +417,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +418,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +419,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +420,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +421,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +422,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +423,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +424,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +425,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +426,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +427,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +428,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +429,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +430,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +431,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +432,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +433,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +434,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +435,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +436,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +437,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +438,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +439,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +440,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +441,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +442,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +443,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +444,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +445,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +446,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +447,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +448,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +449,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +450,"(z,...)","Energy release parameters, , for total and partial cross sections; MT= 300 plus the reaction MT number, e.g., MT=302 is the elastic scattering kerma" +451,"(z,...)",Heading or title information; given in File 1 only. +452,"(z,...)","νT , average total (prompt plus delayed) number of neutrons released per fission event." +454,"(z,...)",Independent fission product yield data +455,"(z,...)","νd, average number of delayed neutrons released per fission event." +456,"(z,...)","νp, average number of prompt neutrons released per fission event." +457,"(z,...)",Radioactive decay data. +458,"(n,...)",Energy release in fission for incident neutrons. +459,"(z,...)",Cumulative fission product yield data. +600,"(z,p0)",Production of a proton leaving the residual nucleus in the ground state. +601,"(z,p1)","Production of a proton, with residual in the 1st excited state." +602,"(z,p2)","Production of a proton, with residual in the 2nd excited state." +603,"(z,p3)","Production of a proton, with residual in the 3rd excited state." +604,"(z,p4)","Production of a proton, with residual in the 4th excited state." +605,"(z,p5)",... +606,"(z,p6)",... +607,"(z,p7)",... +608,"(z,p8)",... +609,"(z,p9)",... +610,"(z,p10)",... +611,"(z,p11)",... +612,"(z,p12)",... +613,"(z,p13)",... +614,"(z,p14)",... +615,"(z,p15)",... +616,"(z,p16)",... +617,"(z,p17)",... +618,"(z,p18)",... +619,"(z,p19)",... +620,"(z,p20)",... +621,"(z,p21)",... +622,"(z,p22)",... +623,"(z,p23)",... +624,"(z,p24)",... +625,"(z,p25)",... +626,"(z,p26)",... +627,"(z,p27)",... +628,"(z,p28)",... +629,"(z,p29)",... +630,"(z,p30)",... +631,"(z,p31)",... +632,"(z,p32)",... +633,"(z,p33)",... +634,"(z,p34)",... +635,"(z,p35)",... +636,"(z,p36)",... +637,"(z,p37)",... +638,"(z,p38)",... +639,"(z,p39)",... +640,"(z,p40)",... +641,"(z,p41)",... +642,"(z,p42)",... +643,"(z,p43)",... +644,"(z,p44)",... +645,"(z,p45)",... +646,"(z,p46)",... +647,"(z,p47)",... +648,"(z,p48)",... +649,"(z,pc)",Production of a proton in the continuum not included in the above discrete representation +650,"(z,d0)",Production of a deuteron leaving the residual nucleus in the ground state +651,"(z,d1)","Production of a deuteron, with the residual in the 1st excited state." +652,"(z,d2)","Production of a deuteron, with the residual in the 2nd excited state." +653,"(z,d3)",... +654,"(z,d4)",... +655,"(z,d5)",... +656,"(z,d6)",... +657,"(z,d7)",... +658,"(z,d8)",... +659,"(z,d9)",... +660,"(z,d10)",... +661,"(z,d11)",... +662,"(z,d12)",... +663,"(z,d13)",... +664,"(z,d14)",... +665,"(z,d15)",... +666,"(z,d16)",... +667,"(z,d17)",... +668,"(z,d18)",... +669,"(z,d19)",... +670,"(z,d20)",... +671,"(z,d21)",... +672,"(z,d22)",... +673,"(z,d23)",... +674,"(z,d24)",... +675,"(z,d25)",... +676,"(z,d26)",... +677,"(z,d27)",... +678,"(z,d28)",... +679,"(z,d29)",... +680,"(z,d30)",... +681,"(z,d31)",... +682,"(z,d32)",... +683,"(z,d33)",... +684,"(z,d34)",... +685,"(z,d35)",... +686,"(z,d36)",... +687,"(z,d37)",... +688,"(z,d38)",... +689,"(z,d39)",... +690,"(z,d40)",... +691,"(z,d41)",... +692,"(z,d42)",... +693,"(z,d43)",... +694,"(z,d44)",... +695,"(z,d45)",... +696,"(z,d46)",... +697,"(z,d47)",... +698,"(z,d48)",... +699,"(z,dc)",Production of a deuteron in the continuum not included in the above discrete representation. +700,"(z,t0)",Production of a triton leaving the residual nucleus in the ground state. +701,"(z,t1)","Production of a triton, with residual in the 1st excited state" +702,"(z,t2)","Production of a triton, with residual in the 2nd excited state." +703,"(z,t3)",... +704,"(z,t4)",... +705,"(z,t5)",... +706,"(z,t6)",... +707,"(z,t7)",... +708,"(z,t8)",... +709,"(z,t9)",... +710,"(z,t10)",... +711,"(z,t11)",... +712,"(z,t12)",... +713,"(z,t13)",... +714,"(z,t14)",... +715,"(z,t15)",... +716,"(z,t16)",... +717,"(z,t17)",... +718,"(z,t18)",... +719,"(z,t19)",... +720,"(z,t20)",... +721,"(z,t21)",... +722,"(z,t22)",... +723,"(z,t23)",... +724,"(z,t24)",... +725,"(z,t25)",... +726,"(z,t26)",... +727,"(z,t27)",... +728,"(z,t28)",... +729,"(z,t29)",... +730,"(z,t30)",... +731,"(z,t31)",... +732,"(z,t32)",... +733,"(z,t33)",... +734,"(z,t34)",... +735,"(z,t35)",... +736,"(z,t36)",... +737,"(z,t37)",... +738,"(z,t38)",... +739,"(z,t39)",... +740,"(z,t40)",... +741,"(z,t41)",... +742,"(z,t42)",... +743,"(z,t43)",... +744,"(z,t44)",... +745,"(z,t45)",... +746,"(z,t46)",... +747,"(z,t47)",... +748,"(z,t48)",... +749,"(z,tc) ",Production of a triton in the continuum not included in the above discrete representation. +750,"(n,3He0)",Production of a 3He particle leaving the residual nucleus in the ground state. +751,"(z,3He1)","Production of a 3He, with residual in the 1st excited state." +752,"(z,3He2)","Production of a 3He, with residual in the 2nd excited state." +753,"(z,3He3)",... +754,"(z,3He4)",... +755,"(z,3He5)",... +756,"(z,3He6)",... +757,"(z,3He7)",... +758,"(z,3He8)",... +759,"(z,3He9)",... +760,"(z,3He10)",... +761,"(z,3He11)",... +762,"(z,3He12)",... +763,"(z,3He13)",... +764,"(z,3He14)",... +765,"(z,3He15)",... +766,"(z,3He16)",... +767,"(z,3He17)",... +768,"(z,3He18)",... +769,"(z,3He19)",... +770,"(z,3He20)",... +771,"(z,3He21)",... +772,"(z,3He22)",... +773,"(z,3He23)",... +774,"(z,3He24)",... +775,"(z,3He25)",... +776,"(z,3He26)",... +777,"(z,3He27)",... +778,"(z,3He28)",... +779,"(z,3He29)",... +780,"(z,3He30)",... +781,"(z,3He31)",... +782,"(z,3He32)",... +783,"(z,3He33)",... +784,"(z,3He34)",... +785,"(z,3He35)",... +786,"(z,3He36)",... +787,"(z,3He37)",... +788,"(z,3He38)",... +789,"(z,3He39)",... +790,"(z,3He40)",... +791,"(z,3He41)",... +792,"(z,3He42)",... +793,"(z,3He43)",... +794,"(z,3He44)",... +795,"(z,3He45)",... +796,"(z,3He46)",... +797,"(z,3He47)",... +798,"(z,3He48)",... +799,"(n,3Hec)",Production of a 3He in the continuum not included in the above discrete representation. +800,"(z,α0)",Production of an alpha particle leaving the residual nucleus in the ground state. +801,"(z,α1)","Production of an alpha particle, with residual in the 1st excited state." +802,"(z,α2)","Production of an alpha particle, with residual in the 2nd excited state." +803,"(z,α3)",... +804,"(z,α4)",... +805,"(z,α5)",... +806,"(z,α6)",... +807,"(z,α7)",... +808,"(z,α8)",... +809,"(z,α9)",... +810,"(z,α10)",... +811,"(z,α11)",... +812,"(z,α12)",... +813,"(z,α13)",... +814,"(z,α14)",... +815,"(z,α15)",... +816,"(z,α16)",... +817,"(z,α17)",... +818,"(z,α18)",... +819,"(z,α19)",... +820,"(z,α20)",... +821,"(z,α21)",... +822,"(z,α22)",... +823,"(z,α23)",... +824,"(z,α24)",... +825,"(z,α25)",... +826,"(z,α26)",... +827,"(z,α27)",... +828,"(z,α28)",... +829,"(z,α29)",... +830,"(z,α30)",... +831,"(z,α31)",... +832,"(z,α32)",... +833,"(z,α33)",... +834,"(z,α34)",... +835,"(z,α35)",... +836,"(z,α36)",... +837,"(z,α37)",... +838,"(z,α38)",... +839,"(z,α39)",... +840,"(z,α40)",... +841,"(z,α41)",... +842,"(z,α42)",... +843,"(z,α43)",... +844,"(z,α44)",... +845,"(z,α45)",... +846,"(z,α46)",... +847,"(z,α47)",... +848,"(z,α48)",... +849,"(z,αc) ",Production of an alpha particle in the continuum not included in the above discrete representation. +875,"(z,2n0)",Production of 2 neutrons with residual in the ground state. +876,"(z,2n1)",Production of 2 neutrons with residual in the 1st excited state. +877,"(z,2n2)",Production of 2 neutrons with residual in the 2nd excited state. +878,"(z,2n3)",... +879,"(z,2n4)",... +880,"(z,2n5)",... +881,"(z,2n6)",... +882,"(z,2n7)",... +883,"(z,2n8)",... +884,"(z,2n9)",... +885,"(z,2n10)",... +886,"(z,2n11)",... +887,"(z,2n12)",... +888,"(z,2n13)",... +889,"(z,2n14)",... +890,"(z,2n15)",... +891,"(z,2nc)",Production of 2 neutrons in the continuum not included in the above discrete representation. \ No newline at end of file diff --git a/src/DataLib/fendl32B_retrofit/reaction_data.py b/src/DataLib/fendl32B_retrofit/reaction_data.py new file mode 100644 index 0000000..e9f3c9d --- /dev/null +++ b/src/DataLib/fendl32B_retrofit/reaction_data.py @@ -0,0 +1,216 @@ +import csv +from numpy import array +import pandas as pd +from pathlib import Path + +# Define a dictionary containing all of the pathways for neutron and proton +# changes in a nucleus following neutron activation + +# emitted delta N delta P +NP_dict = {'n' : array([-1 , 0 ]), # neutron emission + 'p' : array([ 0 , -1 ]), # proton emission + 'd' : array([-1 , -1 ]), # deuteron emission + 't' : array([-2 , -1 ]), # triton emission + '3He' : array([-1 , -2 ]), # helium-3 emission + 'α' : array([-2 , -2 ]), # alpha emission + 'γ' : array([ 0 , 0 ]) # gamma emission +} + +def initialize_dataframe(): + """ + Initialize an empty Pandas DataFrame in which to store extracted data from + TENDL 2017 files. + + Arguments: + None + + Returns: + None + """ + return pd.DataFrame({ + 'Parent KZA' : [], + 'Daughter KZA' : [], + 'Emitted Particles' : [], + 'Non-Zero Groups' : [], + 'Cross Sections' : [] + }) + +def count_emitted_particles(particle, emitted_particle_string): + """ + Count emitted particles from a reaction given a target particle + and the particles produced in a neutron activation reaction. + + Arguments: + particle (str): Name of the target particle produced in the reaction. + Options include n, p, alpha, d, t, and 3He, corresponding to + neutrons, protons, alpha particles, deuterons, tritons, + and helium-3 nuclides. + emitted_particle_string (str): Particle product(s) of the neutron + activation, of the format 'p' for a single proton for example or + '2n' for two neutrons etc. + + Returns: + particle_count (int or None): Count of the target particle present in + the product. If particles not present, returns None rather than 0. + """ + + particle_index = emitted_particle_string.find(particle) + number_str = '' + for i in range(particle_index - 1, -1, -1): + if emitted_particle_string[i].isdigit(): + number_str = emitted_particle_string[i] + number_str + else: + break + + if number_str: + particle_count = int(number_str) + elif particle in emitted_particle_string: + particle_count = 1 + else: + particle_count = None + + return particle_count + +def isomer_check(emitted_particle_string): + """ + Check the isomeric status of a neutron-activated nucleus. + By the formatting conventions of ENDF reaction types, + if the string of a reaction product ends with a digit, + that signifies the excitation state of the nucleus, so + this function looks for and stores these values. + + Arguments: + emitted_particle_string (str): Particle product(s) of the neutron + activation. + + Returns: + isomeric_value (int): Nuclear excitation level of the activated + nucleus. For a nucleus in the ground state, isomeric_state = 0. + """ + + last_digits_str = '' + for char in reversed(emitted_particle_string): + if char.isdigit(): + last_digits_str = char + last_digits_str + else: + break + isomeric_value = int(last_digits_str) if last_digits_str else 0 + return isomeric_value + +def emission_breakdown(emitted_particles): + """ + Identify the particles and their respective counts from a particular + nuclear decay in response to neutron activation. These tallies are + saved in a dictionary with the name of the particles as the keys. + + Arguments: + emitted_particles (str): Particle product(s) of a neutron activation + reaction formatted in a singular string (i.e. np for a + (neutron, proton) emission. + + Returns: + emission_dict (dict): Dictionary containing each individual particle + type and their respetive counts. For an np emission, this would + read out as {'n': 1, 'p': 1}. + """ + + emission_dict = { + particle : count_emitted_particles(particle, emitted_particles) + for particle in NP_dict.keys() + if particle in emitted_particles + } + return emission_dict + +def nucleon_changes(emission_dict): + """ + Calculate the change in neutrons and protons in a nucleus in response to + neutron activation and given a particular set of emitted particles. + + Arguments: + emission_dict (dict): Dictionary containing each individual particle + type in an emission from a nuclear decay and their respective + counts. For an np emission, this would read out as + {'n': 1, 'p': 1}. + + Returns: + NP_change (numpy.array): A one-dimensional array indicating the net + change in neutrons and protons in a nucleus as a result of neutron + activation and subsequent decay. The array is in the format of + array([neutron_change, proton_change]). + """ + + # delta N delta P + NP_change = array([1 , 0 ]) # neutron activation + + for particle, count in emission_dict.items(): + NP_change += count * NP_dict[particle] + + return NP_change + +def establish_directory(file_path = 'mt_table.csv'): + """ + Determine if the target file is in the current working directory or if it + is in a daughter directory. This is used to allow for + fendl3_retrofit.py to be executed either from its own directory or its + parent directory, while always ensuring the files it produces to be + saved in the directory fendl32B_retrofit. + + Arguments: + file_path (str, optional): Path to the target file. + Defaults to "mt_table.csv" so that files get saved in the same + directory as the input table necessary to run the main program. + + Returns: + dir (str): Directory signifier, either "." if the main program is run + in the same directory as the file associated with file_path or + "fendl32B_retrofit", where the reference file would otherwise be + located if this is being run from the parent directory. + """ + + if Path.exists(Path(file_path)): + dir = '.' + else: + dir = 'fendl32B_retrofit' + + return dir + +def process_mt_table(csv_path): + """ + Load in the mt_table.csv file which contains Table B.1 - + "Reaction Type Numbers MT" from the ENDF-6 manual which can be found + at https://www.oecd-nea.org/dbdata/data/manual-endf/endf102_MT.pdf. + Given this, calculate the resultant change in KZA associated with each + MT value in the table and tally the particle emissions associated with + these reactions. Store all of this data in a dictionary of the format: + {'MT' : {'Reaction' : (z , emission), + 'delKZA' : change_in_KZA, + 'Emitted Particles' : string_of_particles + } + } + + Arguments: + csv_path (str): File path to mt_table.csv + This should be in the same repository. + + Returns: + mt_dict (dict): Dictionary formatted data structure for mt_table.csv, + along with changes in KZA and emitted_particles. + """ + dir = establish_directory(csv_path) + csv_path = f'{dir}/{csv_path}' + mt_dict = {} + + with open(csv_path, 'r') as f: + csv_reader = csv.DictReader(f) + for row in csv_reader: + emitted_particles = row['Reaction'].split(',')[1][:-1] + emission_dict = emission_breakdown(emitted_particles) + change_N, change_P = nucleon_changes(emission_dict) + M = isomer_check(emitted_particles) + mt_dict[row['MT']] = { + 'Reaction' : row['Reaction'], + 'delKZA' : (change_P * 1000 + change_P + change_N) * 10 + M, + 'Emitted Particles' : emitted_particles + } + + return mt_dict, dir \ No newline at end of file diff --git a/src/DataLib/fendl32B_retrofit/tendl_preprocessing.py b/src/DataLib/fendl32B_retrofit/tendl_preprocessing.py new file mode 100644 index 0000000..5c03487 --- /dev/null +++ b/src/DataLib/fendl32B_retrofit/tendl_preprocessing.py @@ -0,0 +1,243 @@ +# Import packages +import aiohttp +from bs4 import BeautifulSoup +import urllib.error +import urllib.request +from logging_config import logger +import ENDFtk + + +# Define constant(s) +TENDL_GEN_URL = 'https://tendl.web.psi.ch/tendl_2017' + +async def fetch_and_parse_html(session, url): + """ + Asynchronously fetch the content from the URL using the provided session. + + Arguments: + session (aiohttp.client.ClientSession): Aiohttp session to use for + making the request. + url (str): The URL from which to fetch content. + + Returns: + str or None: The content of the URL as a string if the request is + successful, signified by status code 200. Returns None if the + request is unsuccessful or an error occurs. + """ + + async with session.get(url) as response: + if response.status == 200: + html = await response.text() + soup = BeautifulSoup(html, 'html.parser') + links = soup.find_all('a') + return [link.get('href') for link in links if link.get('href')] + return [] + +async def identify_tendl_isotopes(element): + """ + Use asyncio and aiohttp to iterate over all possible mass numbers for a + given element to identify all of its isotopes and isomers in the TENDL + database. + + Arguments: + element (str): Chemical symbol for element of interest (i.e. Ti). + concurrency_limit (int, optional): The maximum number of concurrent + processes or sessions that can be handled at once. + + Returns: + A_vals (list of str): List of all of the mass numbers of isotopes that + have data stored in both ENDF (TENDL) and PENDF files in the TENDL + 2017 nuclear database. + """ + + A_vals = [] + async with aiohttp.ClientSession() as session: + tasks = [] + for A in range(1, 292): + for i in range(2): + A_str = str(A).zfill(3) + if i == 1: + A_str += 'm' + + navigation_page_url = ( + f'{TENDL_GEN_URL}/neutron_html/{element}/' + f'Neutron{element}{str(A).zfill(2)}.html' + ) + isotope_component = ( + f'/neutron_file/{element}/{element}{A_str}/' + f'lib/endf/n-{element}{A_str}.' + ) + tendl_url = TENDL_GEN_URL + isotope_component + 'tendl' + pendf_url = TENDL_GEN_URL + isotope_component + 'pendf' + + tasks.append((navigation_page_url, tendl_url, + pendf_url, A_str)) + + # Execute tasks and gather results + for navigation_page_url, tendl_url, pendf_url, A_str in tasks: + nav_urls = await fetch_and_parse_html(session, + navigation_page_url) + + if tendl_url in nav_urls and pendf_url in nav_urls: + A_vals.append(A_str) + + return A_vals + +def urllib_download(download_url, filetype): + """ + Use the urllib Request and Error packages to download the contents of + a webpage, if it exists + + Arguments: + download_url (str): Link to the webpage to download the desired file. + filetype (str): Either "ENDF" or "PENDF" filetypes to be downloaded + (case insensitive). + """ + + try: + with urllib.request.urlopen(download_url) as f: + temp_file = f.read().decode('utf-8') + except urllib.error.URLError as e: + if e.code == 404: + temp_file = None + raise FileNotFoundError( + f'{filetype.upper()} file does not exist at {download_url}' + ) + + return temp_file + +def download_tendl(element, A, filetype, save_path = None): + """ + Download ENDF/PENDF files from the TENDL 2017 database for specific isotopes. + + Arguments: + element (str): Chemical symbol for element of interest (i.e. Ti). + A (str or int): Mass number for selected isotope (i.e. 48). + If the target is an isomer, "m" after the mass number (i.e. 48m), + so A must be input as a string. + filetype (str): Either "ENDF" or "PENDF" filetypes to be downloaded + (case insensitive). + save_path (str, optional): User-defined file path for the + downloaded file. + + Defaults to None and will be otherwise defined internally. + + Returns: + save_path (str): File path for the file downloaded file. + """ + + # Ensure that A is properly formatted + A = A.zfill(4) if 'm' in A else str(A).zfill(3) + + file_handling = {'endf' : {'ext': 'tendl', 'tape_num': 20}, + 'pendf' : {'ext': 'pendf', 'tape_num': 21}} + + # Construct the filetype and isotope specific URL + isotope_component = ( + f'/neutron_file/{element}/{element}{A}/lib/endf/n-{element}{A}.' + ) + ext = file_handling[filetype.lower()]['ext'] + download_url = TENDL_GEN_URL + isotope_component + ext + logger.info(f'{filetype.upper()} URL: {download_url}') + + if save_path is None: + save_path = f'tape{file_handling[filetype.lower()]["tape_num"]}' + + temp_file = urllib_download(download_url, filetype) + + with open(save_path, 'w') as f: + f.write(temp_file) + + return save_path + +def extract_gendf_pkza(gendf_path): + """ + Read in and parse the contents of a GENDF file to construct the parent + KZA. KZA values are defined as ZZAAAM, where ZZ is the isotope's + atomic number, AAA is the mass number, and M is the isomeric state + (0 if non-isomeric). + + Arguments: + gendf_path (str): File path to the GENDF file being analyzed. + M (str, optional): Identifier of isomer, signified by the letter "M" + at the end of the mass number string. + + Defaults to None and will be otherwise defined internally. + + Returns: + pKZA (int): Parent KZA identifier. + A (int): Mass number of the parent nucleus. + element (str): Chemical name of the parent. + """ + + with open(gendf_path, 'r') as f: + first_line = f.readline() + Z, element, A = first_line.split('-')[:3] + + Z = int(Z) + M = 1 if 'm' in A.lower() else 0 + A = int(A.lower().split(' ')[0].split('m')[0]) + pKZA = (Z * 1000 + A) * 10 + M + return pKZA, A, element + +def extract_endf_specs(path, filetype): + """ + Extract the material ID and MT numbers from an ENDF or GENDF file. + + Arguments: + path (str): File path to the selected ENDF/GENDF file. + filetype (str): Either ENDF or GENDF (case insensitive) + + Returns: + endf_specs (list): List containing the following values from the file: + matb (int): Unique material ID extracted from the file. + MTs (list): List of reaction types (MT's) present in the file. + file (ENDFtk.tree.File or None): ENDFtk file object containing the + contents for a specific material's cross-section data. + Only returns the file for GENDF filetypes. + """ + + tape = ENDFtk.tree.Tape.from_file(path) + matb = tape.material_numbers[0] + # Set MF for cross sections + xs_MF = 3 + file = tape.material(matb).file(xs_MF) + # Extract the MT numbers that are present in the file + MTs = [MT.MT for MT in file.sections.to_list()] + + endf_specs = [matb, MTs] + if filetype.lower() == 'gendf': + endf_specs.append(file) + + return (endf_specs) + +def extract_cross_sections(file, MT): + """ + Parse through the contents of a GENDF file section to extract the + cross-section data for a specific reaction type (MT). + + Arguments: + file (ENDFtk.tree.File): ENDFtk file object containing a specific + material's cross-section data. + MT (int): Numerical identifier for the reaction type corresponding to + the file's sectional organization. + + Returns: + sigma_list (list): All of the cross-sections for a given reaction type + and material, listed as floating point numbers. If the run fails, + the function will just return an empty list. + """ + + section = file.section(MT).content + + # Only every 2nd line starting at the 3rd line has cross-section data. + lines = section.split('\n')[2:-2:2] + + # Extract the 3rd token and convert to more conventional string + # representation of a float + sigma_list = [ + float(line.split(' ')[2].replace('+','E+').replace('-','E-')) + for line in lines + ] + + return sigma_list \ No newline at end of file