diff --git a/tools/build_inp_blocks.py b/tools/build_inp_blocks.py index c0e8cfd..0880e1a 100644 --- a/tools/build_inp_blocks.py +++ b/tools/build_inp_blocks.py @@ -17,6 +17,7 @@ 'pulse_length': (float), 'pulse_length_unit': (str), 'flux_filepath' : (str), + 'flux_norm' : (float), 'pulse_history': (iterable of (int, float, str)), 'delay_dur' : (float), 'delay_dur_unit': (str) @@ -54,7 +55,7 @@ def make_flux_dict(child_dicts, flux_counter=None): for child_dict in child_dicts: if child_dict['type'] == 'pulse_entry': flux_dict[ - child_dict['flux_filepath']] = f'flux_{next(flux_counter)}' + (child_dict['flux_filepath'], child_dict['flux_norm'])] = f'flux_{next(flux_counter)}' elif child_dict['type'] == 'schedule': flux_dict |= make_flux_dict(child_dict['children'], flux_counter) @@ -66,8 +67,8 @@ def make_flux_block(flux_dict): Create the flux block of an ALARA input file. ''' flux_lines = "" - for flux_path, name in flux_dict.items(): - flux_lines += f"flux {name} {flux_path} 0 default\n" + for (flux_path, flux_norm), flux_name in flux_dict.items(): + flux_lines += f"flux {flux_name} {flux_path} {flux_norm} 0 default\n" return flux_lines + "\n" @@ -99,7 +100,7 @@ def make_schedule_block(child_dicts, ph_dict, flux_dict, sched_counter=None, sch current_sched_lines += ( f"{child_dict['pulse_length']}\t" f"{child_dict['pulse_length_unit']}\t" - f"{flux_dict[child_dict['flux_filepath']]}\t" + f"{flux_dict[(child_dict['flux_filepath'], child_dict['flux_norm'])]}\t" f"{ph_dict[tuple(child_dict['pulse_history'])]}\t" f"{child_dict['delay_dur']}\t" f"{child_dict['delay_dur_unit']}\n" @@ -149,7 +150,7 @@ def make_volume_block(nuclib_lines, volume): def make_input_lines(vol_lines, load_lines, mix_lines, flux_lines, all_ph_lines, all_sched_lines, - trunc_tolerance, nuclib_lines): + trunc_tolerance): """ Collect volume, loading, and mixture blocks from make_volume_block(). Assemble with data and output block-related lines that are expected to change infrequently. diff --git a/tools/test_build_inp_blocks.py b/tools/test_build_inp_blocks.py index eda2d5a..a372589 100644 --- a/tools/test_build_inp_blocks.py +++ b/tools/test_build_inp_blocks.py @@ -16,6 +16,7 @@ def normalize_lines(lines): 'pulse_length': 7.6, 'pulse_length_unit': 'm', 'flux_filepath': './ex_flux', + 'flux_norm' : 0.5, 'pulse_history': [(3, 7.9, 'm'), (2, 5.5, 's'), (9, 1.2, 'c')], 'delay_dur': 5.1, 'delay_dur_unit': 's' @@ -24,6 +25,7 @@ def normalize_lines(lines): 'pulse_length': 7.6, 'pulse_length_unit': 's', 'flux_filepath': '../flux_file', + 'flux_norm' : 0.9, 'pulse_history': [(1, 8.0, 'm'), (2, 3, 's'), (9, 1.1, 'c')], 'delay_dur': 5.8, 'delay_dur_unit': 'm' @@ -37,6 +39,7 @@ def normalize_lines(lines): 'pulse_length': 7.4, 'pulse_length_unit': 'd', 'flux_filepath': './iter_flux', + 'flux_norm' : 1, 'pulse_history': [(3, 7.9, 'm'), (2, 5.5, 's'), (9, 1.2, 'c')], 'delay_dur': 5.33, 'delay_dur_unit': 'c' @@ -62,6 +65,7 @@ def test_make_ph_dict(child_dicts, ph_counter, exp_ph_dict): 'pulse_length': 7.6, 'pulse_length_unit': 'm', 'flux_filepath': './ex_flux', + 'flux_norm' : 0.7, 'pulse_history': [(3, 7.9, 'm'), (2, 5.5, 's'), (9, 1.2, 'c')], 'delay_dur': 5.1, 'delay_dur_unit': 's' @@ -70,6 +74,7 @@ def test_make_ph_dict(child_dicts, ph_counter, exp_ph_dict): 'pulse_length': 7.6, 'pulse_length_unit': 's', 'flux_filepath': '../flux_file', + 'flux_norm' : 1, 'pulse_history': [(1, 8.0, 'm'), (2, 3, 's'), (9, 1.1, 'c')], 'delay_dur': 5.8, 'delay_dur_unit': 'm' @@ -83,14 +88,16 @@ def test_make_ph_dict(child_dicts, ph_counter, exp_ph_dict): 'pulse_length': 7.4, 'pulse_length_unit': 'd', 'flux_filepath': '../flux_file', + 'flux_norm' : 0.6, 'pulse_history': [(3, 7.9, 'm'), (2, 5.5, 's'), (9, 1.2, 'c')], 'delay_dur': 5.33, 'delay_dur_unit': 'c' }], None, { - './ex_flux' : 'flux_1', - '../flux_file' : 'flux_3' + ('./ex_flux', 0.7) : 'flux_1', + ('../flux_file', 1) : 'flux_2', + ('../flux_file', 0.6) : 'flux_3' }) ]) @@ -100,12 +107,12 @@ def test_make_flux_dict(child_dicts, flux_counter, exp_flux_dict): @pytest.mark.parametrize("flux_dict, exp_flux_block", [ ({ - './ex_flux' : 'flux_1', - '../flux_file' : 'flux_3' + ('./ex_flux', 1) : 'flux_1', + ('../flux_file', 2) : 'flux_3' }, """ - flux flux_1 ./ex_flux 0 default - flux flux_3 ../flux_file 0 default + flux flux_1 ./ex_flux 1 0 default + flux flux_3 ../flux_file 2 0 default """ ) ]) @@ -149,6 +156,7 @@ def test_make_pulse_history_block(ph_dict, exp_ph_block): 'pulse_length': 7.6, 'pulse_length_unit': 'm', 'flux_filepath': './iter_flux_2', + 'flux_norm' : 0.2, 'pulse_history': [(3, 7.9, 'm'), (2, 5.5, 's'), (9, 1.2, 'c')], 'delay_dur': 5.1, 'delay_dur_unit': 's' @@ -157,6 +165,7 @@ def test_make_pulse_history_block(ph_dict, exp_ph_block): 'pulse_length': 7.6, 'pulse_length_unit': 's', 'flux_filepath': '../frascati_flux_1', + 'flux_norm' : 5, 'pulse_history': [(1, 8.0, 'm'), (2, 3, 's'), (9, 1.1, 'c')], 'delay_dur': 5.8, 'delay_dur_unit': 'm' @@ -170,6 +179,7 @@ def test_make_pulse_history_block(ph_dict, exp_ph_block): 'pulse_length': 7.4, 'pulse_length_unit': 'd', 'flux_filepath': '../frascati_flux_1', + 'flux_norm' : 5, 'pulse_history': [(3, 7.9, 'm'), (2, 5.5, 's'), (9, 1.2, 'c')], 'delay_dur': 5.33, 'delay_dur_unit': 'c' @@ -180,8 +190,8 @@ def test_make_pulse_history_block(ph_dict, exp_ph_block): ((1, 8.0, 'm'), (2, 3, 's'), (9, 1.1, 'c')): 'pulse_history_3' }, { - './iter_flux_2' : 'flux_1', - '../frascati_flux_1' : 'flux_3' + ('./iter_flux_2', 0.2) : 'flux_1', + ('../frascati_flux_1', 5) : 'flux_3' }, None, "top", @@ -204,8 +214,8 @@ def test_make_schedule_block(child_dicts, ph_dict, flux_dict, sched_counter, @pytest.mark.parametrize("flux_lines, all_ph_lines, all_sched_lines, trunc_tolerance, nuclib_lines, exp_assembled_lines", [ (""" - flux flux_1 ./ex_flux 0 default - flux flux_3 ../flux_file 0 default + flux flux_1 ./ex_flux 3 0 default + flux flux_3 ../flux_file 0.3 0 default """, """pulsehistory pulse_history_1 7 9.5 d @@ -265,8 +275,8 @@ def test_make_schedule_block(child_dicts, ph_dict, flux_dict, sched_counter, specific_activity number_density end - flux flux_1 ./ex_flux 0 default - flux flux_3 ../flux_file 0 default + flux flux_1 ./ex_flux 3 0 default + flux flux_3 ../flux_file 0.3 0 default schedule top sched_1 pulse_history_1 6.3 m 7.4 d flux_3 pulse_history_2 5.33 c @@ -299,7 +309,6 @@ def test_make_input_lines(flux_lines, all_ph_lines, all_sched_lines, trunc_tolerance, nuclib_lines, exp_assembled_lines): vol_lines, load_lines, mix_lines = build_inp_blocks.make_volume_block(nuclib_lines, volume=1) obs_assembled_lines = build_inp_blocks.make_input_lines( - vol_lines, load_lines, mix_lines, flux_lines, all_ph_lines, all_sched_lines, trunc_tolerance, - nuclib_lines) + vol_lines, load_lines, mix_lines, flux_lines, all_ph_lines, all_sched_lines, trunc_tolerance) assert normalize_lines(obs_assembled_lines) == normalize_lines( exp_assembled_lines) diff --git a/tools/test_training_inp_params_to_dict.py b/tools/test_training_inp_params_to_dict.py new file mode 100644 index 0000000..774df04 --- /dev/null +++ b/tools/test_training_inp_params_to_dict.py @@ -0,0 +1,100 @@ +import pytest +import training_inp_params_to_dict +import numpy as np + +@pytest.mark.parametrize("on_times, flux_norm_factors, flux_files, time_unit, exp_training_child_dicts", [ + (np.array([1, 40]), + np.array([1, 0.3]), + np.array(['../iter_flux', '../frascati_flux']), + 'y', + np.array([ + [ + [ + {'type': 'pulse_entry', + 'pulse_length' : 1, + 'pulse_length_unit': 'y', + 'flux_filepath' : '../iter_flux', + 'flux_norm' : 1, + 'pulse_history': [1, 0, 's'], + 'delay_dur' : 0.0, + 'delay_dur_unit' : 's'}, + + {'type': 'pulse_entry', + 'pulse_length' : 1, + 'pulse_length_unit': 'y', + 'flux_filepath' : '../frascati_flux', + 'flux_norm' : 1, + 'pulse_history': [1, 0, 's'], + 'delay_dur' : 0.0, + 'delay_dur_unit' : 's'} + ], + + [ + {'type': 'pulse_entry', + 'pulse_length' : 1, + 'pulse_length_unit': 'y', + 'flux_filepath' : '../iter_flux', + 'flux_norm' : 0.3, + 'pulse_history': [1, 0, 's'], + 'delay_dur' : 0.0, + 'delay_dur_unit' : 's'}, + + {'type': 'pulse_entry', + 'pulse_length' : 1, + 'pulse_length_unit': 'y', + 'flux_filepath' : '../frascati_flux', + 'flux_norm' : 0.3, + 'pulse_history': [1, 0, 's'], + 'delay_dur' : 0.0, + 'delay_dur_unit' : 's'} + ] + ], + + [ + [ + {'type': 'pulse_entry', + 'pulse_length' : 40, + 'pulse_length_unit': 'y', + 'flux_filepath' : '../iter_flux', + 'flux_norm' : 1, + 'pulse_history': [1, 0, 's'], + 'delay_dur' : 0.0, + 'delay_dur_unit' : 's'}, + + {'type': 'pulse_entry', + 'pulse_length' : 40, + 'pulse_length_unit': 'y', + 'flux_filepath' : '../frascati_flux', + 'flux_norm' : 1, + 'pulse_history': [1, 0, 's'], + 'delay_dur' : 0.0, + 'delay_dur_unit' : 's'} + ], + + [ + {'type': 'pulse_entry', + 'pulse_length' : 40, + 'pulse_length_unit': 'y', + 'flux_filepath' : '../iter_flux', + 'flux_norm' : 0.3, + 'pulse_history': [1, 0, 's'], + 'delay_dur' : 0.0, + 'delay_dur_unit' : 's'}, + + {'type': 'pulse_entry', + 'pulse_length' : 40, + 'pulse_length_unit': 'y', + 'flux_filepath' : '../frascati_flux', + 'flux_norm' : 0.3, + 'pulse_history': [1, 0, 's'], + 'delay_dur' : 0.0, + 'delay_dur_unit' : 's'} + ] + ] + ]) + ) + ]) + +def test_write_training_params_dict(on_times, flux_norm_factors, flux_files, time_unit, exp_training_child_dicts): + obs_training_child_dicts = training_inp_params_to_dict.write_training_params_dict(on_times, flux_norm_factors, flux_files, time_unit) + assert np.array_equal(obs_training_child_dicts, exp_training_child_dicts) \ No newline at end of file diff --git a/tools/training_inp_params_to_dict.py b/tools/training_inp_params_to_dict.py new file mode 100644 index 0000000..a725c42 --- /dev/null +++ b/tools/training_inp_params_to_dict.py @@ -0,0 +1,38 @@ +import numpy as np +from itertools import product + +def write_training_params_dict(on_times, flux_norm_factors, flux_files, time_unit): + """ + This function takes a series of input parameters and converts them into a dictionary of the form below. + This dictionary can be used to build a single-line schedule with a single-line pulse history. + [ + {'type': 'pulse_entry', + 'pulse_length': (float), + 'pulse_length_unit': (str), + 'flux_filepath' : (str), + 'flux_norm' : (float), + 'pulse_history': (iterable of (int, float, str)), + 'delay_dur' : (float), + 'delay_dur_unit': (str) + } + ] + :param: on_times (iterable of times (float) during which the flux is nonzero) + :param: flux_norm_factors (iterable of factors (float) that scale the maximum flux magnitude) + :param: flux_files (iterable of paths (str) to flux files) + :param: time_unit (unit (str) of pulse length) + """ + training_child_dicts = np.ndarray((len(on_times), len(flux_norm_factors), len(flux_files)), dtype=object) + for (on_time_idx, on_time), (flux_norm_factor_idx, flux_norm_factor), (flux_file_idx, flux_file) in product( + enumerate(on_times), + enumerate(flux_norm_factors), + enumerate(flux_files) + ): + training_child_dicts[on_time_idx, flux_norm_factor_idx, flux_file_idx] = {'type': 'pulse_entry', + 'pulse_length' : on_time, + 'pulse_length_unit': time_unit, + 'flux_filepath' : flux_file, + 'flux_norm' : flux_norm_factor, + 'pulse_history': [1, 0, 's'], + 'delay_dur' : 0.0, + 'delay_dur_unit' : 's'} + return training_child_dicts \ No newline at end of file