Source code for nerea.calculated

from collections.abc import Iterable
from typing import Self
from dataclasses import dataclass

import serpentTools as sts
import pandas as pd

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

__all__ = ['_Calculated',
           'CalculatedSpectralIndex',
           'CalculatedTraverse']

@dataclass(slots=True)
class _Calculated:
    """
    ``nerea._Calculated``
    ====================
    Superclass for calculated results.
    """
    def calculate(self) -> None:
        """
        ``nerea._Calculated.calculate()``
        ---------------------------------
        Placeholder for inheriting classes.
        """
        return None

[docs] @dataclass(slots=True) class CalculatedSpectralIndex(_Calculated): """ ``nerea.CalculatedSpectralIndex`` ================================= Spectral Index calculated in any simulation. Can be created from Serpent outputs. Can be created from ratio of Serpent detectors or from a direct tally of the ratio. Attributes ---------- **data**: ``pd.DataFrame`` the calculated spectral index value and uncertainty. **model_id**: ``str`` metadata for model identifier. **deposit_ids**: ``list[str]`` two-element list with the deposits considered in the spectral index. First element for numerator, second for denominator. """ data: pd.DataFrame model_id: str deposit_ids: list[str] # 0: num, 1: den
[docs] @classmethod def from_sts(cls, file: str, detector_name: str, **kwargs) -> Self: """ `nerea.CalculatedSpectralIndex.from_sts()` ------------------------------------------ Creates an instance using data extracted from a Serpent det.m file for a specific detector. Parameters ---------- **file** : ``str`` The file path from which data will be read. **detector_name** : ``str`` The name of the detector from which data will be extracted. Returns ------- ``nerea.CalculatedSpectralIndex`` An instance of the `nerea.CalculatedSpectralIndex` class created from the specified file.""" v, u = sts.read(file).detectors[detector_name].bins[0][-2:] n, d = kwargs['deposit_ids'][0], kwargs['deposit_ids'][1] mass_norm = ATOMIC_MASS.loc[d]['value'] / ATOMIC_MASS.loc[n]['value'] # Serpent detector uncertainty is relative kwargs['data'] = _make_df(v * mass_norm, u * v * mass_norm ).assign(VAR_PORT_C_n=None, VAR_PORT_C_d=None) return cls(**kwargs)
[docs] @classmethod def from_sts_detectors(cls, file: str, detector_names: dict[str, str], normalize=False, xs_kwargs: dict={}, **kwargs) -> Self: """ `nerea.CalculatedSpectralIndex.from_sts_detectors()` ---------------------------------------------------- Creates an instance using data extracted from a Serpent det.m file for multiple detectors. Parameters ---------- **file** : ``str`` The file path from which data will be read. **detector_names** : ``dict[str, str]`` Keys can be ``'numerator'`` or ``'denominator'``, while values are the names of the detectors from which data will be extracted. **xs_kwargs** : ``dict`` Additional arguments for ``nerea.Xs`` 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. *kwargs Additional arguments for instance creation - **model_id** (``str``), model identity - **deposit_ids** (``list[str]``), nuclide identifiers Returns ------- `nerea.CalculatedSpectralIndex` An instance of the `CalculatedSpectralIndex` class created from the specified file.""" n_, d_ = kwargs['deposit_ids'][0], kwargs['deposit_ids'][1] n = Xs.from_file(file, {n_: detector_names['numerator']}, **xs_kwargs) d = Xs.from_file(file, {d_: detector_names['denominator']}, **xs_kwargs) if normalize: n, d = n.normalized.data, d.normalized.data else: n, d = n.data, d.data n.index = ['value'] d.index = ['value'] S1 = 1 / d['value'].value S2 = n['value'].value / d['value'].value **2 kwargs['data'] = _make_df(*ratio_v_u(n, d)).assign( VAR_PORT_C_n=(S1 * n['uncertainty'].value) **2, VAR_PORT_C_d=(S2 * d['uncertainty'].value) **2) return cls(**kwargs)
[docs] def calculate(self): """ `nerea.CalculatedSpectralIndex.calculate()` ------------------------------------------- Computes the C value. Alias for self.data. Returns ------- ``pd.DataFrame`` data frame containing C ``'value'`` and ``'uncertainty'`` columns. Examples -------- >>> c_instance = CalculatedSpectralIndex(data=pd.DataFrame({'value': [0.5], 'uncertainty': [0.05]}), model_id='Model1', deposit_ids='Dep1') >>> c_instance.compute() value uncertainty 0 0.5 0.05 """ return self.data
[docs] @dataclass(slots=True) class CalculatedTraverse(_Calculated): """ ``nerea.CalculatedTraverse`` ============================ Traverse calculated in any simulation. Can be created from Serpent outputs. Attributes ---------- **data**: ``pd.DataFrame`` the calculated traverse values and uncertainties. **model_id*: ``str`` metadata for model identifier. **deposit_ids**: ``str`` the deposits of the tally considered.""" data: pd.DataFrame model_id: str deposit_id: str
[docs] @classmethod def from_sts(cls, file: str, detector_names: list[str], **kwargs) -> Self: """ `nerea.CalculatedTraverse.from_sts()` ------------------------------------- Creates an instance using data extracted from a Serpent det.m file for multiple detectors. Parameters ---------- **file**: ``str`` The file path from which data will be read. **detector_names**: ``Iterable[str]`` The names of the detectors from which data will be extracted. **normalization**: ``str``, optional The detector name to normalize the traveres to. Defaults to None, normalizing to the one with the highest counts. Returns ------- ``nerea.CalculatedTraverse`` An instance of the `CalculatedTraverse` class created from the specified file.""" out = [] for d in detector_names: v, u = sts.read(file).detectors[d].bins[0][-2:] out.append(_make_df(v, u * v).assign(traverse=d)) out = pd.concat(out) return cls(data=out, **kwargs)
[docs] def calculate(self, normalization: str=None): """ `nerea.CalculatedTraverse.calculate()` -------------------------------------- Computes the C value. Normalized self.data. Parameters ---------- **normalization**: ``str``, optional The detector name to normalize the traveres to. Defaults to ``None``, normalizing to the one with the highest counts. Returns ------- ``pd.DataFrame`` data frame containing C `'value'` and `'uncertainty'` columns.""" out = [] max_d = self.data.query("value == @self.data.value.max()").traverse.iloc[0] norm_d = max_d if normalization is None else normalization den = self.data.query('traverse == @norm_d') den = _make_df(den.value.iloc[0], den.uncertainty.iloc[0]) num = _make_df(self.data.value, self.data.uncertainty) out = _make_df(*ratio_v_u(num, den)).assign(traverse=self.data.traverse.values) return out.reset_index(drop=True)