From 42b4464256ae46a6a4860c1675443edbe541ca93 Mon Sep 17 00:00:00 2001 From: DAVIDE LAGHI <davide.laghi01@gmail.com> Date: Mon, 13 May 2024 14:46:46 +0200 Subject: [PATCH 1/4] fixed issue #287 --- jade/output.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/jade/output.py b/jade/output.py index 86a3fd7e..c9894406 100644 --- a/jade/output.py +++ b/jade/output.py @@ -329,8 +329,14 @@ def single_postprocess(self): except KeyError: # this means that the column is only one and we have # two distinct DFs for values and errors + # depending on pandas version, these may be series or + # directly arrays values = vals_df["Value"] error = err_df["Error"] + if isinstance(values, pd.Series) or isinstance(values, pd.DataFrame): + values = values.values + if isinstance(error, pd.Series) or isinstance(error, pd.DataFrame): + error = error.values lib_name = self.session.conf.get_lib_name(self.lib) lib = {"x": x, "y": values, "err": error, "ylabel": lib_name} From 28787ba61e838e6deca7de8e54c5eb295d77fba1 Mon Sep 17 00:00:00 2001 From: DAVIDE LAGHI <davide.laghi01@gmail.com> Date: Wed, 22 May 2024 19:02:14 +0200 Subject: [PATCH 2/4] fixes issue #289 --- jade/expoutput.py | 181 ++++++++++++++++++++++------------------------ 1 file changed, 85 insertions(+), 96 deletions(-) diff --git a/jade/expoutput.py b/jade/expoutput.py index 653e5f59..072f1c10 100644 --- a/jade/expoutput.py +++ b/jade/expoutput.py @@ -168,16 +168,61 @@ def build_atlas(self): # Remove tmp images shutil.rmtree(tmp_path) - def _extract_outputs(self): + def _extract_single_output( + self, results_path: os.PathLike, folder: str, lib: str + ) -> tuple[pd.DataFrame, str]: + mfile, ofile = self._get_output_files(results_path) + # Parse output + output = MCNPoutput(mfile, ofile) + + # need to extract the input in case of multi + if self.multiplerun: + pieces = folder.split("_") + input = pieces[-1] + if input not in self.inputs: + self.inputs.append(input) + self.outputs[input, lib] = output + # Get the meaningful results + self.results[input, lib] = self._processMCNPdata(output) + else: + # just treat it as a special case of multiple run + self.outputs[self.testname, lib] = output + # Get the meaningful results + self.results[self.testname, lib] = self._processMCNPdata(output) + input = self.testname + + return output.tallydata, input + + def _extract_outputs(self) -> None: """ - Extract, organize and store the results coming from the MCNP runs + Extract, organize and store the results coming from the different codes + runs + Returns ------- None. """ - outputs = {} - results = {} - inputs = [] + self.outputs = {} + self.results = {} + + # Each output object is processing only one code at the time at the moment + if self.mcnp: + code_tag = "mcnp" + if self.openmc: + print("Experimental comparison not implemented for OpenMC") + return + if self.serpent: + print("Experimental comparison not implemented for Serpent") + return + if self.d1s: + code_tag = "d1s" + + # only multiple runs have multiple inputs + if self.multiplerun: + self.inputs = [self.testname] + else: + self.inputs = [] + # Iterate on the different libraries results except 'Exp' for lib, test_path in self.test_path.items(): if lib != EXP_TAG: @@ -185,72 +230,22 @@ def _extract_outputs(self): # Results are organized by folder and lib code_raw_data = {} for folder in os.listdir(test_path): - # FIX MCNP HARD CODED PATH HERE - if self.mcnp: - results_path = os.path.join(test_path, folder, "mcnp") - pieces = folder.split("_") - # Get zaid - input = pieces[-1] - mfile, ofile = self._get_output_files(results_path) - # Parse output - output = MCNPoutput(mfile, ofile) - outputs[input, lib] = output - code_raw_data[input, lib] = output.tallydata - # self.raw_data[input, lib] = output.tallydata - - # Get the meaningful results - results[input, lib] = self._processMCNPdata(output) - if input not in inputs: - inputs.append(input) - if self.openmc: - print( - "Experimental comparison not implemented \ - for OpenMC" - ) - break - if self.serpent: - print( - "Experimental comparison not implemented \ - for Serpent" - ) - break - if self.d1s: - results_path = os.path.join(test_path, folder, "d1s") - pieces = folder.split("_") - # Get zaid - input = pieces[-1] - mfile, ofile = self._get_output_files(results_path) - # Parse output - output = MCNPoutput(mfile, ofile) - outputs[input, lib] = output - code_raw_data[input, lib] = output.tallydata - # self.raw_data[input, lib] = output.tallydata - - # Get the meaningful results - results[input, lib] = self._processMCNPdata(output) - if input not in inputs: - inputs.append(input) - if self.mcnp: - self.raw_data["mcnp"].update(code_raw_data) - if self.d1s: - self.raw_data["d1s"].update(code_raw_data) + results_path = os.path.join(test_path, folder, code_tag) + tallydata, input = self._extract_single_output( + results_path, folder, lib + ) + code_raw_data[input, lib] = tallydata + # Results are organized just by lib else: - mfile, ofile = self._get_output_files(test_path) - # Parse output - output = MCNPoutput(mfile, ofile) - outputs[self.testname, lib] = output - # Adjourn raw Data - self.raw_data[self.testname, lib] = output.tallydata - # Get the meaningful results - results[self.testname, lib] = self._processMCNPdata(output) - - self.outputs = outputs - self.results = results - if inputs: - self.inputs = inputs - else: - self.inputs = [self.testname] + results_path = os.path.join(test_path, code_tag) + tallydata, input = self._extract_single_output( + results_path, None, lib + ) + code_raw_data = {(self.testname, lib): tallydata} + + # Adjourn raw Data + self.raw_data[code_tag].update(code_raw_data) def _read_exp_results(self): """ @@ -483,9 +478,7 @@ def _pp_excel_comparison(self): Responsible for producing excel outputs """ # Dump the global C/E table - ex_outpath = os.path.join( - self.excel_path, self.testname + "_CE_tables.xlsx" - ) + ex_outpath = os.path.join(self.excel_path, self.testname + "_CE_tables.xlsx") # Create a Pandas Excel writer using XlsxWriter as the engine. with pd.ExcelWriter(ex_outpath, engine="xlsxwriter") as writer: # --- build and dump the C/E table --- @@ -673,7 +666,7 @@ def _read_exp_file(self, filepath): filepath : str string containing the path to the experimental file to be read for comparison - + """ return pd.read_csv(filepath, sep=";") @@ -684,7 +677,7 @@ def _build_atlas(self, tmp_path, atlas): """ Fill the atlas with the customized plots. Creation and saving of the atlas are handled elsewhere. - + Parameters ---------- tmp_path : str @@ -753,7 +746,7 @@ def _get_tally_info(self, tally): tallynum (int): Tally number of the tally being plotted particle (str): Type of quantity being plotted on the X axis quant + unit (str): Unit of quantity being plotted on the X axis - + """ tallynum = tally.tallyNumber particle = tally.particleList[np.where(tally.tallyParticles == 1)[0][0]] @@ -786,7 +779,7 @@ def _define_title(self, input, quantity_CE): def _dump_ce_table(self): """ - Generates the C/E table and dumps them as an .xlsx file + Generates the C/E table and dumps them as an .xlsx file """ final_table = pd.concat(self.tables) skipcol_global = 0 @@ -998,7 +991,7 @@ def _parse_data_df(self, data, output, x_axis, tallynum): x_axis : str X axis title tallynum : int - Tally number, used to determine behaviour for protons and + Tally number, used to determine behaviour for protons and neutrons Returns @@ -1172,7 +1165,7 @@ def _exp_comp_case_check(self, indexes): def _get_conv_df(self, df): """ - Adds extra columns to the dataframe containing the maximum and + Adds extra columns to the dataframe containing the maximum and average errors of the tallies Parameters @@ -1184,9 +1177,9 @@ def _get_conv_df(self, df): Returns ------- conv_df: Dataframe - Same as previous dataframe, but with two extra columns containing + Same as previous dataframe, but with two extra columns containing maximum and average errors - + """ conv_df = pd.DataFrame() for library in df.index.unique(level="Library").tolist(): @@ -1203,7 +1196,7 @@ class TiaraFCOutput(TiaraOutput): def _pp_excel_comparison(self): """ - Builds dataframe from computational output comparable to experimental + Builds dataframe from computational output comparable to experimental data and generates the excel comparison """ @@ -1247,9 +1240,7 @@ def _pp_excel_comparison(self): self._exp_comp_case_check(indexes=indexes) self.case_tree_df.sort_values(indexes, axis=0, inplace=True) # Build ExcelWriter object - filepath = os.path.join( - self.excel_path, "Tiara_Fission_Cells_CE_tables.xlsx" - ) + filepath = os.path.join(self.excel_path, "Tiara_Fission_Cells_CE_tables.xlsx") with pd.ExcelWriter(filepath, engine="xlsxwriter") as writer: # Create 1 worksheet for each energy/material combination @@ -1391,7 +1382,7 @@ def _build_atlas(self, tmp_path, atlas): """ Fill the atlas with the customized plots. Creation and saving of the atlas are handled elsewhere. - + Parameters ---------- tmp_path : str @@ -1549,9 +1540,7 @@ def _pp_excel_comparison(self): indexes = ["Library", "Shield Material", "Energy", "Shield Thickness"] self._exp_comp_case_check(indexes=indexes) # Create ExcelWriter object - filepath = os.path.join( - self.excel_path, "Tiara_Bonner_Spheres_CE_tables.xlsx" - ) + filepath = os.path.join(self.excel_path, "Tiara_Bonner_Spheres_CE_tables.xlsx") with pd.ExcelWriter(filepath, engine="xlsxwriter") as writer: # Loop over shield material/energy combinations mat_list = self.case_tree_df.index.unique(level="Shield Material").tolist() @@ -1662,7 +1651,7 @@ def _build_atlas(self, tmp_path, atlas): """ Fill the atlas with the customized plots. Creation and saving of the atlas are handled elsewhere. - + Parameters ---------- tmp_path : str @@ -1822,7 +1811,7 @@ def _build_atlas(self, tmp_path, atlas): """ Fill the atlas with the customized plots. Creation and saving of the atlas are handled elsewhere. - + Parameters ---------- tmp_path : str @@ -1922,7 +1911,7 @@ def _build_atlas(self, tmp_path, atlas): """ Fill the atlas with the customized plots. Creation and saving of the atlas are handled elsewhere. - + Parameters ---------- tmp_path : str @@ -1944,14 +1933,14 @@ def _build_atlas(self, tmp_path, atlas): return atlas def _plot_tally_group(self, group, tmp_path, atlas): - """ - Plots tallies for a given group of outputs and add to Atlas object + """ + Plots tallies for a given group of outputs and add to Atlas object Parameters ---------- group : list - list of groups in the experimental benchmark object, outputs are - grouped by material, several tallies for each material/group + list of groups in the experimental benchmark object, outputs are + grouped by material, several tallies for each material/group tmp_path : str path to temporary atlas plot folder atlas : JADE Atlas @@ -1960,7 +1949,7 @@ def _plot_tally_group(self, group, tmp_path, atlas): Returns ------- atlas : JADE Atlas - adjusted Atlas object + adjusted Atlas object """ # Extract 'Tally' and 'Input' values for the current 'Group' group_data = self.groups.xs(group, level="Group", drop_level=False) From 778638b40f5fd13215510f38a378968b060be9b8 Mon Sep 17 00:00:00 2001 From: DAVIDE LAGHI <davide.laghi01@gmail.com> Date: Thu, 23 May 2024 09:03:27 +0200 Subject: [PATCH 3/4] fix multirun inputs --- jade/expoutput.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jade/expoutput.py b/jade/expoutput.py index 072f1c10..38dccfb7 100644 --- a/jade/expoutput.py +++ b/jade/expoutput.py @@ -219,9 +219,9 @@ def _extract_outputs(self) -> None: # only multiple runs have multiple inputs if self.multiplerun: - self.inputs = [self.testname] - else: self.inputs = [] + else: + self.inputs = [self.testname] # Iterate on the different libraries results except 'Exp' for lib, test_path in self.test_path.items(): From 55989e80f69f22dc5b2c4289a98dc552652f4cae Mon Sep 17 00:00:00 2001 From: DAVIDE LAGHI <davide.laghi01@gmail.com> Date: Thu, 23 May 2024 09:12:32 +0200 Subject: [PATCH 4/4] solve typing error --- jade/expoutput.py | 1 + 1 file changed, 1 insertion(+) diff --git a/jade/expoutput.py b/jade/expoutput.py index 38dccfb7..59f69d4e 100644 --- a/jade/expoutput.py +++ b/jade/expoutput.py @@ -20,6 +20,7 @@ # You should have received a copy of the GNU General Public License # along with JADE. If not, see <http://www.gnu.org/licenses/>. +from __future__ import annotations import math import os import re