diff --git a/src/elli/result.py b/src/elli/result.py index 62880a01..e35ef015 100644 --- a/src/elli/result.py +++ b/src/elli/result.py @@ -19,7 +19,8 @@ To make handling multiple experiments easier, they can be grouped into a list and provided to a ResultList object. It provides the same methods for data output as the single Result. -The Output is returned as array over the list of results. +The Output is returned as array over the list of results. If needed, these arrays can be +averaged and used like a Result object for fitting. """ from typing import List @@ -458,6 +459,7 @@ def __init__(self, results: List[Result] = None) -> None: Args: results (List[Result], optional): List of results to store. Defaults to None. + mean (bool, optional): Returns the average of all results. Defaults to False. """ if results is None: self.results = [] @@ -493,9 +495,46 @@ def __getattr__(self, name: str) -> npt.NDArray: 'psi', 'delta', 'rho': Reduced ellipsometry parameters, the whole matrices are returned by 'psi_matrix'. + 'mean.name' : Returns averaged values for the requested variable, + e.g. 'mean.psi'. Returns: npt.NDArray: Array of data. """ + if name == "mean": + return AveragedResultList(self.results) + return np.squeeze(np.array([getattr(result, name) for result in self.results])) + + +class AveragedResultList(ResultList): + """ResultList with averaging over all results. + Can be used as drop-in replacement for Result objects, if for example + thickness inhomogeneities need to be simulated. + """ + + def __getattr__(self, name: str) -> npt.NDArray: + """Returns the data for the requested variable 'name' of all results. + + Args: + name (str): Variable name to return. + Examples for 'name'... + 'r_sp' : Amplitude reflection coefficient from 's' to 'p' polarization. + 'r_LR' : Reflection from circular right to circular left polarization. + 'T_pp' : Power transmission coefficient from 'p' to 'p' polarization. + 'Ψ_ps', 'Δ_pp' : Ellipsometry parameters. + 'psi', 'delta', 'rho': + Reduced ellipsometry parameters, + the whole matrices are returned by 'psi_matrix'. + + Returns: + npt.NDArray: Array of data. + """ + + if name == "mean": + raise ValueError( + "The ResultList is already averaged and can't be averaged again." + ) + + return np.mean(super().__getattr__(name), axis=0) diff --git a/tests/test_result.py b/tests/test_result.py index b1a4d1d0..1ecdb8a7 100644 --- a/tests/test_result.py +++ b/tests/test_result.py @@ -1,8 +1,8 @@ """Tests for the result class""" +import elli import numpy as np from pytest import fixture, raises -import elli @fixture @@ -40,3 +40,13 @@ def test_delta_range_error_on_invalid_range(result): with raises(ValueError): result.as_delta_range(20, 180) + + +def test_resultlist_shape(result): + result_list = elli.ResultList([result, result, result]) + + assert len(result_list) == 3 + assert np.shape(result_list.delta) == (3, 50) + + assert np.shape(result_list.mean.delta) == (50,) + assert np.allclose(result_list.mean.delta, result.delta)