diff --git a/tools/README.md b/tools/README.md index 2b096387..5bc99d1a 100644 --- a/tools/README.md +++ b/tools/README.md @@ -6,6 +6,7 @@ Contained within `ALARA/tools` is the Python package, `alara_output_processing`, - Standard Python libraries * [ArgParse](https://docs.python.org/3/library/argparse.html) * [CSV](https://docs.python.org/3/library/csv.html) + * [Numbers](https://docs.python.org/3/library/numbers.html) * [Operator](https://docs.python.org/3/library/operator.html) * [Warnings](https://docs.python.org/3/library/warnings.html) - Generic Python packages @@ -119,6 +120,8 @@ The parameter `filter_dict` allows filtering over any number of columns and any To filter pre-irradiation values, which are identified by `adf["time"] == -1` (see above), write `filter_dict["time"] = -1`. Otherwise, to filter post-irradiation cooling times, any other value for `filter_dict["time"]` will be accepted and will remove the pre-irradiation rows. For clarity, `filter_dict["time"] = "post_irradiation"` is recommended. +To filter values above or below a certain threshold for a given response variable, both the variable and the value inequality expression must be included by having a `filter_dict` like such: `filter_dict = {'variable' : ALARADFRAME.VARIABLE_ENUM[{variable}], 'value' : [{operator}, {threshold}]}`. + When filtering the `nuclide` column, `ALARADFrame.filter_rows()` has functionality to select all nuclides of a particular element, as well as selecting individual nuclides. To do so, instead of `filter_dict["nuclide"] = "fe-55"`, write `filter_dict["nuclide"] = "fe"` to filter all iron isotopes, instead of just 55Fe, for example. Similarly, multiple whole elements can be selected by inputting them as a list for `filter_dict["nuclide"]`. It is also possible to filter by a combination of whole elements and individual nuclides. Additional nuclide filtering can be done on the stability of nuclides. To filter all stable nuclides, write `filter_dict["half_life"] = "stable"` or `filter_dict["half_life"] = -1`. To filter all unstable nuclides, write `filter_dict["half_lives] = "unstable"` or `filter_dict["half_life"] = "radioactive". ` Half-life filtering can also be done relative to certain time thresholds, such as filtering all nuclides with half-lives greater than 1e6 seconds. To do so write `filter_dict["half_life"] = [">", 1e6]`. Generally, the format for this time-operator filtering is `filter_dict["half_life"] = [{operator}, {threshold}]`. diff --git a/tools/alara_output_processing/alara_output_processing.py b/tools/alara_output_processing/alara_output_processing.py index 5b7eed17..dc70b750 100644 --- a/tools/alara_output_processing/alara_output_processing.py +++ b/tools/alara_output_processing/alara_output_processing.py @@ -6,6 +6,7 @@ from numpy import array from pathlib import Path from collections import defaultdict +from numbers import Number # ---------- General Utility Methods ---------- @@ -273,7 +274,8 @@ def _parse_table_data( 'variable' : ALARADFrame.VARIABLE_ENUM[variable], 'var_unit' : unit.split(']')[0], 'value' : float(row[str(time)]) - } for row in reader for time in converted_times] + } for row in reader for time in converted_times + if row[nuclide_col] != 'total'] def extract_tables(self): ''' @@ -429,7 +431,7 @@ def fispact_to_adf(run_lbl, output_path, time_unit='s'): row['value'] = value rows.append(row.copy()) - return ALARADFrame(rows).create_total_rows(), all_nucs + return ALARADFrame(rows), all_nucs class OpenMCParser: UNIT_DICT = { @@ -578,9 +580,7 @@ def openmc_to_adf(run_lbl, output_path, xs_path, chain_path, time_unit): 'value' : responses[t][mat.id][var].get(n,0) }) - return ALARADFrame(rows).create_total_rows()[ - ALARADFrame.CANONICAL_COLUMN_ORDER - ] + return ALARADFrame(rows)[ALARADFrame.CANONICAL_COLUMN_ORDER] class ALARADFrame(pd.DataFrame): @@ -745,10 +745,14 @@ def filter_rows(self, filter_dict): if not isinstance(filters, list): filters = [filters] - if col_name == 'time' and filters[0] in OPS: - filters = filtered_adf._filter_numerically( - filters, set(filtered_adf['time']) - ) + if ( + col_name in ['time', 'value'] + and filters[0] in OPS + and isinstance(filters[1], Number) + ): + filters = filtered_adf._filter_numerically( + filters, set(filtered_adf[col_name]) + ) if col_name == 'nuclide': nuclides = set() @@ -980,7 +984,8 @@ def __init__(self): self.adf = None def make_entries( - self, runs_dict, time_unit='s', xs_path=Path(), chain_path=Path() + self, runs_dict, time_unit='s', xs_path=Path(), chain_path=Path(), + half_lives=None ): ''' Flexibly create a dictionary of subdictionaries containing @@ -1017,7 +1022,11 @@ def make_entries( simulation. Only required if any of the runs in runs_dict is an OpenMC depletion simulation HDF5 results file. If included, must have the file suffix ".xml". - + half_lives (int or None, optional): Option to set a cutoff number + of half-lives for each radionuclide after which point to force + decay responses to 0. + (Defaults to None) + Returns: self.adf (alara_output_processing.ALARADFrame): Specialized ALARA output DataFrame containing combined data from all tables in @@ -1052,6 +1061,10 @@ def make_entries( dfs.append(data) self.adf = ALARADFrame(pd.concat(dfs).fillna(0.0)) + if half_lives is not None: + self.adf = self.adf.zero_long_decay_responses(half_lives=half_lives) + + self.adf = self.adf.create_total_rows() return self.adf