Skip to content

Commit

Permalink
Implement averaging of ResultLists (#162)
Browse files Browse the repository at this point in the history
* Implement averaging of ResultLists
* Move averaging into a new class
  • Loading branch information
MarJMue committed Feb 20, 2024
1 parent 9567086 commit 903150e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
41 changes: 40 additions & 1 deletion src/elli/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 = []
Expand Down Expand Up @@ -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)
12 changes: 11 additions & 1 deletion tests/test_result.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Tests for the result class"""

import elli
import numpy as np
from pytest import fixture, raises
import elli


@fixture
Expand Down Expand Up @@ -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)

0 comments on commit 903150e

Please sign in to comment.