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