From b31c2db7d2e9ece1a2299fe45a6f837a9e5abeab Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Wed, 18 May 2022 14:08:54 +0200 Subject: [PATCH 01/21] Custom perturbation with dataframes --- sandy/core/xs.py | 329 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 323 insertions(+), 6 deletions(-) diff --git a/sandy/core/xs.py b/sandy/core/xs.py index 0373268a..910964a4 100644 --- a/sandy/core/xs.py +++ b/sandy/core/xs.py @@ -156,10 +156,225 @@ def reshape(self, eg): df = pd.DataFrame(xsnew, index=enew, columns=df.columns) return self.__class__(df) - def custom_perturbation(self, mat, mt, pert): + def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): """ - Apply a custom perturbation to a given cross section identified by - a MAT and MT number. + Function to apply perturbations to individual XS or a group of XS. + + Parameters + ---------- + pert : `pd.Series` or `sandy.Pert` or `pd.Dataframe` + tabulated perturbations with the index representing the energy grid + and the columns representing mt. If a `pd.Series` or `sandy.Pert` + is introduced, the optional argument mt must be filled in. + mat : `int`, optional + MAT number. The default is None. + mt : `int`, optional + MT number. The default is None. + **kwargs : `dict` + keyword argument to pass to `sandy.Xs._recontruct_sums`. + + Parameters for _recontruct_sums + --------------------- + drop : `bool`, optional + Keep only mts present in the original file. The default is True. + inplace : `bool`, optional + Argument to define whether the output is a new object or + overwrite the original object.. The default is False. + + Returns + ------- + `sandy.Xs` + Xs disturbed and reconstructed. + + Examples + -------- + Test single perturbation: + >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 10010) + >>> xs = sandy.Xs.from_endf6(endf6) + >>> pert = sandy.Pert([1, 1.05], index=[10, 100]) + >>> pert_xs = xs.custom_perturbation(pert, mat=125, mt=2) + >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() + array([1. , 1.05]) + + >>> (pert_xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)] / xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)]).round(2) + E + 1.00000e-05 1.00000e+00 + 1.00000e+01 1.00000e+00 + 2.00000e+01 1.05000e+00 + 1.00000e+02 1.05000e+00 + 1.00000e+04 1.00000e+00 + Name: (125, 2), dtype: float64 + + Single perturbation in a dataframe: + >>> pert = pd.DataFrame([1, 1.05], index =pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0)), columns=[2]) + >>> pert.columns.name = 'MT' + >>> pert_xs = xs.custom_perturbation(pert, mat=125) + >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() + array([1. , 1.05]) + + >>> (pert_xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)] / xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)]).round(2) + E + 1.00000e-05 1.00000e+00 + 1.00000e+01 1.00000e+00 + 2.00000e+01 1.05000e+00 + 1.00000e+02 1.05000e+00 + 1.00000e+04 1.00000e+00 + Name: (125, 2), dtype: float64 + + Multiple perturbation: + >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 260560) + >>> xs = sandy.Xs.from_endf6(endf6) + >>> col = pd.MultiIndex.from_arrays([[2631, 2631], [5, 2]], names=('MAT', 'MT')) + >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) + >>> pert_xs = xs.custom_perturbation(pert) + >>> pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] + MAT 2631 + MT 1 2 3 5 + E + 1.92000e+08 1.00042e+00 1.00000e+00 1.00121e+00 1.00000e+00 + 1.94000e+08 1.03360e+00 1.05000e+00 1.00106e+00 1.00000e+00 + 1.96000e+08 1.01702e+00 1.00000e+00 1.05085e+00 1.05000e+00 + 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 + """ + xs = self + # By default, apply the perturbation to all the mat in the object: + if mat is not None: + mat_ = [mat] if isinstance(mat, int) else mat + else: + mat_ = xs.data.columns.get_level_values('MAT').unique() + # Decide whether we are applying an initial perturbation or a multiple + # perturbation. + if isinstance(pert, pd.DataFrame): + if 'MAT' not in pert.columns.names: + pert = pd.concat([pert]*len(mat_), names=['MAT'], + keys=mat_, axis=1) + for pert_mat in mat_: + xs = xs._custom_multiple_perturbation(pert, pert_mat, **kwargs) + elif isinstance(pert, sandy.Pert) or isinstance(pert, pd.Series): + pert_ = sandy.Pert(pert) if isinstance(pert, pd.Series) else pert + for pert_mat in mat_: + xs = xs._custom_single_perturbation(pert_mat, mt, pert_, **kwargs) + return xs + + def _custom_multiple_perturbation(self, pert, mat, **kwargs): + """ + Custom a set of perturbation to the Xs object. + + Parameters + ---------- + pert : `pd.Dataframe` + Dataframe containing the perturbation coefficients. It is mandatory + that the index is the energy grid (in groups or pointwise) and that + the columns are the mt to be perturbed. + mat : `int` + MAT number. + **kwargs : `dict` + keyword argument to pass to `sandy.Xs._recontruct_sums`. + + Parameters for _recontruct_sums + --------------------- + drop : `bool`, optional + Keep only mts present in the original file. The default is True. + inplace : `bool`, optional + Argument to define whether the output is a new object or + overwrite the original object.. The default is False. + + Returns + ------- + `sandy.Xs` + Perturbed Xs. + + Examples + -------- + Test single perturbation (Non redundant): + >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 10010) + >>> xs = sandy.Xs.from_endf6(endf6) + >>> col = pd.MultiIndex.from_arrays([[125], [2]], names=('MAT', 'MT')) + >>> pert = pd.DataFrame([1, 1.05], index =pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0)), columns=col) + >>> pert_xs = xs._custom_multiple_perturbation(pert, 125) + >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() + array([1. , 1.05]) + + >>> (pert_xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)] / xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)]).round(2) + E + 1.00000e-05 1.00000e+00 + 1.00000e+01 1.00000e+00 + 2.00000e+01 1.05000e+00 + 1.00000e+02 1.05000e+00 + 1.00000e+04 1.00000e+00 + Name: (125, 2), dtype: float64 + + Test single perturbation (Redundant): + >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 260560) + >>> xs = sandy.Xs.from_endf6(endf6) + >>> col = pd.MultiIndex.from_arrays([[2631], [1]], names=('MAT', 'MT')) + >>> pert = pd.DataFrame([1, 1.05], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08]).insert(0, 0)), columns=col) + >>> pert_xs = xs._custom_multiple_perturbation(pert, 2631) + >>> (pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3)]]).round(2) + MAT 2631 + MT 1 2 3 + E + 1.92000e+08 1.00000e+00 1.00000e+00 1.00000e+00 + 1.94000e+08 1.00000e+00 1.00000e+00 1.00000e+00 + 1.96000e+08 1.03000e+00 1.05000e+00 1.00000e+00 + 1.98000e+08 1.00000e+00 1.00000e+00 1.00000e+00 + + Multiple perturbation(redundant + non redundant, mt perturb max = 3) + >>> col = pd.MultiIndex.from_arrays([[2631, 2631], [3, 2]], names=('MAT', 'MT')) + >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) + >>> pert_xs = xs._custom_multiple_perturbation(pert, 2631) + >>> pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] + MAT 2631 + MT 1 2 3 5 + E + 1.92000e+08 1.00042e+00 1.00000e+00 1.00121e+00 1.00000e+00 + 1.94000e+08 1.03360e+00 1.05000e+00 1.00106e+00 1.00000e+00 + 1.96000e+08 1.01702e+00 1.00000e+00 1.05085e+00 1.05000e+00 + 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 + + Multiple perturbation(non redundant): + >>> col = pd.MultiIndex.from_arrays([[2631, 2631], [5, 2]], names=('MAT', 'MT')) + >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) + >>> pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] + MAT 2631 + MT 1 2 3 5 + E + 1.92000e+08 1.00042e+00 1.00000e+00 1.00121e+00 1.00000e+00 + 1.94000e+08 1.03360e+00 1.05000e+00 1.00106e+00 1.00000e+00 + 1.96000e+08 1.01702e+00 1.00000e+00 1.05085e+00 1.05000e+00 + 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 + """ + # Reshape (all to the right): + if isinstance(pert.index, pd.IntervalIndex): + enew = np.union1d(self.data.index.values, pert.index.right.values) + else: + enew = np.union1d(self.data.index.values, pert.index.values) + u_xs = self.reshape(enew).data + u_pert = reshape_df(pert, enew) + # Redundant xs: + mt = u_xs.columns.get_level_values('MT') + mt_pert_o = u_pert.columns.get_level_values('MT') + parent = pd.Index(self.__class__.redundant_xs.keys()) + mask = mt_pert_o.isin(parent) + if mt_pert_o.max() == 3: + u_pert = u_pert.join(pd.concat([u_pert[(mat, 3)]]*len(mt[mt > 3]), axis=1, + keys=zip([mat]*len(mt[mt > 3]), mt[mt > 3]))) + elif len(mt_pert_o[mask]) != 0: + for mt_parent in mt_pert_o[mask].sort_values(ascending=False): + mt_pert = mt[(mt.isin(redundant_xs[mt_parent]))] + mt_pert = mt_pert[~(mt_pert.isin(mt_pert_o))] + if len(mt_pert) != 0: + u_pert = u_pert.join(pd.concat([u_pert[(mat, mt_parent)]]*len(mt_pert), axis=1, + keys=zip([mat]*len(mt_pert), mt_pert))) + # Apply pertubation: + u_xs.loc[:, u_pert.columns] = u_xs.loc[:, u_pert.columns]\ + .multiply(u_pert, axis='columns') + return self.__class__(u_xs)._reconstruct_sums(**kwargs) + + def _custom_single_perturbation(self, mat, mt, pert, **kwargs): + """ + Apply a single custom perturbation to a given cross section identified + by a MAT and MT number. Parameters ---------- @@ -171,11 +386,59 @@ def custom_perturbation(self, mat, mt, pert): applied pert : `sandy.Pert` tabulated perturbations + **kwargs : `dict` + keyword argument to pass to `sandy.Xs._recontruct_sums`. + + Parameters for _recontruct_sums + --------------------- + drop : `bool`, optional + Keep only mts present in the original file. The default is True. + inplace : `bool`, optional + Argument to define whether the output is a new object or + overwrite the original object.. The default is False. + + Notes + ----- + .. note:: If the mt is redundant, the perturbation applies to all mt + that form the redundant mt. Returns ------- - `Xs` + `sandy.Xs` cross section instance with given series MAT/MT perturbed + + Examples + -------- + Test single perturbation (non redundant): + >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 10010) + >>> xs = sandy.Xs.from_endf6(endf6) + >>> pert = sandy.Pert([1, 1.05], index=[10, 100]) + >>> pert_xs = xs._custom_single_perturbation(125, 2, pert) + >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() + array([1. , 1.05]) + + >>> (pert_xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)] / xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)]).round(2) + E + 1.00000e-05 1.00000e+00 + 1.00000e+01 1.00000e+00 + 2.00000e+01 1.05000e+00 + 1.00000e+02 1.05000e+00 + 1.00000e+04 1.00000e+00 + Name: (125, 2), dtype: float64 + + Test single perturbation (redundant): + >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 260560) + >>> xs = sandy.Xs.from_endf6(endf6) + >>> pert = sandy.Pert([1, 1.05], index=[1.94000e+08, 1.96000e+08]) + >>> pert_xs = xs._custom_single_perturbation(2631, 1, pert) + >>> (pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3)]]).round(2) + MAT 2631 + MT 1 2 3 + E + 1.92000e+08 1.00000e+00 1.00000e+00 1.00000e+00 + 1.94000e+08 1.00000e+00 1.00000e+00 1.00000e+00 + 1.96000e+08 1.03000e+00 1.05000e+00 1.00000e+00 + 1.98000e+08 1.00000e+00 1.00000e+00 1.00000e+00 """ if (mat, mt) not in self.data: msg = f"could not find MAT{mat}/MT{mt}, " +\ @@ -186,8 +449,13 @@ def custom_perturbation(self, mat, mt, pert): enew = np.union1d(self.data.index.values, pert.right.index.values) u_xs = self.reshape(enew) u_pert = pert.reshape(enew) - u_xs.data[(mat, mt)] = u_xs.data[(mat, mt)] * u_pert.right.values - return self.__class__(u_xs.data) + if mt in self.__class__.redundant_xs: + mt = self.data.columns.get_level_values("MT")\ + .intersection(redundant_xs[mt]).union([mt]) + u_xs.data.loc[:, (mat, mt)] = u_xs.data.loc[:, (mat, mt)]\ + .multiply(u_pert.right, + axis='index') + return self.__class__(u_xs.data)._reconstruct_sums(**kwargs) def filter_energies(self, energies): mask = self.data.index.isin(energies) @@ -362,6 +630,20 @@ def foo(l, r): def _reconstruct_sums(self, drop=True, inplace=False): """ Reconstruct redundant xs. + + Parameters + ---------- + drop : `bool`, optional + Keep only mts present in the original file. The default is True. + inplace : `bool`, optional + Argument to define whether the output is a new object or + overwrite the original object.. The default is False. + + Returns + ------- + `sandy.Xs` + Sandy object with the redundant xs calculated. + """ df = self.data.copy() for mat in self.data.columns.get_level_values("MAT").unique(): @@ -527,3 +809,38 @@ def eV2MeV(self): df = self.data.copy() df.index = df.index * 1e-6 return df + + +def reshape_df(df, eg): + """ + Reshape energy dependent dataframe with using "bfill" method. + + Parameters + ---------- + df : `pd.Dataframe` + Dataframe to be reshaped. + . + eg : 1D iterable + New energy grid structure. + + Returns + ------- + data : `pd.Dataframe` + Reshaped dataframe. + + """ + index = pd.Index(eg) + if isinstance(index, pd.IntervalIndex): + index = index.right + if isinstance(df.index, pd.IntervalIndex): + df.index = df.index.right + enew = df.index.union(index).unique().astype(float).values + name = df.index.name + data = df.apply(lambda x: sandy.shared.reshape_bfill( + x.index.values, + x.values, + enew, + left_values=1, + right_values=1, + )).set_index(enew).rename_axis(name) + return data From 810c081074afeb257c33900a63c5e736499159a3 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Thu, 19 May 2022 10:56:28 +0200 Subject: [PATCH 02/21] Requested changes --- sandy/core/xs.py | 162 +++++++++++------------------------------ sandy/pert.py | 182 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 205 insertions(+), 139 deletions(-) diff --git a/sandy/core/xs.py b/sandy/core/xs.py index 910964a4..fff72d96 100644 --- a/sandy/core/xs.py +++ b/sandy/core/xs.py @@ -156,16 +156,15 @@ def reshape(self, eg): df = pd.DataFrame(xsnew, index=enew, columns=df.columns) return self.__class__(df) - def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): + def custom_perturbation(self, pert, mat=None, **kwargs): """ Function to apply perturbations to individual XS or a group of XS. Parameters ---------- - pert : `pd.Series` or `sandy.Pert` or `pd.Dataframe` + pert : `sandy.Pert` or `pd.Dataframe` tabulated perturbations with the index representing the energy grid - and the columns representing mt. If a `pd.Series` or `sandy.Pert` - is introduced, the optional argument mt must be filled in. + and the columns representing MT. mat : `int`, optional MAT number. The default is None. mt : `int`, optional @@ -192,7 +191,7 @@ def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 10010) >>> xs = sandy.Xs.from_endf6(endf6) >>> pert = sandy.Pert([1, 1.05], index=[10, 100]) - >>> pert_xs = xs.custom_perturbation(pert, mat=125, mt=2) + >>> pert_xs = xs.custom_perturbation(pert, mat=125) >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() array([1. , 1.05]) @@ -231,7 +230,7 @@ def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): MAT 2631 MT 1 2 3 5 E - 1.92000e+08 1.00042e+00 1.00000e+00 1.00121e+00 1.00000e+00 + 1.92000e+08 1.03353e+00 1.05000e+00 1.00121e+00 1.00000e+00 1.94000e+08 1.03360e+00 1.05000e+00 1.00106e+00 1.00000e+00 1.96000e+08 1.01702e+00 1.00000e+00 1.05085e+00 1.05000e+00 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 @@ -242,30 +241,28 @@ def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): mat_ = [mat] if isinstance(mat, int) else mat else: mat_ = xs.data.columns.get_level_values('MAT').unique() - # Decide whether we are applying an initial perturbation or a multiple - # perturbation. - if isinstance(pert, pd.DataFrame): - if 'MAT' not in pert.columns.names: - pert = pd.concat([pert]*len(mat_), names=['MAT'], - keys=mat_, axis=1) - for pert_mat in mat_: - xs = xs._custom_multiple_perturbation(pert, pert_mat, **kwargs) - elif isinstance(pert, sandy.Pert) or isinstance(pert, pd.Series): - pert_ = sandy.Pert(pert) if isinstance(pert, pd.Series) else pert + # Create perturbation object: + pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert + # Perturbation data for all the mat numbers: + if isinstance(pert_.data, pd.DataFrame): + if 'MAT' not in pert_.data.columns.names: + pert_ = pd.concat([pert_.data]*len(mat_), names=['MAT'], + keys=mat_, axis=1) + pert_ = sandy.Pert(pert_) for pert_mat in mat_: - xs = xs._custom_single_perturbation(pert_mat, mt, pert_, **kwargs) + xs = xs._custom_perturbation(pert_, pert_mat, **kwargs) + else: + xs = xs._custom_perturbation(pert_, mat_, **kwargs) return xs - def _custom_multiple_perturbation(self, pert, mat, **kwargs): + def _custom_perturbation(self, pert, mat, **kwargs): """ Custom a set of perturbation to the Xs object. Parameters ---------- - pert : `pd.Dataframe` - Dataframe containing the perturbation coefficients. It is mandatory - that the index is the energy grid (in groups or pointwise) and that - the columns are the mt to be perturbed. + pert : `sandy.Pert` + tabulated perturbations mat : `int` MAT number. **kwargs : `dict` @@ -291,7 +288,7 @@ def _custom_multiple_perturbation(self, pert, mat, **kwargs): >>> xs = sandy.Xs.from_endf6(endf6) >>> col = pd.MultiIndex.from_arrays([[125], [2]], names=('MAT', 'MT')) >>> pert = pd.DataFrame([1, 1.05], index =pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0)), columns=col) - >>> pert_xs = xs._custom_multiple_perturbation(pert, 125) + >>> pert_xs = xs._custom_perturbation(sandy.Pert(pert), 125) >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() array([1. , 1.05]) @@ -309,7 +306,7 @@ def _custom_multiple_perturbation(self, pert, mat, **kwargs): >>> xs = sandy.Xs.from_endf6(endf6) >>> col = pd.MultiIndex.from_arrays([[2631], [1]], names=('MAT', 'MT')) >>> pert = pd.DataFrame([1, 1.05], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08]).insert(0, 0)), columns=col) - >>> pert_xs = xs._custom_multiple_perturbation(pert, 2631) + >>> pert_xs = xs._custom_perturbation(sandy.Pert(pert), 2631) >>> (pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3)]]).round(2) MAT 2631 MT 1 2 3 @@ -322,12 +319,12 @@ def _custom_multiple_perturbation(self, pert, mat, **kwargs): Multiple perturbation(redundant + non redundant, mt perturb max = 3) >>> col = pd.MultiIndex.from_arrays([[2631, 2631], [3, 2]], names=('MAT', 'MT')) >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) - >>> pert_xs = xs._custom_multiple_perturbation(pert, 2631) + >>> pert_xs = xs._custom_perturbation(sandy.Pert(pert), 2631) >>> pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] MAT 2631 MT 1 2 3 5 E - 1.92000e+08 1.00042e+00 1.00000e+00 1.00121e+00 1.00000e+00 + 1.92000e+08 1.03353e+00 1.05000e+00 1.00121e+00 1.00000e+00 1.94000e+08 1.03360e+00 1.05000e+00 1.00106e+00 1.00000e+00 1.96000e+08 1.01702e+00 1.00000e+00 1.05085e+00 1.05000e+00 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 @@ -335,22 +332,35 @@ def _custom_multiple_perturbation(self, pert, mat, **kwargs): Multiple perturbation(non redundant): >>> col = pd.MultiIndex.from_arrays([[2631, 2631], [5, 2]], names=('MAT', 'MT')) >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) + >>> pert_xs = xs._custom_perturbation(sandy.Pert(pert), 2631) >>> pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] MAT 2631 MT 1 2 3 5 E - 1.92000e+08 1.00042e+00 1.00000e+00 1.00121e+00 1.00000e+00 + 1.92000e+08 1.03353e+00 1.05000e+00 1.00121e+00 1.00000e+00 1.94000e+08 1.03360e+00 1.05000e+00 1.00106e+00 1.00000e+00 1.96000e+08 1.01702e+00 1.00000e+00 1.05085e+00 1.05000e+00 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 + + Pert a series without mt and mat information: + >>> pert = pd.Series([1, 1.05], index=pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.98000e+08]).insert(0, 0))) + >>> pert_xs = xs._custom_perturbation(sandy.Pert(pert), 2631) + >>> pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] + MAT 2631 + MT 1 2 3 5 + E + 1.92000e+08 1.00042e+00 1.00000e+00 1.00121e+00 1.00000e+00 + 1.94000e+08 1.00040e+00 1.00000e+00 1.00106e+00 1.00000e+00 + 1.96000e+08 1.05032e+00 1.05000e+00 1.05085e+00 1.05000e+00 + 1.98000e+08 1.05016e+00 1.05000e+00 1.05047e+00 1.05000e+00 """ # Reshape (all to the right): - if isinstance(pert.index, pd.IntervalIndex): - enew = np.union1d(self.data.index.values, pert.index.right.values) - else: - enew = np.union1d(self.data.index.values, pert.index.values) + enew = np.union1d(self.data.index.values, pert.right.index.values) u_xs = self.reshape(enew).data - u_pert = reshape_df(pert, enew) + u_pert = pert.reshape(enew).right + if isinstance(u_pert, pd.Series): + u_xs = u_xs.multiply(u_pert, axis='index') + return self.__class__(u_xs)._reconstruct_sums(**kwargs) # Redundant xs: mt = u_xs.columns.get_level_values('MT') mt_pert_o = u_pert.columns.get_level_values('MT') @@ -358,7 +368,7 @@ def _custom_multiple_perturbation(self, pert, mat, **kwargs): mask = mt_pert_o.isin(parent) if mt_pert_o.max() == 3: u_pert = u_pert.join(pd.concat([u_pert[(mat, 3)]]*len(mt[mt > 3]), axis=1, - keys=zip([mat]*len(mt[mt > 3]), mt[mt > 3]))) + keys=zip([mat]*len(mt[mt > 3]), mt[mt > 3]))) elif len(mt_pert_o[mask]) != 0: for mt_parent in mt_pert_o[mask].sort_values(ascending=False): mt_pert = mt[(mt.isin(redundant_xs[mt_parent]))] @@ -371,92 +381,6 @@ def _custom_multiple_perturbation(self, pert, mat, **kwargs): .multiply(u_pert, axis='columns') return self.__class__(u_xs)._reconstruct_sums(**kwargs) - def _custom_single_perturbation(self, mat, mt, pert, **kwargs): - """ - Apply a single custom perturbation to a given cross section identified - by a MAT and MT number. - - Parameters - ---------- - mat : `int` - MAT material number of the xs to which perturbations are to be - applied - mt : `int` - MT reaction number of the xs to which perturbations are to be - applied - pert : `sandy.Pert` - tabulated perturbations - **kwargs : `dict` - keyword argument to pass to `sandy.Xs._recontruct_sums`. - - Parameters for _recontruct_sums - --------------------- - drop : `bool`, optional - Keep only mts present in the original file. The default is True. - inplace : `bool`, optional - Argument to define whether the output is a new object or - overwrite the original object.. The default is False. - - Notes - ----- - .. note:: If the mt is redundant, the perturbation applies to all mt - that form the redundant mt. - - Returns - ------- - `sandy.Xs` - cross section instance with given series MAT/MT perturbed - - Examples - -------- - Test single perturbation (non redundant): - >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 10010) - >>> xs = sandy.Xs.from_endf6(endf6) - >>> pert = sandy.Pert([1, 1.05], index=[10, 100]) - >>> pert_xs = xs._custom_single_perturbation(125, 2, pert) - >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() - array([1. , 1.05]) - - >>> (pert_xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)] / xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)]).round(2) - E - 1.00000e-05 1.00000e+00 - 1.00000e+01 1.00000e+00 - 2.00000e+01 1.05000e+00 - 1.00000e+02 1.05000e+00 - 1.00000e+04 1.00000e+00 - Name: (125, 2), dtype: float64 - - Test single perturbation (redundant): - >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 260560) - >>> xs = sandy.Xs.from_endf6(endf6) - >>> pert = sandy.Pert([1, 1.05], index=[1.94000e+08, 1.96000e+08]) - >>> pert_xs = xs._custom_single_perturbation(2631, 1, pert) - >>> (pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3)]]).round(2) - MAT 2631 - MT 1 2 3 - E - 1.92000e+08 1.00000e+00 1.00000e+00 1.00000e+00 - 1.94000e+08 1.00000e+00 1.00000e+00 1.00000e+00 - 1.96000e+08 1.03000e+00 1.05000e+00 1.00000e+00 - 1.98000e+08 1.00000e+00 1.00000e+00 1.00000e+00 - """ - if (mat, mt) not in self.data: - msg = f"could not find MAT{mat}/MT{mt}, " +\ - "perturbation will not be applied" - logging.warning(msg) - u_xs = self - else: - enew = np.union1d(self.data.index.values, pert.right.index.values) - u_xs = self.reshape(enew) - u_pert = pert.reshape(enew) - if mt in self.__class__.redundant_xs: - mt = self.data.columns.get_level_values("MT")\ - .intersection(redundant_xs[mt]).union([mt]) - u_xs.data.loc[:, (mat, mt)] = u_xs.data.loc[:, (mat, mt)]\ - .multiply(u_pert.right, - axis='index') - return self.__class__(u_xs.data)._reconstruct_sums(**kwargs) - def filter_energies(self, energies): mask = self.data.index.isin(energies) data = self.data.loc[mask] diff --git a/sandy/pert.py b/sandy/pert.py index 9dde8232..854dcb7d 100644 --- a/sandy/pert.py +++ b/sandy/pert.py @@ -12,6 +12,17 @@ ] +col = pd.MultiIndex.from_arrays([[2631, 2631], [5, 2]], names=('MAT', 'MT')) +pert = pd.DataFrame([[1, 1.05], [1.05, 1]], + index=pd.IntervalIndex.from_breaks(pd.Index([10, 100]) + .insert(0, 0)), + columns=col) + +pert_ind = pd.Series([1, 1.05], index=pd.IntervalIndex + .from_breaks(pd.Index([10, 100]) + .insert(0, 0))) + + class Pert(): """ Container for tabulated multigroup perturbation coefficients. @@ -42,8 +53,12 @@ class Pert(): def __repr__(self): return self.data.__repr__() - def __init__(self, series, **kwargs): - self.data = pd.Series(series, dtype=float, **kwargs) + def __init__(self, df, **kwargs): + df_ = np.array(df) + if len(df_.shape) == 1: + self.data = pd.Series(df, dtype=float, **kwargs) + else: + self.data = pd.DataFrame(df, dtype=float, **kwargs) @property def data(self): @@ -93,8 +108,27 @@ def right(self): ------- `pandas.Series` perturbations + + Examples + -------- + >>> sandy.Pert(pert_ind).right + 1.00000e+01 1.00000e+00 + 1.00000e+02 1.05000e+00 + dtype: float64 + + >>> sandy.Pert(pert).right + MAT 2631 + MT 5 2 + 1.00000e+01 1.00000e+00 1.05000e+00 + 1.00000e+02 1.05000e+00 1.00000e+00 """ - return pd.Series(self.data.values, index=self.data.index.right) + if len(self.data.shape) == 1: + return pd.Series(self.data.values, + index=self.data.index.right) + else: + return pd.DataFrame(self.data.values, + index=self.data.index.right, + columns=self.data.columns) @property def left(self): @@ -107,8 +141,27 @@ def left(self): ------- `pandas.Series` perturbations + + Examples + -------- + >>> sandy.Pert(pert_ind).left + 0.00000e+00 1.00000e+00 + 1.00000e+01 1.05000e+00 + dtype: float64 + + >>> sandy.Pert(pert).left + MAT 2631 + MT 5 2 + 0.00000e+00 1.00000e+00 1.05000e+00 + 1.00000e+01 1.05000e+00 1.00000e+00 """ - return pd.Series(self.data.values, index=self.data.index.left) + if len(self.data.shape) == 1: + return pd.Series(self.data.values, + index=self.data.index.left) + else: + return pd.DataFrame(self.data.values, + index=self.data.index.left, + columns=self.data.columns) @property def mid(self): @@ -121,8 +174,27 @@ def mid(self): ------- `pandas.Series` perturbations + + Examples + -------- + >>> sandy.Pert(pert_ind).mid + 5.00000e+00 1.00000e+00 + 5.50000e+01 1.05000e+00 + dtype: float64 + + >>> sandy.Pert(pert).mid + MAT 2631 + MT 5 2 + 5.00000e+00 1.00000e+00 1.05000e+00 + 5.50000e+01 1.05000e+00 1.00000e+00 """ - return pd.Series(self.data.values, index=self.data.index.mid) + if len(self.data.shape) == 1: + return pd.Series(self.data.values, + index=self.data.index.mid) + else: + return pd.DataFrame(self.data.values, + index=self.data.index.mid, + columns=self.data.columns) def reshape(self, eg, inplace=False): """ @@ -150,33 +222,69 @@ def reshape(self, eg, inplace=False): if the given energy grid is not monotonic `value.Error` if negative values are found in the given energy grid + + Examples + -------- + >>> sandy.Pert(pert).reshape([0, 1, 5, 25, 50, 100, 1.95000e+08]).data + MAT 2631 + MT 5 2 + ENERGY + (0.0, 1.0] 1.00000e+00 1.05000e+00 + (1.0, 5.0] 1.00000e+00 1.05000e+00 + (5.0, 10.0] 1.00000e+00 1.05000e+00 + (10.0, 25.0] 1.05000e+00 1.00000e+00 + (25.0, 50.0] 1.05000e+00 1.00000e+00 + (50.0, 100.0] 1.05000e+00 1.00000e+00 + (100.0, 195000000.0] 1.00000e+00 1.00000e+00 + + >>> sandy.Pert(pert_ind).reshape([0, 1, 5, 25, 50, 100, 1.95000e+08]).data + ENERGY + (0.0, 1.0] 1.00000e+00 + (1.0, 5.0] 1.00000e+00 + (5.0, 10.0] 1.00000e+00 + (10.0, 25.0] 1.05000e+00 + (25.0, 50.0] 1.05000e+00 + (50.0, 100.0] 1.05000e+00 + (100.0, 195000000.0] 1.00000e+00 + dtype: float64 """ index = pd.Index(eg) + df = self.right if not index.is_monotonic_increasing: raise sandy.Error("energy grid is not monotonic increasing") if (index < 0).any(): raise ValueError("found negative values in the energy grid") - enew = self.right.index.union(index).unique().astype(float).values + enew = df.index.union(index).unique().astype(float).values # remove zero if any, it will be automatically added by `Pert` enew = enew[enew != 0] # this part prevents errors in "scipy.interp1d" when x.size == 1 - x = self.right.index.values - y = self.right.values - if y.size == 1: - # this must be done after that enew is created - x = np.insert(x, 0, 0) - y = np.insert(y, 0, 0) - pertnew = sandy.shared.reshape_bfill( - x, - y, + name = df.index.name + if isinstance(df, pd.Series): + index = df.index.values + values = df.values + if values.size == 1: + # this must be done after that enew is created + index = np.insert(index, 0, 0) + values = np.insert(values, 0, 0) + pertnew = sandy.shared.reshape_bfill( + index, + values, enew, - left_values=1, + left_values="first", right_values=1, ) - series = pd.Series(pertnew, index=enew) + data = pd.Series(pertnew, index=enew) + else: + data = df.apply(lambda x: sandy.shared.reshape_bfill( + x.index.values, + x.values, + enew, + left_values="first", + right_values=1, + )).set_index(enew).rename_axis(name) if not inplace: - return Pert(series) - self.data = series + return self.__class__(data) + self.data = data def truncate(self, low=0.0, high=2.0): """ @@ -196,6 +304,23 @@ def truncate(self, low=0.0, high=2.0): ------- `sandy.Pert` perturbation instance with truncated values. + + Examples + -------- + >>> pert = pd.DataFrame([[-1, 2.55], [2.55, -1]], index =pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0)), columns=col) + >>> sandy.Pert(pert).truncate().data + MAT 2631 + MT 5 2 + ENERGY + (0.0, 10.0] 0.00000e+00 2.00000e+00 + (10.0, 100.0] 2.00000e+00 0.00000e+00 + + >>> pert_ind = pd.Series([-1, 2.05], index=pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0))) + >>> sandy.Pert(pert_ind).truncate().data + ENERGY + (0.0, 10.0] 0.00000e+00 + (10.0, 100.0] 2.00000e+00 + dtype: float64 """ data = self.data.copy() data = data.where(data <= high, high).where(data >= low, low) @@ -222,6 +347,23 @@ def recenter(self, low=0.0, high=2.0, value=1.): ------- `sandy.Pert` perturbation instance with truncated values. + + Examples + -------- + >>> pert = pd.DataFrame([[-1, 2.55], [2.55, -1]], index =pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0)), columns=col) + >>> sandy.Pert(pert).recenter().data + MAT 2631 + MT 5 2 + ENERGY + (0.0, 10.0] 1.00000e+00 1.00000e+00 + (10.0, 100.0] 1.00000e+00 1.00000e+00 + + >>> pert_ind = pd.Series([-1, 2.05], index=pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0))) + >>> sandy.Pert(pert_ind).recenter().data + ENERGY + (0.0, 10.0] 1.00000e+00 + (10.0, 100.0] 1.00000e+00 + dtype: float64 """ data = self.data.copy() data = data.where(data <= high, value).where(data >= low, value) @@ -259,7 +401,7 @@ def from_bin(cls, elow, ehigh, coeff): Parameters ---------- - elow : TYPE + elow : `float` lower energy boundary in eV. ehigh : `float` upper energy boundary in eV. From 2465ef1be3f970b05816f5320da6e9031686fcea Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Thu, 19 May 2022 11:32:33 +0200 Subject: [PATCH 03/21] Erase function --- sandy/core/xs.py | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/sandy/core/xs.py b/sandy/core/xs.py index fff72d96..cb54a813 100644 --- a/sandy/core/xs.py +++ b/sandy/core/xs.py @@ -733,38 +733,3 @@ def eV2MeV(self): df = self.data.copy() df.index = df.index * 1e-6 return df - - -def reshape_df(df, eg): - """ - Reshape energy dependent dataframe with using "bfill" method. - - Parameters - ---------- - df : `pd.Dataframe` - Dataframe to be reshaped. - . - eg : 1D iterable - New energy grid structure. - - Returns - ------- - data : `pd.Dataframe` - Reshaped dataframe. - - """ - index = pd.Index(eg) - if isinstance(index, pd.IntervalIndex): - index = index.right - if isinstance(df.index, pd.IntervalIndex): - df.index = df.index.right - enew = df.index.union(index).unique().astype(float).values - name = df.index.name - data = df.apply(lambda x: sandy.shared.reshape_bfill( - x.index.values, - x.values, - enew, - left_values=1, - right_values=1, - )).set_index(enew).rename_axis(name) - return data From e4a09171ff4012538663536bd7153f2eca2d32d8 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Thu, 19 May 2022 16:00:31 +0200 Subject: [PATCH 04/21] custom perturbation boundary --- sandy/core/xs.py | 48 ++++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/sandy/core/xs.py b/sandy/core/xs.py index cb54a813..56cb6034 100644 --- a/sandy/core/xs.py +++ b/sandy/core/xs.py @@ -156,7 +156,7 @@ def reshape(self, eg): df = pd.DataFrame(xsnew, index=enew, columns=df.columns) return self.__class__(df) - def custom_perturbation(self, pert, mat=None, **kwargs): + def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): """ Function to apply perturbations to individual XS or a group of XS. @@ -191,23 +191,7 @@ def custom_perturbation(self, pert, mat=None, **kwargs): >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 10010) >>> xs = sandy.Xs.from_endf6(endf6) >>> pert = sandy.Pert([1, 1.05], index=[10, 100]) - >>> pert_xs = xs.custom_perturbation(pert, mat=125) - >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() - array([1. , 1.05]) - - >>> (pert_xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)] / xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)]).round(2) - E - 1.00000e-05 1.00000e+00 - 1.00000e+01 1.00000e+00 - 2.00000e+01 1.05000e+00 - 1.00000e+02 1.05000e+00 - 1.00000e+04 1.00000e+00 - Name: (125, 2), dtype: float64 - - Single perturbation in a dataframe: - >>> pert = pd.DataFrame([1, 1.05], index =pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0)), columns=[2]) - >>> pert.columns.name = 'MT' - >>> pert_xs = xs.custom_perturbation(pert, mat=125) + >>> pert_xs = xs.custom_perturbation(pert, mat=125, mt=2) >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() array([1. , 1.05]) @@ -236,23 +220,19 @@ def custom_perturbation(self, pert, mat=None, **kwargs): 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 """ xs = self - # By default, apply the perturbation to all the mat in the object: - if mat is not None: - mat_ = [mat] if isinstance(mat, int) else mat - else: - mat_ = xs.data.columns.get_level_values('MAT').unique() - # Create perturbation object: pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert - # Perturbation data for all the mat numbers: - if isinstance(pert_.data, pd.DataFrame): - if 'MAT' not in pert_.data.columns.names: - pert_ = pd.concat([pert_.data]*len(mat_), names=['MAT'], - keys=mat_, axis=1) - pert_ = sandy.Pert(pert_) - for pert_mat in mat_: - xs = xs._custom_perturbation(pert_, pert_mat, **kwargs) - else: - xs = xs._custom_perturbation(pert_, mat_, **kwargs) + if isinstance(pert_.data, pd.Series): + if mat and mt: + columns = pd.MultiIndex.from_arrays([[mat], [mt]], + names=('MAT', 'MT')) + df = pd.DataFrame(pert_.data.values, index=pert_.data.index, + columns=columns) + pert_ = sandy.Pert(df) + else: + print("The input do not have enought information") + mat_ = pert_.data.columns.get_level_values('MAT').unique() + for pert_mat in mat_: + xs = xs._custom_perturbation(pert_, pert_mat, **kwargs) return xs def _custom_perturbation(self, pert, mat, **kwargs): From 5d27ea4569c7d0c50a3d8c113dc598efe17a94b6 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Thu, 19 May 2022 16:10:20 +0200 Subject: [PATCH 05/21] pert boudaries --- sandy/pert.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sandy/pert.py b/sandy/pert.py index 854dcb7d..ff9a938b 100644 --- a/sandy/pert.py +++ b/sandy/pert.py @@ -239,13 +239,10 @@ def reshape(self, eg, inplace=False): >>> sandy.Pert(pert_ind).reshape([0, 1, 5, 25, 50, 100, 1.95000e+08]).data ENERGY - (0.0, 1.0] 1.00000e+00 - (1.0, 5.0] 1.00000e+00 - (5.0, 10.0] 1.00000e+00 + (0.0, 10.0] 1.00000e+00 (10.0, 25.0] 1.05000e+00 (25.0, 50.0] 1.05000e+00 (50.0, 100.0] 1.05000e+00 - (100.0, 195000000.0] 1.00000e+00 dtype: float64 """ index = pd.Index(eg) @@ -274,6 +271,8 @@ def reshape(self, eg, inplace=False): right_values=1, ) data = pd.Series(pertnew, index=enew) + data = data.loc[(data.index >= index.min()) & + (data.index <= index.max())] else: data = df.apply(lambda x: sandy.shared.reshape_bfill( x.index.values, @@ -282,6 +281,8 @@ def reshape(self, eg, inplace=False): left_values="first", right_values=1, )).set_index(enew).rename_axis(name) + data = data.loc[(data.index >= index.min()) & + (data.index <= index.max()), :] if not inplace: return self.__class__(data) self.data = data From 65d2a2a751ea72934e3c80f87e6c03c6b93872e1 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Thu, 19 May 2022 16:16:53 +0200 Subject: [PATCH 06/21] pert boudaries --- sandy/core/xs.py | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/sandy/core/xs.py b/sandy/core/xs.py index 56cb6034..4a682780 100644 --- a/sandy/core/xs.py +++ b/sandy/core/xs.py @@ -321,26 +321,13 @@ def _custom_perturbation(self, pert, mat, **kwargs): 1.94000e+08 1.03360e+00 1.05000e+00 1.00106e+00 1.00000e+00 1.96000e+08 1.01702e+00 1.00000e+00 1.05085e+00 1.05000e+00 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 - - Pert a series without mt and mat information: - >>> pert = pd.Series([1, 1.05], index=pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.98000e+08]).insert(0, 0))) - >>> pert_xs = xs._custom_perturbation(sandy.Pert(pert), 2631) - >>> pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] - MAT 2631 - MT 1 2 3 5 - E - 1.92000e+08 1.00042e+00 1.00000e+00 1.00121e+00 1.00000e+00 - 1.94000e+08 1.00040e+00 1.00000e+00 1.00106e+00 1.00000e+00 - 1.96000e+08 1.05032e+00 1.05000e+00 1.05085e+00 1.05000e+00 - 1.98000e+08 1.05016e+00 1.05000e+00 1.05047e+00 1.05000e+00 """ # Reshape (all to the right): - enew = np.union1d(self.data.index.values, pert.right.index.values) + index = self.data.index + enew = index.union(pert.right.index.values) + enew = enew[(enew <= index.max()) & (enew >= index.min())] u_xs = self.reshape(enew).data u_pert = pert.reshape(enew).right - if isinstance(u_pert, pd.Series): - u_xs = u_xs.multiply(u_pert, axis='index') - return self.__class__(u_xs)._reconstruct_sums(**kwargs) # Redundant xs: mt = u_xs.columns.get_level_values('MT') mt_pert_o = u_pert.columns.get_level_values('MT') From 61186f92a523a4bab96efd8f421c9f4d748257f9 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Fri, 20 May 2022 11:46:42 +0200 Subject: [PATCH 07/21] bug in pert --- sandy/pert.py | 45 +++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/sandy/pert.py b/sandy/pert.py index ff9a938b..1c663c2a 100644 --- a/sandy/pert.py +++ b/sandy/pert.py @@ -239,11 +239,14 @@ def reshape(self, eg, inplace=False): >>> sandy.Pert(pert_ind).reshape([0, 1, 5, 25, 50, 100, 1.95000e+08]).data ENERGY - (0.0, 10.0] 1.00000e+00 + (0.0, 1.0] 1.00000e+00 + (1.0, 5.0] 1.00000e+00 + (5.0, 10.0] 1.00000e+00 (10.0, 25.0] 1.05000e+00 (25.0, 50.0] 1.05000e+00 (50.0, 100.0] 1.05000e+00 - dtype: float64 + (100.0, 195000000.0] 1.00000e+00 + Name: 0, dtype: float64 """ index = pd.Index(eg) df = self.right @@ -257,32 +260,18 @@ def reshape(self, eg, inplace=False): # this part prevents errors in "scipy.interp1d" when x.size == 1 name = df.index.name if isinstance(df, pd.Series): - index = df.index.values - values = df.values - if values.size == 1: - # this must be done after that enew is created - index = np.insert(index, 0, 0) - values = np.insert(values, 0, 0) - pertnew = sandy.shared.reshape_bfill( - index, - values, - enew, - left_values="first", - right_values=1, - ) - data = pd.Series(pertnew, index=enew) - data = data.loc[(data.index >= index.min()) & - (data.index <= index.max())] - else: - data = df.apply(lambda x: sandy.shared.reshape_bfill( - x.index.values, - x.values, - enew, - left_values="first", - right_values=1, - )).set_index(enew).rename_axis(name) - data = data.loc[(data.index >= index.min()) & - (data.index <= index.max()), :] + df = df.to_frame() + data = df.apply(lambda x: sandy.shared.reshape_bfill( + x.index.values, + x.values, + enew, + left_values="first", + right_values=1, + )).set_index(enew).rename_axis(name) + data = data.loc[(data.index >= index.min()) & + (data.index <= index.max()), :] + if data.shape[1] == 1: + data = data.iloc[:, 0] if not inplace: return self.__class__(data) self.data = data From 6e110c6f6209daa6b49ed195f2cc593e6f4bc6bb Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Fri, 20 May 2022 15:36:57 +0200 Subject: [PATCH 08/21] bug in pert --- sandy/core/xs.py | 9 +-- sandy/pert.py | 139 ++++++++++++++++++++++------------------------- 2 files changed, 71 insertions(+), 77 deletions(-) diff --git a/sandy/core/xs.py b/sandy/core/xs.py index 4a682780..b8c441ee 100644 --- a/sandy/core/xs.py +++ b/sandy/core/xs.py @@ -190,7 +190,7 @@ def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): Test single perturbation: >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 10010) >>> xs = sandy.Xs.from_endf6(endf6) - >>> pert = sandy.Pert([1, 1.05], index=[10, 100]) + >>> pert = pd.Series([1, 1.05], index=[10, 100]) >>> pert_xs = xs.custom_perturbation(pert, mat=125, mt=2) >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() array([1. , 1.05]) @@ -220,16 +220,17 @@ def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 """ xs = self - pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert - if isinstance(pert_.data, pd.Series): + if isinstance(pert, pd.Series): if mat and mt: columns = pd.MultiIndex.from_arrays([[mat], [mt]], names=('MAT', 'MT')) - df = pd.DataFrame(pert_.data.values, index=pert_.data.index, + df = pd.DataFrame(pert.values, index=pert.index, columns=columns) pert_ = sandy.Pert(df) else: print("The input do not have enought information") + else: + pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert mat_ = pert_.data.columns.get_level_values('MAT').unique() for pert_mat in mat_: xs = xs._custom_perturbation(pert_, pert_mat, **kwargs) diff --git a/sandy/pert.py b/sandy/pert.py index 1c663c2a..429902d1 100644 --- a/sandy/pert.py +++ b/sandy/pert.py @@ -54,11 +54,7 @@ def __repr__(self): return self.data.__repr__() def __init__(self, df, **kwargs): - df_ = np.array(df) - if len(df_.shape) == 1: - self.data = pd.Series(df, dtype=float, **kwargs) - else: - self.data = pd.DataFrame(df, dtype=float, **kwargs) + self.data = pd.DataFrame(df, dtype=float, **kwargs) @property def data(self): @@ -112,9 +108,9 @@ def right(self): Examples -------- >>> sandy.Pert(pert_ind).right - 1.00000e+01 1.00000e+00 - 1.00000e+02 1.05000e+00 - dtype: float64 + 0 + 1.00000e+01 1.00000e+00 + 1.00000e+02 1.05000e+00 >>> sandy.Pert(pert).right MAT 2631 @@ -122,13 +118,9 @@ def right(self): 1.00000e+01 1.00000e+00 1.05000e+00 1.00000e+02 1.05000e+00 1.00000e+00 """ - if len(self.data.shape) == 1: - return pd.Series(self.data.values, - index=self.data.index.right) - else: - return pd.DataFrame(self.data.values, - index=self.data.index.right, - columns=self.data.columns) + return pd.DataFrame(self.data.values, + index=self.data.index.right, + columns=self.data.columns) @property def left(self): @@ -145,9 +137,9 @@ def left(self): Examples -------- >>> sandy.Pert(pert_ind).left - 0.00000e+00 1.00000e+00 - 1.00000e+01 1.05000e+00 - dtype: float64 + 0 + 0.00000e+00 1.00000e+00 + 1.00000e+01 1.05000e+00 >>> sandy.Pert(pert).left MAT 2631 @@ -155,13 +147,9 @@ def left(self): 0.00000e+00 1.00000e+00 1.05000e+00 1.00000e+01 1.05000e+00 1.00000e+00 """ - if len(self.data.shape) == 1: - return pd.Series(self.data.values, - index=self.data.index.left) - else: - return pd.DataFrame(self.data.values, - index=self.data.index.left, - columns=self.data.columns) + return pd.DataFrame(self.data.values, + index=self.data.index.left, + columns=self.data.columns) @property def mid(self): @@ -178,9 +166,9 @@ def mid(self): Examples -------- >>> sandy.Pert(pert_ind).mid - 5.00000e+00 1.00000e+00 - 5.50000e+01 1.05000e+00 - dtype: float64 + 0 + 5.00000e+00 1.00000e+00 + 5.50000e+01 1.05000e+00 >>> sandy.Pert(pert).mid MAT 2631 @@ -188,13 +176,9 @@ def mid(self): 5.00000e+00 1.00000e+00 1.05000e+00 5.50000e+01 1.05000e+00 1.00000e+00 """ - if len(self.data.shape) == 1: - return pd.Series(self.data.values, - index=self.data.index.mid) - else: - return pd.DataFrame(self.data.values, - index=self.data.index.mid, - columns=self.data.columns) + return pd.DataFrame(self.data.values, + index=self.data.index.mid, + columns=self.data.columns) def reshape(self, eg, inplace=False): """ @@ -238,40 +222,49 @@ def reshape(self, eg, inplace=False): (100.0, 195000000.0] 1.00000e+00 1.00000e+00 >>> sandy.Pert(pert_ind).reshape([0, 1, 5, 25, 50, 100, 1.95000e+08]).data - ENERGY - (0.0, 1.0] 1.00000e+00 - (1.0, 5.0] 1.00000e+00 - (5.0, 10.0] 1.00000e+00 - (10.0, 25.0] 1.05000e+00 - (25.0, 50.0] 1.05000e+00 - (50.0, 100.0] 1.05000e+00 - (100.0, 195000000.0] 1.00000e+00 - Name: 0, dtype: float64 + 0 + ENERGY + (0.0, 10.0] 1.00000e+00 + (10.0, 25.0] 1.05000e+00 + (25.0, 50.0] 1.05000e+00 + (50.0, 100.0] 1.05000e+00 """ - index = pd.Index(eg) + eg_ = pd.Index(eg) df = self.right - if not index.is_monotonic_increasing: + if not eg_.is_monotonic_increasing: raise sandy.Error("energy grid is not monotonic increasing") - if (index < 0).any(): + if (eg_ < 0).any(): raise ValueError("found negative values in the energy grid") - enew = df.index.union(index).unique().astype(float).values + enew = df.index.union(eg_).unique().astype(float).values # remove zero if any, it will be automatically added by `Pert` enew = enew[enew != 0] # this part prevents errors in "scipy.interp1d" when x.size == 1 name = df.index.name - if isinstance(df, pd.Series): - df = df.to_frame() - data = df.apply(lambda x: sandy.shared.reshape_bfill( - x.index.values, - x.values, - enew, - left_values="first", - right_values=1, - )).set_index(enew).rename_axis(name) - data = data.loc[(data.index >= index.min()) & - (data.index <= index.max()), :] - if data.shape[1] == 1: - data = data.iloc[:, 0] + if df.shape[1] == 1: + index = df.index.values + values = df.values + if values.size == 1: + # this must be done after that enew is created + index = np.insert(index, 0, 0) + values = np.insert(values, 0, 0) + pertnew = sandy.shared.reshape_bfill( + index, + values, + enew, + left_values="first", + right_values=1, + ) + data = pd.DataFrame(pertnew, index=enew, columns=df.columns) + else: + data = df.apply(lambda x: sandy.shared.reshape_bfill( + x.index.values, + x.values, + enew, + left_values="first", + right_values=1, + )).set_index(enew).rename_axis(name) + data = data.loc[(data.index >= eg_.min()) & + (data.index <= eg_.max()), :] if not inplace: return self.__class__(data) self.data = data @@ -307,10 +300,10 @@ def truncate(self, low=0.0, high=2.0): >>> pert_ind = pd.Series([-1, 2.05], index=pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0))) >>> sandy.Pert(pert_ind).truncate().data - ENERGY - (0.0, 10.0] 0.00000e+00 - (10.0, 100.0] 2.00000e+00 - dtype: float64 + 0 + ENERGY + (0.0, 10.0] 0.00000e+00 + (10.0, 100.0] 2.00000e+00 """ data = self.data.copy() data = data.where(data <= high, high).where(data >= low, low) @@ -350,10 +343,10 @@ def recenter(self, low=0.0, high=2.0, value=1.): >>> pert_ind = pd.Series([-1, 2.05], index=pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0))) >>> sandy.Pert(pert_ind).recenter().data - ENERGY - (0.0, 10.0] 1.00000e+00 - (10.0, 100.0] 1.00000e+00 - dtype: float64 + 0 + ENERGY + (0.0, 10.0] 1.00000e+00 + (10.0, 100.0] 1.00000e+00 """ data = self.data.copy() data = data.where(data <= high, value).where(data >= low, value) @@ -406,10 +399,10 @@ def from_bin(cls, elow, ehigh, coeff): Examples -------- >>> Pert.from_bin(1e-5, 1e-4, 0.05) - ENERGY - (0.0, 1e-05] 1.00000e+00 - (1e-05, 0.0001] 1.05000e+00 - dtype: float64 + 0 + ENERGY + (0.0, 1e-05] 1.00000e+00 + (1e-05, 0.0001] 1.05000e+00 """ pert = cls([1, 1 + coeff], index=[elow, ehigh]) return pert From e2886b2c2d57edd9ac10cb7bfd378bf987b8ed48 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Fri, 20 May 2022 15:43:49 +0200 Subject: [PATCH 09/21] lpc custom perturbation add --- sandy/core/lpc.py | 128 +++++++++++++++++++++++++++++++++------------- 1 file changed, 93 insertions(+), 35 deletions(-) diff --git a/sandy/core/lpc.py b/sandy/core/lpc.py index 7470010f..0e520ffb 100644 --- a/sandy/core/lpc.py +++ b/sandy/core/lpc.py @@ -140,9 +140,13 @@ def filter_by(self, key, value): >>> comp = LPC.filter_by('E', 1e-05).data.index.get_level_values(2) == 1e-05 >>> assert comp.all() == True """ - info = {'MAT': 0, 'MT': 1, 'E': 2} - condition = self.data.index.get_level_values(info[key]) == value - out = self.data.copy()[condition] + value_ = [value] if isinstance(value, int) or isinstance(value, float) else value + if key == 'P': + condition = self.data.columns.get_level_values(key).isin(value_) + out = self.data.copy().loc[:, condition] + else: + condition = self.data.index.get_level_values(key).isin(value_) + out = self.data.copy()[condition] if out.empty: raise sandy.Error("applied filter returned empty dataframe") return self.__class__(out) @@ -205,24 +209,81 @@ def custom_perturbation(self, mat, mt, p, pert): >>> mat= 9228 >>> mt= 2 >>> p = 1 - >>> pert= sandy.Pert([1, 1.05], index=[1.00000e+03, 5.00000e+03]) + >>> pert= pd.Series([1, 1.05], index=[1.00000e+03, 5.00000e+03]) >>> pert = LPC.custom_perturbation(mat, mt, p, pert)._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] >>> data = LPC._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] >>> (pert/data).fillna(0) MAT MT E 9228 2 1.00000e-05 0.00000e+00 + 7.73304e+01 0.00000e+00 1.00000e+03 1.00000e+00 2.00000e+03 1.05000e+00 5.00000e+03 1.05000e+00 - 1.00000e+04 1.00000e+00 + 1.00000e+04 0.00000e+00 Name: 1, dtype: float64 """ - eg = self.data.loc[(mat, mt)].index.values - enew = np.union1d(eg, pert.right.index.values) - u_lpc = self.reshape(enew, selected_mat=mat, selected_mt=mt) - u_pert = pert.reshape(enew) - u_lpc.data.loc[(mat, mt)][p] *= u_pert.right.values - return Lpc(u_lpc.data) + if isinstance(pert, pd.Series): + if mat is not None and mt is not None and p is not None: + columns = pd.MultiIndex.from_product([[mat], [mt], [p]], + names=['MAT', 'MT', 'P']) + df = pd.DataFrame(pert.values, index=pert.index, + columns=columns) + pert_ = sandy.Pert(df) + else: + print("The input do not have enought information") + else: + pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert + return self._custom_perturbation(pert_) + + def _custom_perturbation(self, pert): + """ + Apply a energy dependent custom perturbation + + Parameters + ---------- + pert : `sandy.Pert` + tabulated perturbations + + Returns + ------- + `Lpc` + lpc instance with given series polynomial coefficient perturbed + + Examples + -------- + >>> tape = sandy.get_endf6_file("jeff_33",'xs',922350) + >>> LPC = sandy.Lpc.from_endf6(tape) + >>> mat= 9228 + >>> mt= 2 + >>> p = 1 + >>> columns = pd.MultiIndex.from_product([[mat], [mt], [p]], names=['MAT', 'MT', 'P']) + >>> pert= sandy.Pert(pd.DataFrame([1, 1.05], index=[1.00000e+03, 5.00000e+03], columns=columns)) + >>> pert = LPC._custom_perturbation(pert)._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] + >>> data = LPC._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] + >>> (pert/data).fillna(0) + MAT MT E + 9228 2 1.00000e-05 0.00000e+00 + 7.73304e+01 0.00000e+00 + 1.00000e+03 1.00000e+00 + 2.00000e+03 1.05000e+00 + 5.00000e+03 1.05000e+00 + 1.00000e+04 0.00000e+00 + Name: 1, dtype: float64 + """ + energy_grid = self.data.index.get_level_values('E').unique() + enew = energy_grid.union(pert.right.index) + enew = enew[(enew <= energy_grid.max()) & (enew >= energy_grid.min())] + mat = pert.data.columns.get_level_values('MAT').unique().values + mt = pert.data.columns.get_level_values('MT').unique().values + u_pert = pert.reshape(enew).right + u_lpc = self.reshape(enew, selected_mat=mat, selected_mt=mt)\ + .data.unstack(level=['MAT', 'MT']) + u_lpc = u_lpc.reorder_levels(u_pert.columns.names, axis=1) + u_lpc.loc[:, u_pert.columns] = u_lpc.loc[:, u_pert.columns]\ + .multiply(u_pert, axis='columns') + u_lpc = u_lpc.stack(level=['MAT', 'MT'])\ + .reorder_levels(self.data.index.names, axis=0) + return self.__class__(u_lpc) def reshape(self, eg, selected_mat=None, selected_mt=None): """ @@ -258,34 +319,31 @@ def reshape(self, eg, selected_mat=None, selected_mt=None): 0 1.00000e-05 0.00000e+00 0.00000e+00 1 1.00000e+00 1.13380e-06 2.53239e-09 2 2.00000e+00 2.26761e-06 5.06481e-09 - 3 1.00000e+03 1.13381e-03 2.53242e-06 - 4 2.00000e+03 2.93552e-03 1.59183e-05 + 3 7.73304e+01 8.76780e-05 1.95833e-07 + 4 1.00000e+03 1.13381e-03 2.53242e-06 """ - listdf = [] - for (mat, mt), df in self.data.groupby(["MAT", "MT"]): - if selected_mat: - if mat != selected_mat: - listdf.append(df) - continue - if selected_mt: - if mt != selected_mt: - listdf.append(df) - continue - df = df.T[mat][mt].T - enew = df.index.union(eg).astype("float").rename("E") + lpc = self + if selected_mat: + selected_mat_ = [selected_mat] if isinstance(selected_mat, int) else selected_mat + lpc = lpc.filter_by('MAT', selected_mat_) + if selected_mt: + selected_mt_ = [selected_mt] if isinstance(selected_mt, int) else selected_mt + lpc = lpc.filter_by('MT', selected_mt_) + energy_grid = lpc.data.index.get_level_values('E').unique() + enew = energy_grid.union(pd.Index(eg)).astype("float").rename("E") + + def reshape_lpc(df, eg): valsnew = sandy.shared.reshape_differential( - df.index.values, + df.index.get_level_values('E').values, df.values, enew, ) - dfnew = pd.DataFrame(valsnew, index=enew, columns=df.columns) \ - .reset_index(drop=False) - dfnew.insert(0, "MAT", mat) - dfnew.insert(0, "MT", mt) - dfnew.set_index(self._indexnames, inplace=True) - listdf.append(dfnew) - data = pd.concat(listdf, axis=0) - return Lpc(data) + dfnew = pd.DataFrame(valsnew, index=enew, columns=df.columns) + return dfnew.loc[(dfnew.index >= energy_grid.min()) & + (dfnew.index <= energy_grid.max()), :] + + data = lpc.data.groupby(["MAT", "MT"]).apply(reshape_lpc, enew) + return self.__class__(data) def to_endf6(self, endf6): """ @@ -435,7 +493,7 @@ def _add_points(self, extra_points): rdf["MT"] = mt rdf = rdf.set_index(["MAT", "MT", "E"]) List.append(rdf) - return Lpc(pd.concat(List, axis=0)) + return self.__class__(pd.concat(List, axis=0)) def _perturb(self, pert, method=2, **kwargs): """ From 6104758d95b0512bba4807937821f9378556eaad Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Mon, 23 May 2022 16:21:37 +0200 Subject: [PATCH 10/21] edistr perturbation --- sandy/pfns.py | 106 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 27 deletions(-) diff --git a/sandy/pfns.py b/sandy/pfns.py index 5b85195b..9619beb8 100644 --- a/sandy/pfns.py +++ b/sandy/pfns.py @@ -378,7 +378,8 @@ def normalize(self): df = pd.concat(out) return self.__class__(df) - def custom_perturbation(self, pert, mat, mt, k, ein_low, ein_high): + def custom_perturbation(self, pert, mat=None, mt=None, k=None, + ein_low=None, ein_high=None): """ Given a peruration object (fractions), a MAT number, a MT number, a subsection number, a lower and an upper incoming energy bound, @@ -387,18 +388,18 @@ def custom_perturbation(self, pert, mat, mt, k, ein_low, ein_high): Parameters ---------- - pert : `sandy.Pert` + pert : `sandy.Pert` or `pd.Series` perturbation object. - mat : `int` - MAT number. + mat : `int`, optional + MAT number. The default is None. mt : `int` - MT number. + MT number. The default is None. k : `int` - subsection. - ein_low : TYPE - lower energy boundary in eV. - ein_high : TYPE - upper energy boundary in eV. + subsection. The default is None. + ein_low : `float`, optional + lower energy boundary in eV. The default is None. + ein_high : `float`, optional + upper energy boundary in eV. The default is None. Returns ------- @@ -417,7 +418,7 @@ def custom_perturbation(self, pert, mat, mt, k, ein_low, ein_high): Examples -------- >>> orig = Edistr(minimal_edistrtest) - >>> pert = sandy.Pert([1.3], index=[1e-3]) + >>> pert = pd.Series([1.3], index=[1e-3]) >>> orig.custom_perturbation(pert, 9437, 18, 0, 1.5, 2.5) MAT MT K EIN EOUT VALUE 0 9437 18 0 1.00000e+00 1.00000e-05 4.00000e-01 @@ -426,22 +427,73 @@ def custom_perturbation(self, pert, mat, mt, k, ein_low, ein_high): 3 9437 18 0 2.00000e+00 1.00000e+00 7.00000e-01 4 9437 18 0 2.00000e+00 1.00000e+07 1.00000e-01 """ - data = self.data.copy() - condition = (data.MT == mt) &\ - (data.MAT == mat) &\ - (data.K == k) &\ - (data.EIN < ein_high) &\ - (data.EIN >= ein_low) - dfs = [] - dfs.append(data[~condition]) - for ein, df in data[condition].groupby("EIN"): - series = pert.reshape(df.EOUT).data.loc[df.EOUT] - # truncate extremes and replace them with boundaries - px = sandy.Pert(series).truncate() - df.VALUE *= px.data.values - dfs.append(df) - out = pd.concat(dfs) - return self.__class__(out) + if isinstance(pert, pd.Series): + if mat is not None and mt is not None and k is not None and ein_low is not None and ein_high is not None: + columns = pd.MultiIndex.from_product([[mat], [mt], [k], [ein_low], [ein_high]], + names=['MAT', 'MT', 'K', 'ELO', 'EHI']) + df = pd.DataFrame(pert.values, index=pert.index, + columns=columns) + pert_ = sandy.Pert(df) + else: + print("The input do not have enought information") + return + else: + pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert + return self._custom_perturbation(pert_) + + def _custom_perturbation(self, pert): + """ + Apply the perturbation to the outgoing energy distributions for all + incident energies comprised within the given boundarie in the pert + variable columns. + + Parameters + ---------- + pert : `sandy.Pert` + perturbation object + + Returns + ------- + `sandy.Edistr` + perturbed distributions. + + Examples + -------- + >>> orig = Edistr(minimal_edistrtest) + >>> pert = pd.Series([1.3], index=[1e-3]) + >>> columns = pd.MultiIndex.from_product([[9437], [18], [0], [1.5], [2.5]], names=['MAT', 'MT', 'K', 'ELO', 'EHI']) + >>> df = pd.DataFrame(pert.values, index=pert.index, columns=columns) + >>> pert_ = sandy.Pert(df) + >>> orig._custom_perturbation(pert_) + MAT MT K EIN EOUT VALUE + 0 9437 18 0 1.00000e+00 1.00000e-05 4.00000e-01 + 1 9437 18 0 1.00000e+00 2.00000e+07 6.00000e-01 + 2 9437 18 0 2.00000e+00 1.00000e-04 2.60000e-01 + 3 9437 18 0 2.00000e+00 1.00000e+00 7.00000e-01 + 4 9437 18 0 2.00000e+00 1.00000e+07 1.00000e-01 + """ + energy_grid = self.data.loc[:, 'EOUT'].unique() + enew = np.union1d(energy_grid, pert.right.index) + enew = enew[(enew <= energy_grid.max()) & (enew >= energy_grid.min())] + u_pert = pert.reshape(enew).right + + def foo(df, pert): + ein = df.loc[:, 'EIN'].unique()[0] + mat = df.loc[:, 'MAT'].unique()[0] + mt = df.loc[:, 'MT'].unique()[0] + col = pert.columns + mask = (mat == col.get_level_values('MAT')) & (mt == col.get_level_values('MT')) & (ein >= col.get_level_values('ELO')) & (ein <= col.get_level_values('EHI')) + pert_ = pert.loc[:, mask] + if not pert_.empty: + pert_ = pert_.iloc[:, [0]]\ + .reindex(index=df.loc[:, "EOUT"].values)\ + .values\ + .flatten() + df["VALUE"] = df['VALUE'].values * pert_ + return df + pert_edistr = self.data.groupby(['MAT', 'MT', 'K', 'EIN'])\ + .apply(foo, u_pert) + return self.__class__(pert_edistr) def _perturb(self, pert, method=2, normalize=True, **kwargs): """Perturb energy distributions given a set of perturbations. From e21729b50541e7b3faa550b7533234d58989b55e Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Mon, 23 May 2022 16:49:17 +0200 Subject: [PATCH 11/21] updates --- sandy/pert.py | 15 +++++++++------ sandy/pfns.py | 5 ++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/sandy/pert.py b/sandy/pert.py index 429902d1..339468a0 100644 --- a/sandy/pert.py +++ b/sandy/pert.py @@ -222,12 +222,15 @@ def reshape(self, eg, inplace=False): (100.0, 195000000.0] 1.00000e+00 1.00000e+00 >>> sandy.Pert(pert_ind).reshape([0, 1, 5, 25, 50, 100, 1.95000e+08]).data - 0 - ENERGY - (0.0, 10.0] 1.00000e+00 - (10.0, 25.0] 1.05000e+00 - (25.0, 50.0] 1.05000e+00 - (50.0, 100.0] 1.05000e+00 + 0 + ENERGY + (0.0, 1.0] 1.00000e+00 + (1.0, 5.0] 1.00000e+00 + (5.0, 10.0] 1.00000e+00 + (10.0, 25.0] 1.05000e+00 + (25.0, 50.0] 1.05000e+00 + (50.0, 100.0] 1.05000e+00 + (100.0, 195000000.0] 1.00000e+00 """ eg_ = pd.Index(eg) df = self.right diff --git a/sandy/pfns.py b/sandy/pfns.py index 9619beb8..e761f536 100644 --- a/sandy/pfns.py +++ b/sandy/pfns.py @@ -482,7 +482,10 @@ def foo(df, pert): mat = df.loc[:, 'MAT'].unique()[0] mt = df.loc[:, 'MT'].unique()[0] col = pert.columns - mask = (mat == col.get_level_values('MAT')) & (mt == col.get_level_values('MT')) & (ein >= col.get_level_values('ELO')) & (ein <= col.get_level_values('EHI')) + mask = (mat == col.get_level_values('MAT')) & \ + (mt == col.get_level_values('MT')) & \ + (ein >= col.get_level_values('ELO')) & \ + (ein <= col.get_level_values('EHI')) pert_ = pert.loc[:, mask] if not pert_.empty: pert_ = pert_.iloc[:, [0]]\ From 942268aae523016a0074ebc58db80521f9316a25 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Tue, 24 May 2022 09:45:16 +0200 Subject: [PATCH 12/21] reshape in edistr --- sandy/pfns.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/sandy/pfns.py b/sandy/pfns.py index e761f536..22ba47f1 100644 --- a/sandy/pfns.py +++ b/sandy/pfns.py @@ -186,6 +186,64 @@ def get_table(self, mat, mt, k): .sort_index(axis="index") \ .sort_index(axis="columns") + def reshape(self, enew): + """ + Reshape the outgoing energy. + + Parameters + ---------- + enew : 1D iterable or `float` + new energy grid. + + Returns + ------- + `sandy.Edistr` + Energy distribution instance over new grid. + + Examples + -------- + >>> orig = Edistr(minimal_edistrtest) + >>> orig.reshape(1.5) + MAT MT K EIN EOUT VALUE + 0 9437 18 0 1.00000e+00 1.00000e-05 4.00000e-01 + 1 9437 18 0 1.00000e+00 1.50000e+00 4.00000e-01 + 2 9437 18 0 1.00000e+00 2.00000e+07 6.00000e-01 + 3 9437 18 0 2.00000e+00 1.00000e-04 2.00000e-01 + 4 9437 18 0 2.00000e+00 1.00000e+00 7.00000e-01 + 5 9437 18 0 2.00000e+00 1.50000e+00 7.00000e-01 + 6 9437 18 0 2.00000e+00 1.00000e+07 1.00000e-01 + + >>> orig.reshape([1.5e-5, 1.5, 15e6]) + MAT MT K EIN EOUT VALUE + 0 9437 18 0 1.00000e+00 1.00000e-05 4.00000e-01 + 1 9437 18 0 1.00000e+00 1.50000e-05 4.00000e-01 + 2 9437 18 0 1.00000e+00 1.50000e+00 4.00000e-01 + 3 9437 18 0 1.00000e+00 1.50000e+07 5.50000e-01 + 4 9437 18 0 1.00000e+00 2.00000e+07 6.00000e-01 + 5 9437 18 0 2.00000e+00 1.00000e-04 2.00000e-01 + 6 9437 18 0 2.00000e+00 1.00000e+00 7.00000e-01 + 7 9437 18 0 2.00000e+00 1.50000e+00 7.00000e-01 + 8 9437 18 0 2.00000e+00 1.00000e+07 1.00000e-01 + """ + enew_ = np.array(enew) if isinstance(enew, np.ndarray) else enew + + def foo(df, enew): + df_ = df.loc[:, ["EOUT", "VALUE"]].set_index("EOUT") + enew_ = np.union1d(df_.index.values, enew) + enew_ = enew_[(enew_ >= df_.index.min()) & (enew_ <= df_.index.max())] + new_edistr = sandy.shared.reshape_differential( + df_.index.values, + df_.values, + enew_, + ) + new_edistr = pd.DataFrame(new_edistr, index=enew_, + columns=df_.columns) + new_edistr.index.name = 'EOUT' + return new_edistr + edistr_reshape = self.data.groupby(['MAT', 'MT', 'K', 'EIN'])\ + .apply(foo, enew_).reset_index() + return self.__class__(edistr_reshape) + def add_energy_point(self, mat, mt, k, enew): """ Add outgoing energy distribution at one additional incident energy by From 262d98493ab0624a7c6640b71827e8dd295e3e4d Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Tue, 24 May 2022 10:58:43 +0200 Subject: [PATCH 13/21] to_pert in samples --- sandy/core/cov.py | 45 +++++++++++--------- sandy/core/samples.py | 96 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 20 deletions(-) diff --git a/sandy/core/cov.py b/sandy/core/cov.py index 91dfcea5..27eb0469 100644 --- a/sandy/core/cov.py +++ b/sandy/core/cov.py @@ -683,16 +683,18 @@ def sampling(self, nsmp, seed=None, rows=None, pdf='normal', -------- Draw 3 sets of samples using custom seed: >>> sandy.CategoryCov([[1, 0.4],[0.4, 1]]).sampling(3, seed=11) - 0 1 - 0 -7.49455e-01 -2.13159e+00 - 1 1.28607e+00 1.10684e+00 - 2 1.48457e+00 9.00879e-01 + 0 1 + SMP + 0 -7.49455e-01 -2.13159e+00 + 1 1.28607e+00 1.10684e+00 + 2 1.48457e+00 9.00879e-01 >>> sandy.CategoryCov([[1, 0.4],[0.4, 1]]).sampling(3, seed=11, rows=1) - 0 1 - 0 -7.49455e-01 -2.13159e+00 - 1 1.28607e+00 1.10684e+00 - 2 1.48457e+00 9.00879e-01 + 0 1 + SMP + 0 -7.49455e-01 -2.13159e+00 + 1 1.28607e+00 1.10684e+00 + 2 1.48457e+00 9.00879e-01 >>> sample = sandy.CategoryCov([[1, 0.4],[0.4, 1]]).sampling(1000000, seed=11) >>> sample.data.cov() @@ -702,10 +704,11 @@ def sampling(self, nsmp, seed=None, rows=None, pdf='normal', Small negative eigenvalue: >>> sandy.CategoryCov([[1, -.2],[-.2, 3]]).sampling(3, seed=11, tolerance=0) - 0 1 - 0 2.74945e+00 5.21505e+00 - 1 7.13927e-01 1.07147e+00 - 2 5.15435e-01 1.64683e+00 + 0 1 + SMP + 0 2.74945e+00 5.21505e+00 + 1 7.13927e-01 1.07147e+00 + 2 5.15435e-01 1.64683e+00 >>> sandy.CategoryCov([[1, -.2],[-.2, 3]]).sampling(1000000, seed=11, tolerance=0).data.cov() 0 1 @@ -714,16 +717,18 @@ def sampling(self, nsmp, seed=None, rows=None, pdf='normal', Sampling with different `pdf`: >>> sandy.CategoryCov([[1, -.2],[-.2, 3]]).sampling(3, seed=11, pdf='uniform', tolerance=0) - 0 1 - 0 -1.07578e-01 2.34960e+00 - 1 -6.64587e-01 5.21222e-01 - 2 8.72585e-01 9.12563e-01 + 0 1 + SMP + 0 -1.07578e-01 2.34960e+00 + 1 -6.64587e-01 5.21222e-01 + 2 8.72585e-01 9.12563e-01 >>> sandy.CategoryCov([[1, .2],[.2, 3]]).sampling(3, seed=11, pdf='lognormal', tolerance=0) - 0 1 - 0 3.03419e+00 1.57919e+01 - 1 5.57248e-01 4.74160e-01 - 2 4.72366e-01 6.50840e-01 + 0 1 + SMP + 0 3.03419e+00 1.57919e+01 + 1 5.57248e-01 4.74160e-01 + 2 4.72366e-01 6.50840e-01 >>> sandy.CategoryCov([[1, -.2],[-.2, 3]]).sampling(1000000, seed=11, pdf='uniform', tolerance=0).data.cov() 0 1 diff --git a/sandy/core/samples.py b/sandy/core/samples.py index a7021b50..4b8da7e9 100644 --- a/sandy/core/samples.py +++ b/sandy/core/samples.py @@ -89,6 +89,7 @@ def data(self): @data.setter def data(self, data): self._data = data + self._data.index.name = 'SMP' @property def condition_number(self): @@ -262,3 +263,98 @@ def from_csv(cls, file, **kwargs): """ df = pd.read_csv(file, **kwargs) return cls(df) + + def to_pert(self, smp=None): + """ + Samples in the format of `Sandy.Pert`. If the sample number is not + entered, a `pd.DataFrame` is created with a multiindex, the first level + being the sample number and the second the energy grid. + + Parameters + ---------- + smp : `int`, optional + Number of the sample. The default is None. + + Returns + ------- + `sandy.Pert` or `pd.DataFrame` + Samples in `sandy.Pert` format. + + Examples + -------- + >>> samples = pd.DataFrame([[0.5, 1.5], [0.75, 1.25]] , index=[0, 1]) + >>> samples.columns = pd.MultiIndex.from_arrays([[125, 125], [2, 2], [1e-05, 19970500.0]], names=['MAT', 'MT', 'E']) + >>> sandy.Samples(samples).to_pert() + MAT 125 + MT 2 + SMP E + 0 1.00000e-05 5.00000e-01 + 1.99705e+07 1.50000e+00 + 1 1.00000e-05 7.50000e-01 + 1.99705e+07 1.25000e+00 + + >>> sandy.Samples(samples).to_pert(smp=0) + MAT 125 + MT 2 + ENERGY + (0.0, 1e-05] 5.00000e-01 + (1e-05, 19970500.0] 1.50000e+00 + + >>> samples = pd.DataFrame([[0.5, 1.5], [0.75, 1.25]] , index=[0, 1]) + >>> samples.columns = pd.MultiIndex.from_arrays([[125, 125], [2, 2], [1.00000e-05, 1.00000e-05], [1.00000e-05, 1.00000e-05], [1e-05, 19970500.0]], names=['MAT', 'MT', 'ELO', 'EHI', 'E']) + >>> sandy.Samples(samples).to_pert() + MAT 125 + MT 2 + ELO 1.00000e-05 + EHI 1.00000e-05 + SMP E + 0 1.00000e-05 5.00000e-01 + 1.99705e+07 1.50000e+00 + 1 1.00000e-05 7.50000e-01 + 1.99705e+07 1.25000e+00 + + >>> sandy.Samples(samples).to_pert(smp=0) + MAT 125 + MT 2 + ELO 1.00000e-05 + EHI 1.00000e-05 + ENERGY + (0.0, 1e-05] 5.00000e-01 + (1e-05, 19970500.0] 1.50000e+00 + + >>> samples = pd.DataFrame([[0.5, 1.5], [0.75, 1.25]] , index=[0, 1]) + >>> samples.columns = pd.MultiIndex.from_arrays([[125, 125], [2, 2], [1, 1], [1e-05, 19970500.0]], names=['MAT', 'MT', 'L', 'E']) + >>> sandy.Samples(samples).to_pert() + MAT 125 + MT 2 + L 1 + SMP E + 0 1.00000e-05 5.00000e-01 + 1.99705e+07 1.50000e+00 + 1 1.00000e-05 7.50000e-01 + 1.99705e+07 1.25000e+00 + + >>> sandy.Samples(samples).to_pert(smp=0) + MAT 125 + MT 2 + L 1 + ENERGY + (0.0, 1e-05] 5.00000e-01 + (1e-05, 19970500.0] 1.50000e+00 + """ + data = self.data.copy() + levels = list(np.arange(data.columns.nlevels)) + if smp is not None: + if isinstance(smp, int) and smp in data.index: + pert = data.loc[smp].to_frame().unstack(level=levels[0:-1]) + pert.columns = pert.columns.droplevel(level=None) + pert = sandy.Pert(pert) + else: + print(f"{smp} is not correct or do not exist") + else: + def foo(df): + df = df.stack() + df.index = df.index.droplevel(level='SMP') + return df + pert = data.groupby('SMP').apply(foo).fillna(0) + return pert From dbe9c55462d8a9fb2a0ae07d0e3f234c6f346445 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Tue, 24 May 2022 13:49:13 +0200 Subject: [PATCH 14/21] lpc custom perturbation bug for sampling --- sandy/core/lpc.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sandy/core/lpc.py b/sandy/core/lpc.py index 0e520ffb..5d42ddb9 100644 --- a/sandy/core/lpc.py +++ b/sandy/core/lpc.py @@ -279,6 +279,8 @@ def _custom_perturbation(self, pert): u_lpc = self.reshape(enew, selected_mat=mat, selected_mt=mt)\ .data.unstack(level=['MAT', 'MT']) u_lpc = u_lpc.reorder_levels(u_pert.columns.names, axis=1) + if 'L' in u_pert.columns.names: + u_pert.columns = u_pert.columns.set_names('P', level='L') u_lpc.loc[:, u_pert.columns] = u_lpc.loc[:, u_pert.columns]\ .multiply(u_pert, axis='columns') u_lpc = u_lpc.stack(level=['MAT', 'MT'])\ From 1f0db012c6e8b889c2e0672a228f335c71fe0fc7 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Wed, 25 May 2022 10:38:57 +0200 Subject: [PATCH 15/21] mat option --- sandy/core/lpc.py | 28 ++++++++++++++++++---------- sandy/core/xs.py | 12 +++++++++++- sandy/pfns.py | 11 +++++++++-- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/sandy/core/lpc.py b/sandy/core/lpc.py index 5d42ddb9..4d2887e2 100644 --- a/sandy/core/lpc.py +++ b/sandy/core/lpc.py @@ -181,21 +181,21 @@ def _filters(self, conditions): out = out.filter_by(keys, values) return out - def custom_perturbation(self, mat, mt, p, pert): + def custom_perturbation(self, pert, mat=None, mt=None, p=None): """ Apply a custom perturbation (energy dependent) to a given Legendre polynomial coefficient. Parameters ---------- - mat : `int` - MAT material number - mt : `int` - MT reaction number - p : `int` - order of the Legendre polynomial coefficient pert : `sandy.Pert` tabulated perturbations + mat : `int`, optional + MAT material number. The default is None. + mt : `int`, optional + MT reaction number. The default is None. + p : `int`, optional + order of the Legendre polynomial coefficient. The default is None. Returns ------- @@ -210,7 +210,7 @@ def custom_perturbation(self, mat, mt, p, pert): >>> mt= 2 >>> p = 1 >>> pert= pd.Series([1, 1.05], index=[1.00000e+03, 5.00000e+03]) - >>> pert = LPC.custom_perturbation(mat, mt, p, pert)._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] + >>> pert = LPC.custom_perturbation(pert, mat=mat, mt=mt, p=p)._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] >>> data = LPC._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] >>> (pert/data).fillna(0) MAT MT E @@ -233,9 +233,9 @@ def custom_perturbation(self, mat, mt, p, pert): print("The input do not have enought information") else: pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert - return self._custom_perturbation(pert_) + return self._custom_perturbation(pert_, mat=mat) - def _custom_perturbation(self, pert): + def _custom_perturbation(self, pert, mat=None): """ Apply a energy dependent custom perturbation @@ -243,6 +243,8 @@ def _custom_perturbation(self, pert): ---------- pert : `sandy.Pert` tabulated perturbations + mat : `int`, optional + MAT material number. The default is None. Returns ------- @@ -276,6 +278,12 @@ def _custom_perturbation(self, pert): mat = pert.data.columns.get_level_values('MAT').unique().values mt = pert.data.columns.get_level_values('MT').unique().values u_pert = pert.reshape(enew).right + if mat is not None: + u_pert = u_pert.T.query(f"MAT == {mat}").T + if u_pert.empty: + print(f"{mat} is not in perturbation") + return self + u_lpc = self.reshape(enew, selected_mat=mat, selected_mt=mt)\ .data.unstack(level=['MAT', 'MT']) u_lpc = u_lpc.reorder_levels(u_pert.columns.names, axis=1) diff --git a/sandy/core/xs.py b/sandy/core/xs.py index b8c441ee..aa5b0259 100644 --- a/sandy/core/xs.py +++ b/sandy/core/xs.py @@ -231,7 +231,12 @@ def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): print("The input do not have enought information") else: pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert - mat_ = pert_.data.columns.get_level_values('MAT').unique() + + if mat is not None: + mat_ = [mat] if isinstance(mat, int) else mat + else: + mat_ = pert_.data.columns.get_level_values('MAT').unique() + for pert_mat in mat_: xs = xs._custom_perturbation(pert_, pert_mat, **kwargs) return xs @@ -329,6 +334,11 @@ def _custom_perturbation(self, pert, mat, **kwargs): enew = enew[(enew <= index.max()) & (enew >= index.min())] u_xs = self.reshape(enew).data u_pert = pert.reshape(enew).right + if mat is not None: + u_pert = u_pert.T.query(f"MAT == {mat}").T + if u_pert.empty: + print(f"{mat} is not in perturbation") + return self # Redundant xs: mt = u_xs.columns.get_level_values('MT') mt_pert_o = u_pert.columns.get_level_values('MT') diff --git a/sandy/pfns.py b/sandy/pfns.py index 22ba47f1..92d35a40 100644 --- a/sandy/pfns.py +++ b/sandy/pfns.py @@ -497,9 +497,9 @@ def custom_perturbation(self, pert, mat=None, mt=None, k=None, return else: pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert - return self._custom_perturbation(pert_) + return self._custom_perturbation(pert_, mat=mat) - def _custom_perturbation(self, pert): + def _custom_perturbation(self, pert, mat=None): """ Apply the perturbation to the outgoing energy distributions for all incident energies comprised within the given boundarie in the pert @@ -509,6 +509,8 @@ def _custom_perturbation(self, pert): ---------- pert : `sandy.Pert` perturbation object + mat : `int`, optional + MAT number. The default is None. Returns ------- @@ -534,6 +536,11 @@ def _custom_perturbation(self, pert): enew = np.union1d(energy_grid, pert.right.index) enew = enew[(enew <= energy_grid.max()) & (enew >= energy_grid.min())] u_pert = pert.reshape(enew).right + if mat is not None: + u_pert = u_pert.T.query(f"MAT == {mat}").T + if u_pert.empty: + print(f"{mat} is not in perturbation") + return self def foo(df, pert): ein = df.loc[:, 'EIN'].unique()[0] From 2b2decb844a5b212f512f1be67c6fd8773ad3129 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Thu, 2 Jun 2022 12:13:34 +0200 Subject: [PATCH 16/21] Update --- sandy/core/lpc.py | 83 +++++----------------------- sandy/core/xs.py | 138 +++++++++------------------------------------- sandy/pert.py | 35 ++++++++++++ sandy/pfns.py | 67 ++++------------------ 4 files changed, 87 insertions(+), 236 deletions(-) diff --git a/sandy/core/lpc.py b/sandy/core/lpc.py index 4d2887e2..a94c6e0d 100644 --- a/sandy/core/lpc.py +++ b/sandy/core/lpc.py @@ -181,70 +181,15 @@ def _filters(self, conditions): out = out.filter_by(keys, values) return out - def custom_perturbation(self, pert, mat=None, mt=None, p=None): + def custom_perturbation(self, pert): """ Apply a custom perturbation (energy dependent) to a given Legendre polynomial coefficient. Parameters ---------- - pert : `sandy.Pert` - tabulated perturbations - mat : `int`, optional - MAT material number. The default is None. - mt : `int`, optional - MT reaction number. The default is None. - p : `int`, optional - order of the Legendre polynomial coefficient. The default is None. - - Returns - ------- - `Lpc` - lpc instance with given series polynomial coefficient perturbed - - Examples - -------- - >>> tape = sandy.get_endf6_file("jeff_33",'xs',922350) - >>> LPC = sandy.Lpc.from_endf6(tape) - >>> mat= 9228 - >>> mt= 2 - >>> p = 1 - >>> pert= pd.Series([1, 1.05], index=[1.00000e+03, 5.00000e+03]) - >>> pert = LPC.custom_perturbation(pert, mat=mat, mt=mt, p=p)._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] - >>> data = LPC._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] - >>> (pert/data).fillna(0) - MAT MT E - 9228 2 1.00000e-05 0.00000e+00 - 7.73304e+01 0.00000e+00 - 1.00000e+03 1.00000e+00 - 2.00000e+03 1.05000e+00 - 5.00000e+03 1.05000e+00 - 1.00000e+04 0.00000e+00 - Name: 1, dtype: float64 - """ - if isinstance(pert, pd.Series): - if mat is not None and mt is not None and p is not None: - columns = pd.MultiIndex.from_product([[mat], [mt], [p]], - names=['MAT', 'MT', 'P']) - df = pd.DataFrame(pert.values, index=pert.index, - columns=columns) - pert_ = sandy.Pert(df) - else: - print("The input do not have enought information") - else: - pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert - return self._custom_perturbation(pert_, mat=mat) - - def _custom_perturbation(self, pert, mat=None): - """ - Apply a energy dependent custom perturbation - - Parameters - ---------- - pert : `sandy.Pert` - tabulated perturbations - mat : `int`, optional - MAT material number. The default is None. + pert : `sandy.Pert` or `pd.DataFrame` + tabulated perturbation Returns ------- @@ -260,7 +205,7 @@ def _custom_perturbation(self, pert, mat=None): >>> p = 1 >>> columns = pd.MultiIndex.from_product([[mat], [mt], [p]], names=['MAT', 'MT', 'P']) >>> pert= sandy.Pert(pd.DataFrame([1, 1.05], index=[1.00000e+03, 5.00000e+03], columns=columns)) - >>> pert = LPC._custom_perturbation(pert)._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] + >>> pert = LPC.custom_perturbation(pert)._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] >>> data = LPC._filters({'MAT': mat, 'MT':2}).data.loc[:,1].iloc[0:5] >>> (pert/data).fillna(0) MAT MT E @@ -272,23 +217,23 @@ def _custom_perturbation(self, pert, mat=None): 1.00000e+04 0.00000e+00 Name: 1, dtype: float64 """ + pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert + if 'L' in pert_.data.columns.names: + pert_.data.columns = pert_.data.columns.set_names('P', level='L') + + # New energy grid: energy_grid = self.data.index.get_level_values('E').unique() enew = energy_grid.union(pert.right.index) enew = enew[(enew <= energy_grid.max()) & (enew >= energy_grid.min())] + + # Reshape to new energy grid and columns estructure: mat = pert.data.columns.get_level_values('MAT').unique().values mt = pert.data.columns.get_level_values('MT').unique().values - u_pert = pert.reshape(enew).right - if mat is not None: - u_pert = u_pert.T.query(f"MAT == {mat}").T - if u_pert.empty: - print(f"{mat} is not in perturbation") - return self - u_lpc = self.reshape(enew, selected_mat=mat, selected_mt=mt)\ .data.unstack(level=['MAT', 'MT']) - u_lpc = u_lpc.reorder_levels(u_pert.columns.names, axis=1) - if 'L' in u_pert.columns.names: - u_pert.columns = u_pert.columns.set_names('P', level='L') + u_pert = pert_.reorder(u_lpc.columns).reshape(enew).right + + # Aply perturbation: u_lpc.loc[:, u_pert.columns] = u_lpc.loc[:, u_pert.columns]\ .multiply(u_pert, axis='columns') u_lpc = u_lpc.stack(level=['MAT', 'MT'])\ diff --git a/sandy/core/xs.py b/sandy/core/xs.py index aa5b0259..2f979c5c 100644 --- a/sandy/core/xs.py +++ b/sandy/core/xs.py @@ -156,7 +156,7 @@ def reshape(self, eg): df = pd.DataFrame(xsnew, index=enew, columns=df.columns) return self.__class__(df) - def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): + def custom_perturbation(self, pert, **kwargs): """ Function to apply perturbations to individual XS or a group of XS. @@ -165,10 +165,6 @@ def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): pert : `sandy.Pert` or `pd.Dataframe` tabulated perturbations with the index representing the energy grid and the columns representing MT. - mat : `int`, optional - MAT number. The default is None. - mt : `int`, optional - MT number. The default is None. **kwargs : `dict` keyword argument to pass to `sandy.Xs._recontruct_sums`. @@ -190,91 +186,9 @@ def custom_perturbation(self, pert, mat=None, mt=None, **kwargs): Test single perturbation: >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 10010) >>> xs = sandy.Xs.from_endf6(endf6) - >>> pert = pd.Series([1, 1.05], index=[10, 100]) - >>> pert_xs = xs.custom_perturbation(pert, mat=125, mt=2) - >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() - array([1. , 1.05]) - - >>> (pert_xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)] / xs.data.loc[[1.00000e-05, 10, 20.0, 100, 10000.0], (125, 2)]).round(2) - E - 1.00000e-05 1.00000e+00 - 1.00000e+01 1.00000e+00 - 2.00000e+01 1.05000e+00 - 1.00000e+02 1.05000e+00 - 1.00000e+04 1.00000e+00 - Name: (125, 2), dtype: float64 - - Multiple perturbation: - >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 260560) - >>> xs = sandy.Xs.from_endf6(endf6) - >>> col = pd.MultiIndex.from_arrays([[2631, 2631], [5, 2]], names=('MAT', 'MT')) - >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) - >>> pert_xs = xs.custom_perturbation(pert) - >>> pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] - MAT 2631 - MT 1 2 3 5 - E - 1.92000e+08 1.03353e+00 1.05000e+00 1.00121e+00 1.00000e+00 - 1.94000e+08 1.03360e+00 1.05000e+00 1.00106e+00 1.00000e+00 - 1.96000e+08 1.01702e+00 1.00000e+00 1.05085e+00 1.05000e+00 - 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 - """ - xs = self - if isinstance(pert, pd.Series): - if mat and mt: - columns = pd.MultiIndex.from_arrays([[mat], [mt]], - names=('MAT', 'MT')) - df = pd.DataFrame(pert.values, index=pert.index, - columns=columns) - pert_ = sandy.Pert(df) - else: - print("The input do not have enought information") - else: - pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert - - if mat is not None: - mat_ = [mat] if isinstance(mat, int) else mat - else: - mat_ = pert_.data.columns.get_level_values('MAT').unique() - - for pert_mat in mat_: - xs = xs._custom_perturbation(pert_, pert_mat, **kwargs) - return xs - - def _custom_perturbation(self, pert, mat, **kwargs): - """ - Custom a set of perturbation to the Xs object. - - Parameters - ---------- - pert : `sandy.Pert` - tabulated perturbations - mat : `int` - MAT number. - **kwargs : `dict` - keyword argument to pass to `sandy.Xs._recontruct_sums`. - - Parameters for _recontruct_sums - --------------------- - drop : `bool`, optional - Keep only mts present in the original file. The default is True. - inplace : `bool`, optional - Argument to define whether the output is a new object or - overwrite the original object.. The default is False. - - Returns - ------- - `sandy.Xs` - Perturbed Xs. - - Examples - -------- - Test single perturbation (Non redundant): - >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 10010) - >>> xs = sandy.Xs.from_endf6(endf6) >>> col = pd.MultiIndex.from_arrays([[125], [2]], names=('MAT', 'MT')) >>> pert = pd.DataFrame([1, 1.05], index =pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0)), columns=col) - >>> pert_xs = xs._custom_perturbation(sandy.Pert(pert), 125) + >>> pert_xs = xs.custom_perturbation(sandy.Pert(pert)) >>> (pert_xs.data.loc[:, (125, 2)] / xs.data.loc[:, (125, 2)]).round(2).unique() array([1. , 1.05]) @@ -287,12 +201,13 @@ def _custom_perturbation(self, pert, mat, **kwargs): 1.00000e+04 1.00000e+00 Name: (125, 2), dtype: float64 + Multiple perturbation: Test single perturbation (Redundant): >>> endf6 = sandy.get_endf6_file('jeff_33','xs', 260560) >>> xs = sandy.Xs.from_endf6(endf6) >>> col = pd.MultiIndex.from_arrays([[2631], [1]], names=('MAT', 'MT')) >>> pert = pd.DataFrame([1, 1.05], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08]).insert(0, 0)), columns=col) - >>> pert_xs = xs._custom_perturbation(sandy.Pert(pert), 2631) + >>> pert_xs = xs.custom_perturbation(sandy.Pert(pert)) >>> (pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3)]]).round(2) MAT 2631 MT 1 2 3 @@ -305,7 +220,7 @@ def _custom_perturbation(self, pert, mat, **kwargs): Multiple perturbation(redundant + non redundant, mt perturb max = 3) >>> col = pd.MultiIndex.from_arrays([[2631, 2631], [3, 2]], names=('MAT', 'MT')) >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) - >>> pert_xs = xs._custom_perturbation(sandy.Pert(pert), 2631) + >>> pert_xs = xs.custom_perturbation(sandy.Pert(pert)) >>> pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] MAT 2631 MT 1 2 3 5 @@ -318,7 +233,7 @@ def _custom_perturbation(self, pert, mat, **kwargs): Multiple perturbation(non redundant): >>> col = pd.MultiIndex.from_arrays([[2631, 2631], [5, 2]], names=('MAT', 'MT')) >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) - >>> pert_xs = xs._custom_perturbation(sandy.Pert(pert), 2631) + >>> pert_xs = xs.custom_perturbation(sandy.Pert(pert)) >>> pert_xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] / xs.data.loc[[1.92000e+08, 1.94000e+08, 1.96000e+08, 1.98000e+08], [(2631, 1), (2631, 2), (2631, 3), (2631, 5)]] MAT 2631 MT 1 2 3 5 @@ -328,32 +243,33 @@ def _custom_perturbation(self, pert, mat, **kwargs): 1.96000e+08 1.01702e+00 1.00000e+00 1.05085e+00 1.05000e+00 1.98000e+08 1.00016e+00 1.00000e+00 1.00044e+00 1.00000e+00 """ + pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert # Reshape (all to the right): index = self.data.index enew = index.union(pert.right.index.values) enew = enew[(enew <= index.max()) & (enew >= index.min())] u_xs = self.reshape(enew).data - u_pert = pert.reshape(enew).right - if mat is not None: - u_pert = u_pert.T.query(f"MAT == {mat}").T - if u_pert.empty: - print(f"{mat} is not in perturbation") - return self + u_pert = pert_.reorder(self.data.columns).reshape(enew).right # Redundant xs: - mt = u_xs.columns.get_level_values('MT') - mt_pert_o = u_pert.columns.get_level_values('MT') - parent = pd.Index(self.__class__.redundant_xs.keys()) - mask = mt_pert_o.isin(parent) - if mt_pert_o.max() == 3: - u_pert = u_pert.join(pd.concat([u_pert[(mat, 3)]]*len(mt[mt > 3]), axis=1, - keys=zip([mat]*len(mt[mt > 3]), mt[mt > 3]))) - elif len(mt_pert_o[mask]) != 0: - for mt_parent in mt_pert_o[mask].sort_values(ascending=False): - mt_pert = mt[(mt.isin(redundant_xs[mt_parent]))] - mt_pert = mt_pert[~(mt_pert.isin(mt_pert_o))] - if len(mt_pert) != 0: - u_pert = u_pert.join(pd.concat([u_pert[(mat, mt_parent)]]*len(mt_pert), axis=1, - keys=zip([mat]*len(mt_pert), mt_pert))) + for mat in u_pert.columns.get_level_values('MAT'): + mt = u_xs[(mat)].columns.get_level_values('MT') + mt_pert_o = u_pert[(mat)].columns.get_level_values('MT') + parent = pd.Index(self.__class__.redundant_xs.keys()) + mask = mt_pert_o.isin(parent) + if mt_pert_o.max() == 3: + u_pert = u_pert.join(pd.concat([u_pert[(mat, 3)]]*len(mt[mt > 3]), + axis=1, + keys=zip([mat]*len(mt[mt > 3]), + mt[mt > 3]))) + elif len(mt_pert_o[mask]) != 0: + for mt_parent in mt_pert_o[mask].sort_values(ascending=False): + mt_pert = mt[(mt.isin(redundant_xs[mt_parent]))] + mt_pert = mt_pert[~(mt_pert.isin(mt_pert_o))] + if len(mt_pert) != 0: + u_pert = u_pert.join(pd.concat([u_pert[(mat, mt_parent)]]*len(mt_pert), + axis=1, + keys=zip([mat]*len(mt_pert), + mt_pert))) # Apply pertubation: u_xs.loc[:, u_pert.columns] = u_xs.loc[:, u_pert.columns]\ .multiply(u_pert, axis='columns') diff --git a/sandy/pert.py b/sandy/pert.py index 339468a0..9c17f384 100644 --- a/sandy/pert.py +++ b/sandy/pert.py @@ -180,6 +180,41 @@ def mid(self): index=self.data.index.mid, columns=self.data.columns) + def reorder(self, columns): + """ + Sort the levels in the columns of `Sandy.Pert` + + Parameters + ---------- + columns : `pd.Multiindex` + New columns order. + + Returns + ------- + `sandy.Pert` + Pert order with sort levels. + + Examples + -------- + >>> col = pd.MultiIndex.from_arrays([[5, 2], [2631, 2631]], names=('MT', 'MAT')) + >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) + >>> col_new = pd.MultiIndex.from_arrays([[2631, 2631], [2, 5]], names=('MT', 'MAT')) + >>> sandy.Pert(pert).reorder(['MAT', 'MT']) + MAT 2631 + MT 2 5 + ENERGY + (0.0, 194000000.0] 1.05000e+00 1.00000e+00 + (194000000.0, 196000001.0] 1.00000e+00 1.05000e+00 + """ + data = self.data + for name in columns.names: + if name not in self.data.columns.names: + print("Levels do not match") + return + data_reorder = data.reorder_levels(columns.names, axis=1) + col = columns.intersection(data_reorder.columns) + return sandy.Pert(data_reorder[col]) + def reshape(self, eg, inplace=False): """ Interpolate perturbation over new energy grid structure using `bfill` diff --git a/sandy/pfns.py b/sandy/pfns.py index 92d35a40..994cc411 100644 --- a/sandy/pfns.py +++ b/sandy/pfns.py @@ -436,8 +436,7 @@ def normalize(self): df = pd.concat(out) return self.__class__(df) - def custom_perturbation(self, pert, mat=None, mt=None, k=None, - ein_low=None, ein_high=None): + def custom_perturbation(self, pert): """ Given a peruration object (fractions), a MAT number, a MT number, a subsection number, a lower and an upper incoming energy bound, @@ -446,8 +445,8 @@ def custom_perturbation(self, pert, mat=None, mt=None, k=None, Parameters ---------- - pert : `sandy.Pert` or `pd.Series` - perturbation object. + pert : `sandy.Pert` or `pd.DataFrame` + Tabulated perturbation. mat : `int`, optional MAT number. The default is None. mt : `int` @@ -473,50 +472,6 @@ def custom_perturbation(self, pert, mat=None, mt=None, k=None, .. note:: If the perturbation exceeds 100%, it is truncated. - Examples - -------- - >>> orig = Edistr(minimal_edistrtest) - >>> pert = pd.Series([1.3], index=[1e-3]) - >>> orig.custom_perturbation(pert, 9437, 18, 0, 1.5, 2.5) - MAT MT K EIN EOUT VALUE - 0 9437 18 0 1.00000e+00 1.00000e-05 4.00000e-01 - 1 9437 18 0 1.00000e+00 2.00000e+07 6.00000e-01 - 2 9437 18 0 2.00000e+00 1.00000e-04 2.60000e-01 - 3 9437 18 0 2.00000e+00 1.00000e+00 7.00000e-01 - 4 9437 18 0 2.00000e+00 1.00000e+07 1.00000e-01 - """ - if isinstance(pert, pd.Series): - if mat is not None and mt is not None and k is not None and ein_low is not None and ein_high is not None: - columns = pd.MultiIndex.from_product([[mat], [mt], [k], [ein_low], [ein_high]], - names=['MAT', 'MT', 'K', 'ELO', 'EHI']) - df = pd.DataFrame(pert.values, index=pert.index, - columns=columns) - pert_ = sandy.Pert(df) - else: - print("The input do not have enought information") - return - else: - pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert - return self._custom_perturbation(pert_, mat=mat) - - def _custom_perturbation(self, pert, mat=None): - """ - Apply the perturbation to the outgoing energy distributions for all - incident energies comprised within the given boundarie in the pert - variable columns. - - Parameters - ---------- - pert : `sandy.Pert` - perturbation object - mat : `int`, optional - MAT number. The default is None. - - Returns - ------- - `sandy.Edistr` - perturbed distributions. - Examples -------- >>> orig = Edistr(minimal_edistrtest) @@ -524,7 +479,7 @@ def _custom_perturbation(self, pert, mat=None): >>> columns = pd.MultiIndex.from_product([[9437], [18], [0], [1.5], [2.5]], names=['MAT', 'MT', 'K', 'ELO', 'EHI']) >>> df = pd.DataFrame(pert.values, index=pert.index, columns=columns) >>> pert_ = sandy.Pert(df) - >>> orig._custom_perturbation(pert_) + >>> orig.custom_perturbation(pert_) MAT MT K EIN EOUT VALUE 0 9437 18 0 1.00000e+00 1.00000e-05 4.00000e-01 1 9437 18 0 1.00000e+00 2.00000e+07 6.00000e-01 @@ -532,16 +487,17 @@ def _custom_perturbation(self, pert, mat=None): 3 9437 18 0 2.00000e+00 1.00000e+00 7.00000e-01 4 9437 18 0 2.00000e+00 1.00000e+07 1.00000e-01 """ + pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert + + # New energy grid: energy_grid = self.data.loc[:, 'EOUT'].unique() enew = np.union1d(energy_grid, pert.right.index) enew = enew[(enew <= energy_grid.max()) & (enew >= energy_grid.min())] + + # Reshape to new energy grid and columns estructure: u_pert = pert.reshape(enew).right - if mat is not None: - u_pert = u_pert.T.query(f"MAT == {mat}").T - if u_pert.empty: - print(f"{mat} is not in perturbation") - return self + # Apply the perturbation: def foo(df, pert): ein = df.loc[:, 'EIN'].unique()[0] mat = df.loc[:, 'MAT'].unique()[0] @@ -555,8 +511,7 @@ def foo(df, pert): if not pert_.empty: pert_ = pert_.iloc[:, [0]]\ .reindex(index=df.loc[:, "EOUT"].values)\ - .values\ - .flatten() + .values.flatten() df["VALUE"] = df['VALUE'].values * pert_ return df pert_edistr = self.data.groupby(['MAT', 'MT', 'K', 'EIN'])\ From 22f3f723eca06b5d9df9cd7557d40000b56d49fa Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Thu, 2 Jun 2022 13:15:45 +0200 Subject: [PATCH 17/21] Update --- sandy/pert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sandy/pert.py b/sandy/pert.py index 9c17f384..0ef30e8b 100644 --- a/sandy/pert.py +++ b/sandy/pert.py @@ -199,7 +199,7 @@ def reorder(self, columns): >>> col = pd.MultiIndex.from_arrays([[5, 2], [2631, 2631]], names=('MT', 'MAT')) >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) >>> col_new = pd.MultiIndex.from_arrays([[2631, 2631], [2, 5]], names=('MT', 'MAT')) - >>> sandy.Pert(pert).reorder(['MAT', 'MT']) + >>> sandy.Pert(pert).reorder(col_new) MAT 2631 MT 2 5 ENERGY From 3d00f8d52f08eb1239bd54a1801149b77c6b8ad0 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Thu, 2 Jun 2022 13:21:17 +0200 Subject: [PATCH 18/21] Update --- sandy/pert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sandy/pert.py b/sandy/pert.py index 0ef30e8b..312c1205 100644 --- a/sandy/pert.py +++ b/sandy/pert.py @@ -198,7 +198,7 @@ def reorder(self, columns): -------- >>> col = pd.MultiIndex.from_arrays([[5, 2], [2631, 2631]], names=('MT', 'MAT')) >>> pert = pd.DataFrame([[1, 1.05], [1.05, 1]], index =pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)), columns=col) - >>> col_new = pd.MultiIndex.from_arrays([[2631, 2631], [2, 5]], names=('MT', 'MAT')) + >>> col_new = pd.MultiIndex.from_arrays([[2631, 2631], [2, 5]], names=('MAT', 'MT')) >>> sandy.Pert(pert).reorder(col_new) MAT 2631 MT 2 5 From 5d7d2ba1fdee479d7aaa2036c24a32b2ded03844 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Fri, 3 Jun 2022 15:37:44 +0200 Subject: [PATCH 19/21] Notebook --- .../notebook_Edistr_custom_perturbation.ipynb | 133 +++++++++++++ .../notebook_Lpc_custom_perturbation.ipynb | 111 +++++++++++ .../notebook_Xs_custom_perturbation.ipynb | 100 ++++++++++ ...ook_from_sandy.Samples_to_sandy.Pert.ipynb | 179 ++++++++++++++++++ .../notebook_reorder_of_sandy.Pert.ipynb | 127 +++++++++++++ .../notebook_reshape_of_sandy.Pert.ipynb | 105 ++++++++++ 6 files changed, 755 insertions(+) create mode 100644 notebooks/notebook_Edistr_custom_perturbation.ipynb create mode 100644 notebooks/notebook_Lpc_custom_perturbation.ipynb create mode 100644 notebooks/notebook_Xs_custom_perturbation.ipynb create mode 100644 notebooks/notebook_from_sandy.Samples_to_sandy.Pert.ipynb create mode 100644 notebooks/notebook_reorder_of_sandy.Pert.ipynb create mode 100644 notebooks/notebook_reshape_of_sandy.Pert.ipynb diff --git a/notebooks/notebook_Edistr_custom_perturbation.ipynb b/notebooks/notebook_Edistr_custom_perturbation.ipynb new file mode 100644 index 00000000..83adc1bf --- /dev/null +++ b/notebooks/notebook_Edistr_custom_perturbation.ipynb @@ -0,0 +1,133 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sandy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "col = columns = pd.MultiIndex.from_product([[9237], [18], [0], [1.00000e-05], [2.00000e-05]], names=['MAT', 'MT', 'K', 'ELO', 'EHI'])\n", + "pert = pd.DataFrame([1.3, 1.5, 1.2, 1.1, 1, 0.7, 1.6, 0.5, 1.8, 1.5, 0.6, 1.5, 0.8], \n", + " index=sandy.energy_grids.CASMO12,\n", + " columns=col)\n", + "pert = sandy.Pert(pert)\n", + "pert" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Custom perturbation of U-238:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "extra_points = np.logspace(-5, 7, 49)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "edistr = sandy.Edistr.from_endf6(sandy.get_endf6_file(\"jeff_33\", \"xs\", 922380)).reshape(extra_points)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "edistr_pert = edistr.custom_perturbation(pert)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mask = (9237 == edistr.data.MAT) & \\\n", + " (18 == edistr.data.MT) & \\\n", + " (0 == edistr.data.K) & \\\n", + " (1.00000e-05 == edistr.data.EIN)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(7, 3.5), dpi=100)\n", + "edistr.data[mask][['EOUT', \"VALUE\"]].set_index('EOUT').plot(logx=True, logy=True, alpha=0.8, linewidth=0.9, ax=ax)\n", + "edistr_pert.data[mask][['EOUT', \"VALUE\"]].set_index('EOUT').plot(logx=True, logy=True, alpha=0.8, linewidth=0.9, ax=ax)\n", + "ax.set_ylabel(\"Legendre polynomial coefficients for P=1\")\n", + "ax.set_xlabel(\"energy / eV\")\n", + "fig.tight_layout()" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "d167b81dab4cfdd7e83bd7f0413ce20e956b35802f4873808516fc813094dcfb" + }, + "kernelspec": { + "display_name": "Python 3.7.10 ('sandy-devel')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/notebook_Lpc_custom_perturbation.ipynb b/notebooks/notebook_Lpc_custom_perturbation.ipynb new file mode 100644 index 00000000..448b6357 --- /dev/null +++ b/notebooks/notebook_Lpc_custom_perturbation.ipynb @@ -0,0 +1,111 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sandy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "col = pd.MultiIndex.from_arrays([[2], [9237], [1]], names=('MT', 'MAT', 'P'))\n", + "pert = pd.DataFrame([1.3, 1.5, 1.2, 1.1, 1, 0.7, 1.6, 0.5, 1.8, 1.5, 0.6, 1.5, 0.8], \n", + " index=sandy.energy_grids.CASMO12,\n", + " columns=col)\n", + "pert = sandy.Pert(pert)\n", + "pert" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Custom perturbation of U-238:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "extra_points = np.logspace(-5, 7, 49)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lpc = sandy.Lpc.from_endf6(sandy.get_endf6_file(\"jeff_33\", \"xs\", 922380)).reshape(extra_points)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lpc_pert = lpc.custom_perturbation(pert)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(7, 3.5), dpi=100)\n", + "lpc.data.loc[(9237, 2), (1)].plot(logx=True, logy=True, alpha=0.8, linewidth=0.9, ax=ax)\n", + "lpc_pert.data.loc[(9237, 2), (1)].plot(logx=True, logy=True, alpha=0.8, linewidth=0.9, ax=ax)\n", + "ax.set_ylabel(\"Legendre polynomial coefficients for P=1\")\n", + "ax.set_xlabel(\"energy / eV\")\n", + "fig.tight_layout()" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "d167b81dab4cfdd7e83bd7f0413ce20e956b35802f4873808516fc813094dcfb" + }, + "kernelspec": { + "display_name": "Python 3.7.10 ('sandy-devel')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/notebook_Xs_custom_perturbation.ipynb b/notebooks/notebook_Xs_custom_perturbation.ipynb new file mode 100644 index 00000000..c538e342 --- /dev/null +++ b/notebooks/notebook_Xs_custom_perturbation.ipynb @@ -0,0 +1,100 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sandy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "col = pd.MultiIndex.from_arrays([[2], [125]], names=('MT', 'MAT'))\n", + "pert = pd.DataFrame([1.3, 1.5, 1.2, 1.1, 1, 0.7, 1.6, 0.5, 1.8, 1.5, 0.6, 1.5, 0.8], \n", + " index=sandy.energy_grids.CASMO12,\n", + " columns=col)\n", + "pert = sandy.Pert(pert)\n", + "pert" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Custom perturbation of H:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xs = sandy.Xs.from_endf6(sandy.get_endf6_file(\"jeff_33\", \"xs\", 10010))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xs_pert = xs.custom_perturbation(pert)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(7, 3.5), dpi=100)\n", + "xs.data.plot(logx=True, logy=True, alpha=0.8, linewidth=0.9, ax=ax)\n", + "xs_pert.data.plot(logx=True, logy=True, alpha=0.8, linewidth=0.9, ax=ax)\n", + "ax.set_ylabel(\"cross section / b\")\n", + "ax.set_xlabel(\"energy / eV\")\n", + "ax.set_xlim([1e-5, 2e7])\n", + "ax.set_ylim([1e-1, 1e4])\n", + "fig.tight_layout()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python3 (sandy-devel)", + "language": "python", + "name": "sandy-devel" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/notebook_from_sandy.Samples_to_sandy.Pert.ipynb b/notebooks/notebook_from_sandy.Samples_to_sandy.Pert.ipynb new file mode 100644 index 00000000..da8c3b21 --- /dev/null +++ b/notebooks/notebook_from_sandy.Samples_to_sandy.Pert.ipynb @@ -0,0 +1,179 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sandy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "XS samples:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "samples = pd.DataFrame([[0.5, 1.5], [0.75, 1.25]] , index=[0, 1])\n", + "samples.columns = pd.MultiIndex.from_arrays([[125, 125], [2, 2], [1e-05, 19970500.0]], names=['MAT', 'MT', 'E'])\n", + "samples = sandy.Samples(samples)\n", + "samples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "samples.to_pert()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Single sample:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "samples.to_pert(smp=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "LPC samples:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "samples = pd.DataFrame([[0.5, 1.5], [0.75, 1.25]] , index=[0, 1])\n", + "samples.columns = pd.MultiIndex.from_arrays([[125, 125], [2, 2], [1.00000e-05, 1.00000e-05], [1.00000e-05, \t1.00000e-05], [1e-05, 19970500.0]], names=['MAT', 'MT', 'ELO', 'EHI', 'E'])\n", + "samples = sandy.Samples(samples)\n", + "samples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "samples.to_pert()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Single sample:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "samples.to_pert(smp=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Energy distribution samples:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "samples = pd.DataFrame([[0.5, 1.5], [0.75, 1.25]] , index=[0, 1])\n", + "samples.columns = pd.MultiIndex.from_arrays([[125, 125], [2, 2], [1, 1], [1e-05, 19970500.0]], names=['MAT', 'MT', 'L', 'E'])\n", + "samples = sandy.Samples(samples)\n", + "samples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "samples.to_pert()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Single sample:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "samples.to_pert(smp=0)\n" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "d167b81dab4cfdd7e83bd7f0413ce20e956b35802f4873808516fc813094dcfb" + }, + "kernelspec": { + "display_name": "Python 3.7.10 ('sandy-devel')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/notebook_reorder_of_sandy.Pert.ipynb b/notebooks/notebook_reorder_of_sandy.Pert.ipynb new file mode 100644 index 00000000..896a1d1e --- /dev/null +++ b/notebooks/notebook_reorder_of_sandy.Pert.ipynb @@ -0,0 +1,127 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sandy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Rearrange `sandy.Pert` columns levels using input order" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "col = pd.MultiIndex.from_arrays([[5, 2, 2, 3], [2631, 2631, 125, 125]], names=('MT', 'MAT'))\n", + "pert = pd.DataFrame([[1, 1.05, 0.95, 1.30], [1.05, 1, 1.15, 0.7]], \n", + " index=pd.IntervalIndex.from_breaks(pd.Index([1.94000e+08, 1.96000e+08+1]).insert(0, 0)),\n", + " columns=col)\n", + "pert = sandy.Pert(pert)\n", + "pert" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Reorder for custom perturbation of H:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xs = sandy.Xs.from_endf6(sandy.get_endf6_file(\"jeff_33\", \"xs\", 10010))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pert.reorder(xs.data.columns)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Reorder for custom perturbation of Fe:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xs = sandy.Xs.from_endf6(sandy.get_endf6_file(\"jeff_33\", \"xs\", 260560))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pert.reorder(xs.data.columns)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "d167b81dab4cfdd7e83bd7f0413ce20e956b35802f4873808516fc813094dcfb" + }, + "kernelspec": { + "display_name": "Python 3.7.10 ('sandy-devel')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/notebook_reshape_of_sandy.Pert.ipynb b/notebooks/notebook_reshape_of_sandy.Pert.ipynb new file mode 100644 index 00000000..d3dabd14 --- /dev/null +++ b/notebooks/notebook_reshape_of_sandy.Pert.ipynb @@ -0,0 +1,105 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sandy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns \n", + "import numpy as np\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Reshape of `sandy.Pert` object" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pert = pd.Series([1, 1.05], index=pd.IntervalIndex.from_breaks(pd.Index([10, 100]).insert(0, 0)))\n", + "pert = sandy.Pert(pert)\n", + "plot = pert.right.reset_index().rename(columns={\"index\": \"E\", 0:'Perturbation'})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(4, 4), dpi=100)\n", + "plot.plot(kind=\"scatter\", x=\"E\", y='Perturbation', ax=ax, grid=True, legend=None)\n", + "plt.xticks(np.arange(0, 130, 10))\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Reshape:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pert_reshape = pert.reshape(np.arange(0, 120)).right.reset_index().rename(columns={\"index\": \"E\", 0:'Perturbation'})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(4, 4), dpi=100)\n", + "pert_reshape.plot(kind=\"scatter\", x=\"E\", y='Perturbation', ax=ax, grid=True, legend=None)\n", + "plt.xticks(np.arange(0, 130, 10))\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python3 (sandy-devel)", + "language": "python", + "name": "sandy-devel" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 7b767ae59d994885ee320f61a30c456a5d364e7f Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Wed, 22 Jun 2022 13:32:48 +0200 Subject: [PATCH 20/21] custom perturbation in Edistr bug solve --- sandy/pfns.py | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/sandy/pfns.py b/sandy/pfns.py index 994cc411..f8e22366 100644 --- a/sandy/pfns.py +++ b/sandy/pfns.py @@ -445,18 +445,8 @@ def custom_perturbation(self, pert): Parameters ---------- - pert : `sandy.Pert` or `pd.DataFrame` - Tabulated perturbation. - mat : `int`, optional - MAT number. The default is None. - mt : `int` - MT number. The default is None. - k : `int` - subsection. The default is None. - ein_low : `float`, optional - lower energy boundary in eV. The default is None. - ein_high : `float`, optional - upper energy boundary in eV. The default is None. + pert : `sandy.Pert` or `pd.Series` + perturbation object. Returns ------- @@ -481,11 +471,11 @@ def custom_perturbation(self, pert): >>> pert_ = sandy.Pert(df) >>> orig.custom_perturbation(pert_) MAT MT K EIN EOUT VALUE - 0 9437 18 0 1.00000e+00 1.00000e-05 4.00000e-01 - 1 9437 18 0 1.00000e+00 2.00000e+07 6.00000e-01 - 2 9437 18 0 2.00000e+00 1.00000e-04 2.60000e-01 - 3 9437 18 0 2.00000e+00 1.00000e+00 7.00000e-01 - 4 9437 18 0 2.00000e+00 1.00000e+07 1.00000e-01 + 0 9437 18 0 1.00000e+00 1.00000e-05 4.00000e-08 + 1 9437 18 0 1.00000e+00 2.00000e+07 6.00000e-08 + 2 9437 18 0 2.00000e+00 1.00000e-04 3.75000e-07 + 3 9437 18 0 2.00000e+00 1.00000e+00 1.75000e-07 + 4 9437 18 0 2.00000e+00 1.00000e+07 2.50000e-08 """ pert_ = sandy.Pert(pert) if not isinstance(pert, sandy.Pert) else pert @@ -495,7 +485,7 @@ def custom_perturbation(self, pert): enew = enew[(enew <= energy_grid.max()) & (enew >= energy_grid.min())] # Reshape to new energy grid and columns estructure: - u_pert = pert.reshape(enew).right + u_pert = pert.reshape(enew, right_values=0).right # Apply the perturbation: def foo(df, pert): @@ -512,11 +502,11 @@ def foo(df, pert): pert_ = pert_.iloc[:, [0]]\ .reindex(index=df.loc[:, "EOUT"].values)\ .values.flatten() - df["VALUE"] = df['VALUE'].values * pert_ + df["VALUE"] = df['VALUE'].values + pert_ return df pert_edistr = self.data.groupby(['MAT', 'MT', 'K', 'EIN'])\ .apply(foo, u_pert) - return self.__class__(pert_edistr) + return self.__class__(pert_edistr).normalize() def _perturb(self, pert, method=2, normalize=True, **kwargs): """Perturb energy distributions given a set of perturbations. From fd09110cf4987348dc30c82f7726eb3139bfd543 Mon Sep 17 00:00:00 2001 From: Bengoechea Aitor Date: Wed, 22 Jun 2022 14:13:40 +0200 Subject: [PATCH 21/21] custom perturbation in Edistr bug solve --- sandy/pert.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sandy/pert.py b/sandy/pert.py index 312c1205..914f0249 100644 --- a/sandy/pert.py +++ b/sandy/pert.py @@ -215,7 +215,7 @@ def reorder(self, columns): col = columns.intersection(data_reorder.columns) return sandy.Pert(data_reorder[col]) - def reshape(self, eg, inplace=False): + def reshape(self, eg, inplace=False, right_values=1): """ Interpolate perturbation over new energy grid structure using `bfill` method. @@ -290,7 +290,7 @@ def reshape(self, eg, inplace=False): values, enew, left_values="first", - right_values=1, + right_values=right_values, ) data = pd.DataFrame(pertnew, index=enew, columns=df.columns) else: @@ -299,7 +299,7 @@ def reshape(self, eg, inplace=False): x.values, enew, left_values="first", - right_values=1, + right_values=right_values, )).set_index(enew).rename_axis(name) data = data.loc[(data.index >= eg_.min()) & (data.index <= eg_.max()), :]