Source code for nerea.classes

from dataclasses import dataclass

from typing import Self

import pandas as pd
import serpentTools as sts

from .utils import _make_df, ratio_v_u
from .constants import ATOMIC_MASS

__all__ = ["EffectiveDelayedParams", "Xs"]


[docs] @dataclass(slots=True) class EffectiveDelayedParams: """ ``nerea.EffectiveDelayedParams`` ================================ Class storing and pre-processing effective delayed parameters. Attributes ---------- **lambda_i**: ``pd.DataFrame`` precursor-group-wise effective decay constant. **beta_i**: ``pd.DataFrame`` precursor-group-wise effective decay fraction. """ lambda_i: pd.DataFrame beta_i: pd.DataFrame
[docs] @classmethod def from_sts(cls, file: str) -> Self: """ `nerea.EffectiveDelayedParams.from_sts()` ----------------------------------------- Creates an instance using data extracted from a Serpent res.m. Parameters ---------- **file** : ``str`` The file path from which data will be read. Returns ------- `nerea.EffectiveDelayedParams` An instance of the `nerea.EffectiveDelayedParams` class created from the specified file.""" bi = sts.read(file).resdata['adjIfpImpBetaEff'].reshape(-1, 2)[1:, :] li = sts.read(file).resdata['adjIfpImpLambda'].reshape(-1, 2)[1:, :] bi = _make_df(bi[:, 0], bi[:, 1] * bi[:, 0]) li = _make_df(li[:, 0], li[:, 1] * li[:, 0]) return cls(li, bi)
[docs] @dataclass(slots=True) class Xs: """ ``nerea.Xs`` ============ Class storing one group cross section data. Attributes ---------- **data**: ``pd.DataFrame`` data frame with cross section data (index is nuclide identifier). **mass_normalized**: ``bool``, optional whether the cross section is mass-normalized. Default is `False`. **volume_normalized**: ``bool``, optional whether the cross section is volume-normalized. Default is `False`. **volume**: ``float``, optional volume for volume normalization. Default is `1.0`.""" data : pd.DataFrame mass_normalized : bool=False volume_normalized : bool=False volume: float = 1.
[docs] def copy(self) -> Self: """ `nerea.Xs.copy()` ----------------- Copies the `nerea.Xs` isntance. Returns ------- `nerea.Xs`""" return self.__class__(self.data.copy(), self.mass_normalized, self.volume_normalized, self.volume)
[docs] @classmethod def from_file(cls, file: str, read: dict[str, str], *args, **kwargs) -> Self: """ `nerea.Xs.from_file()` ---------------------- Create Xs object from serpent detector output file. Parameters ---------- **file**: ``str`` Serpent output file path from which data will be read. **read**: ``dict[str, str]`` The nuclide (`key`) associated with each detector (`value`). **args, **kwargs Additional arguments for instance creation - **mass_normalized** (``bool``, optional), whether the cross section is mass-normalized. - **volume_normalized** (``bool``, optional), whether the cross section is volume-normalized. - **volume** (``float``, optional), volume for volume normalization. Returns ------- `nerea.Xs`""" data = pd.DataFrame({n: sts.read(file).detectors[d].bins[0][-2:] for n, d in read.items()}).T data.columns = ['value', 'uncertainty'] data.index.name = 'nuclide' # uncertainy is absolute data.uncertainty = data.uncertainty * data.value return cls(data, *args, **kwargs)
@property def normalized(self) -> Self: """ `nerea.Xs.normalized()` ----------------------- Normalizes the cross section data per unit volume and mass. Returns ------- `nerea.Xs`""" if not self.volume_normalized: self.data /= self.volume if not self.mass_normalized: idx = self.data.index.copy() self.data = _make_df(*ratio_v_u(self.data, ATOMIC_MASS), relative=False)[['value', 'uncertainty'] ].dropna() self.data.index = idx self.volume_normalized = True self.mass_normalized = True return self