Source code for skneuromsi.core.ndresult.stats_acc

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This file is part of the
#   Scikit-NeuroMSI Project (https://github.com/renatoparedes/scikit-neuromsi).
# Copyright (c) 2021-2025, Renato Paredes; Cabral, Juan
# License: BSD 3-Clause
# Full Text:
#     https://github.com/renatoparedes/scikit-neuromsi/blob/main/LICENSE.txt

# =============================================================================
# DOCS
# =============================================================================

"""Stats helper for the Result object."""


# =============================================================================
# IMPORTS
# =============================================================================

import pandas as pd

from ..constants import DIMENSIONS
from ...utils import AccessorABC

# =============================================================================
# STATS ACCESSOR
# =============================================================================


[docs] class ResultStatsAccessor(AccessorABC): """Calculate basic statistics of the result. Kind of statistic to produce: - describe - count - mean - std - min - max - dimmin - dimmax - quantile Parameters ---------- result : NDResult The NDResult object for which to calculate statistics. """ _default_kind = "describe" def __init__(self, result): self._result = result def _to_xarray(self, modes, times, positions, coordinates): """Convert the NDResult to an xarray.DataArray with specified filters. Parameters ---------- modes : array-like or None The modes to include in the filtered xarray.DataArray. times : array-like or None The times to include in the filtered xarray.DataArray. positions : array-like or None The positions to include in the filtered xarray.DataArray. coordinates : array-like or None The coordinates to include in the filtered xarray.DataArray. Returns ------- xarray.DataArray The filtered xarray.DataArray. """ xa = self._result.to_xarray() flt = { dim_name: dim_flt for dim_name, dim_flt in zip( DIMENSIONS, (modes, times, positions, coordinates) ) if dim_flt is not None } return xa.sel(flt) if flt else xa
[docs] def count( self, *, modes=None, times=None, positions=None, coordinates=None ): """Count the number of elements in the NDResult. Parameters ---------- modes : array-like or None, optional The modes to include in the count. times : array-like or None, optional The times to include in the count. positions : array-like or None, optional The positions to include in the count. coordinates : array-like or None, optional The coordinates to include in the count. Returns ------- int The number of elements in the filtered NDResult. """ xa = self._to_xarray(modes, times, positions, coordinates) return int(xa.count().to_numpy())
[docs] def mean( self, *, modes=None, times=None, positions=None, coordinates=None ): """Calculate the mean value of the NDResult. Parameters ---------- modes : array-like or None, optional The modes to include in the mean calculation. times : array-like or None, optional The times to include in the mean calculation. positions : array-like or None, optional The positions to include in the mean calculation. coordinates : array-like or None, optional The coordinates to include in the mean calculation. Returns ------- float The mean value of the filtered NDResult. """ xa = self._to_xarray(modes, times, positions, coordinates) return float(xa.mean().to_numpy())
[docs] def std(self, *, modes=None, times=None, positions=None, coordinates=None): """Calculate the standard deviation of the NDResult. Parameters ---------- modes : array-like or None, optional The modes to include in the standard deviation calculation. times : array-like or None, optional The times to include in the standard deviation calculation. positions : array-like or None, optional The positions to include in the standard deviation calculation. coordinates : array-like or None, optional The coordinates to include in the standard deviation calculation. Returns ------- float The standard deviation of the filtered NDResult. """ xa = self._to_xarray(modes, times, positions, coordinates) return float(xa.std().to_numpy())
[docs] def min( # noqa self, *, modes=None, times=None, positions=None, coordinates=None ): """Calculate the minimum value of the NDResult. Parameters ---------- modes : array-like or None, optional The modes to include in the minimum value calculation. times : array-like or None, optional The times to include in the minimum value calculation. positions : array-like or None, optional The positions to include in the minimum value calculation. coordinates : array-like or None, optional The coordinates to include in the minimum value calculation. Returns ------- float The minimum value of the filtered NDResult. """ xa = self._to_xarray(modes, times, positions, coordinates) return float(xa.min().to_numpy())
[docs] def dimmin( self, *, modes=None, times=None, positions=None, coordinates=None ): """Calculate the minimum value and corresponding dimensions of the \ NDResult. Parameters ---------- modes : array-like or None, optional The modes to include in the minimum value calculation. times : array-like or None, optional The times to include in the minimum value calculation. positions : array-like or None, optional The positions to include in the minimum value calculation. coordinates : array-like or None, optional The coordinates to include in the minimum value calculation. Returns ------- pandas.Series A series containing the minimum value and corresponding dimensions of the filtered NDResult. """ xa = self._to_xarray(modes, times, positions, coordinates) data = {} for dim, min_idx_xa in xa.argmin(...).items(): arr = xa[dim].to_numpy() min_idx = min_idx_xa.to_numpy() data[dim] = arr[min_idx] data["values"] = xa.min(...).to_numpy() return pd.Series(data, name="min")
[docs] def max( # noqa self, *, modes=None, times=None, positions=None, coordinates=None ): # noqa """Calculate the maximum value of the NDResult. Parameters ---------- modes : array-like or None, optional The modes to include in the maximum value calculation. times : array-like or None, optional The times to include in the maximum value calculation. positions : array-like or None, optional The positions to include in the maximum value calculation. coordinates : array-like or None, optional The coordinates to include in the maximum value calculation. Returns ------- float The maximum value of the filtered NDResult. """ xa = self._to_xarray(modes, times, positions, coordinates) return float(xa.max().to_numpy())
[docs] def dimmax( self, *, modes=None, times=None, positions=None, coordinates=None ): """Calculate the maximum value and corresponding dimensions of \ the NDResult. Parameters ---------- modes : array-like or None, optional The modes to include in the maximum value calculation. times : array-like or None, optional The times to include in the maximum value calculation. positions : array-like or None, optional The positions to include in the maximum value calculation. coordinates : array-like or None, optional The coordinates to include in the maximum value calculation. Returns ------- pandas.Series A series containing the maximum value and corresponding dimensions of the filtered NDResult. """ xa = self._to_xarray(modes, times, positions, coordinates) data = {} for dim, max_idx_xa in xa.argmax(...).items(): arr = xa[dim].to_numpy() max_idx = max_idx_xa.to_numpy() data[dim] = arr[max_idx] data["values"] = xa.max(...).to_numpy() return pd.Series(data, name="max")
[docs] def quantile( self, q=0.25, *, modes=None, times=None, positions=None, coordinates=None, **kwargs, ): """Calculate the quantile value(s) of the NDResult. Parameters ---------- q : float or array-like, optional The quantile(s) to calculate. Default is 0.25. modes : array-like or None, optional The modes to include in the quantile calculation. times : array-like or None, optional The times to include in the quantile calculation. positions : array-like or None, optional The positions to include in the quantile calculation. coordinates : array-like or None, optional The coordinates to include in the quantile calculation. **kwargs Additional keyword arguments to pass to xarray.DataArray.quantile(). Returns ------- numpy.ndarray The calculated quantile value(s) of the filtered NDResult. """ xa = self._to_xarray(modes, times, positions, coordinates) return xa.quantile(q=q, **kwargs).to_numpy()
[docs] def describe(self, percentiles=None): """Generate descriptive statistics of the NDResult. Parameters ---------- percentiles : array-like or None, optional The percentiles to include in the descriptive statistics. Default is [0.25, 0.5, 0.75]. Returns ------- pandas.DataFrame A DataFrame containing descriptive statistics of the NDResult. """ percentiles = [0.25, 0.5, 0.75] if percentiles is None else percentiles xa = self._result.to_xarray() data = {} data["count"] = xa.count().to_numpy() data["mean"] = xa.mean().to_numpy() data["std"] = xa.std().to_numpy() data["min"] = xa.min().to_numpy() for perc, pvalue in zip( percentiles, xa.quantile(percentiles).to_numpy() ): pkey = f"{int(perc * 100)}%" data[pkey] = pvalue data["max"] = xa.max().to_numpy() return pd.Series(data, name="describe", dtype=float).to_frame()