timeseries.py 3.87 KB
Newer Older
1
import numpy as np
Markus Mirz's avatar
Markus Mirz committed
2
import cmath
3
4

class TimeSeries:
5
6
7
    """Stores data from different simulation sources.
    A TimeSeries object always consists of timestamps and datapoints.
    """
8
9
10
11
    def __init__(self, name, time, values, label=""):
        self.time = np.array(time)
        self.values = np.array(values)
        self.name = name
12
13
14
15
16
17
        self.label = name

    @staticmethod
    def diff(name, ts1, ts2):
        """Returns difference between values of two Timeseries objects.
        """
18
19
20
21
22
23
24
        if ts1.time==ts2.time:
            ts_diff = TimeSeries(name, ts1.time, (ts1.values - ts2.values))
        else:  # different timestamps, common time vector and interpolation required before substraction
            time = sorted(set(list(ts1.time) + list(ts2.time)))
            interp_vals_ts1 = np.interp(time, ts1.time, ts1.values)
            interp_vals_ts2 = np.interp(time, ts2.time, ts2.values)
            ts_diff = TimeSeries(name, time, (interp_vals_ts2 - interp_vals_ts1))
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
        return ts_diff


    def scale_ts(self, name, factor):
        """Returns scaled timeseries.
        Assumes the same time steps for both timeseries.
        """
        ts_scaled = TimeSeries(name, self.time, self.values * factor)
        return ts_scaled

    @staticmethod
    def complex_abs_dep(name, ts_real, ts_imag):
        """ Calculate absolute value of complex variable.
        Assumes the same time steps for both timeseries.
        """
        ts_abs = TimeSeries(name, ts_real.time, np.sqrt(ts_real.values ** 2 + ts_imag.values ** 2))
        return ts_abs

    @staticmethod
    def complex_abs(name, ts_real, ts_imag):
        """ Calculate absolute value of complex variable.
        Assumes the same time steps for both timeseries.
        """
        ts_complex = np.vectorize(complex)(ts_real.values, ts_imag.values)
        ts_abs = TimeSeries(name, ts_real.time, ts_complex.abs())
        return ts_abs

    def abs(self, name):
Markus Mirz's avatar
Markus Mirz committed
53
        """ Calculate absolute value of complex time series.
54
        """
Markus Mirz's avatar
Markus Mirz committed
55
56
57
58
        abs_values = []
        for value in self.values:
            abs_values.append(np.abs(value))
        ts_abs = TimeSeries(name, self.time, abs_values)
59
60
        return ts_abs

Markus Mirz's avatar
Markus Mirz committed
61
62
    def phase(self, name):
        """ Calculate absolute value of complex time series.
63
        """
Markus Mirz's avatar
Markus Mirz committed
64
65
66
67
68
69
        phase_values = []
        for value in self.values:
            phase_values.append(np.angle(value, deg=True))
        ts_abs = TimeSeries(name, self.time, phase_values)
        ts_phase = TimeSeries(name, self.time, phase_values)
        return ts_phase
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

    @staticmethod
    def dyn_phasor_shift_to_emt(name, real, imag, freq):
        """ Shift dynamic phasor values to EMT by frequency freq.
            Assumes the same time steps for both timeseries.
        """
        ts_shift = TimeSeries(name, real.time, real.values*np.cos(2*np.pi*freq*real.time) - imag.values*np.sin(2*np.pi*freq*real.time))
        return ts_shift

    @staticmethod
    def check_node_number_comp(ts_comp, node):
        """
        Check if node number is available in complex time series.
        :param ts_comp: complex time series
        :param node: node number to be checked
        :return: true if node number is available, false if out of range
        """
        ts_comp_length = len(ts_comp)
        im_offset = int(ts_comp_length / 2)
        if im_offset <= node or node < 0:
            print('Complex node not available')
            return false
        else:
            return true

    @staticmethod
    def check_node_number(ts, node):
        """
        Check if node number is available in time series.
        :param ts: time series
        :param node: node number to be checked
        :return: true if node number is available, false if out of range
        """
        ts_length = len(ts)
        if ts_length <= node or node < 0:
            print('Node not available')
            return false
        else:
            return true