File: average_runs.py

package info (click to toggle)
python-dynasor 2.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 22,008 kB
  • sloc: python: 5,263; sh: 20; makefile: 3
file content (61 lines) | stat: -rw-r--r-- 2,216 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import numpy as np
from dynasor.sample import Sample
from typing import List
from copy import deepcopy


def get_sample_averaged_over_independent_runs(
        samples: List[Sample], live_dangerously=False) -> Sample:
    """
    Compute an averaged sample from multiple samples obtained from identical independent runs.

    Note, all the meta_data and dimensions in all samples must be the same,
    else ValueError is raised (unless ``live_dangerously`` is set to True).

    Parameters
    ----------
    samples
        list of all sample objects to be averaged over
    live_dangerously
        setting True allows for averaging over samples which meta-data information is not identical.
    """

    # get meta data and dimensions from first sample
    sample_ref = samples[0]
    data_dict = dict()
    meta_data = deepcopy(sample_ref.meta_data)

    # test that all samples have identical dimensions
    for sample in samples:
        assert sorted(sample.dimensions) == sorted(sample_ref.dimensions)
        for dim in sample_ref.dimensions:
            assert np.allclose(sample[dim], sample_ref[dim])

    for dim in sample_ref.dimensions:
        data_dict[dim] = sample_ref[dim]

    # test that all samples have identical meta_data
    if not live_dangerously:
        for sample in samples:
            assert len(sample.meta_data) == len(meta_data)

            for key, val in meta_data.items():
                if isinstance(val, dict):
                    for k, v in val.items():
                        assert sample_ref.meta_data[key][k] == sample.meta_data[key][k]
                elif isinstance(val, np.ndarray):
                    assert np.allclose(sample.meta_data[key], val)
                elif isinstance(val, float):
                    assert np.isclose(sample.meta_data[key], val)
                else:
                    assert sample.meta_data[key] == val

    # average all correlation functions
    for key in sample.available_correlation_functions:
        data = []
        for sample in samples:
            data.append(sample[key])
        data_average = np.nanmean(data, axis=0)
        data_dict[key] = data_average

    return sample.__class__(data_dict, **meta_data)