Commit 3b7427a1 authored by Markus Mirz's avatar Markus Mirz

updated timeseries functions

parent 3c55c530
...@@ -3,7 +3,7 @@ import cmath ...@@ -3,7 +3,7 @@ import cmath
class TimeSeries: class TimeSeries:
"""Stores data from different simulation sources. """Stores data from different simulation sources.
A TimeSeries object always consists of timestamps and datapoints. A TimeSeries object always consists of timestamps and datapoints.
""" """
def __init__(self, name, time, values, label=""): def __init__(self, name, time, values, label=""):
self.time = np.array(time) self.time = np.array(time)
...@@ -11,43 +11,108 @@ class TimeSeries: ...@@ -11,43 +11,108 @@ class TimeSeries:
self.name = name self.name = name
self.label = name self.label = name
def scale(self, name, factor): def scale(self, factor):
"""Returns scaled timeseries. """Returns scaled timeseries.
Assumes the same time steps for both timeseries.
""" """
ts_scaled = TimeSeries(name, self.time, self.values * factor) ts_scaled = TimeSeries(self.name+'_scl', self.time, self.values * factor)
return ts_scaled return ts_scaled
def abs(self, name): def abs(self):
""" Calculate absolute value of complex time series. """ Calculate absolute value of complex time series.
""" """
abs_values = [] abs_values = []
for value in self.values: for value in self.values:
abs_values.append(np.abs(value)) abs_values.append(np.abs(value))
ts_abs = TimeSeries(name, self.time, abs_values) ts_abs = TimeSeries(self.name+'_abs', self.time, abs_values)
return ts_abs return ts_abs
def phase(self, name): def phase(self):
""" Calculate absolute value of complex time series. """ Calculate phase of complex time series.
""" """
phase_values = [] phase_values = []
for value in self.values: for value in self.values:
phase_values.append(np.angle(value, deg=True)) phase_values.append(np.angle(value, deg=True))
ts_abs = TimeSeries(name, self.time, phase_values) ts_phase = TimeSeries(self.name+'_phase', self.time, phase_values)
ts_phase = TimeSeries(name, self.time, phase_values)
return ts_phase return ts_phase
def phasor(self, name): def phasor(self):
"""Calculate phasor of complex time series and return dict with abs and phase. """Calculate phasors of complex time series
and return dict with absolute value and phase.
""" """
ts_abs = self.abs(self.name + '_abs') ts_abs = self.abs()
ts_phase = self.phase(self.name + '_phase') ts_phase = self.phase()
ts_phasor = {} ts_phasor = {}
ts_phasor['abs'] = ts_abs ts_phasor['abs'] = ts_abs
ts_phasor['phase'] = ts_phase ts_phasor['phase'] = ts_phase
return ts_phasor return ts_phasor
def frequency_shift(self, freq):
""" Shift dynamic phasor values to EMT by frequency freq.
Only the real part is considered.
Assumes the same time steps for both timeseries.
:param freq: shift frequency
:return: new timeseries with shifted time domain values
"""
ts_shift = TimeSeries(self.name+'_shift', self.time,
self.values.real*np.cos(2*np.pi * freq * self.time)
- self.values.imag*np.sin(2*np.pi * freq * self.time))
return ts_shift
def calc_freq_spectrum(self):
""" Calculates frequency spectrum of the time series using FFT
"""
Ts = self.time[1]-self.time[0]
fft_values = np.fft.fft(self.values)
freqs_num = int(len(fft_values)/2)
fft_freqs = np.fft.fftfreq(len(fft_values), d=Ts)
return fft_freqs[:freqs_num], np.abs(fft_values[:freqs_num])/freqs_num
def interpolate_cmpl(self, timestep):
""" Not tested yet!
Interpolates complex timeseries with timestep
:param timestep:
:return:
"""
interpl_time = np.arange(self.time[0], self.time[-1], timestep)
realValues = interp1d(interpl_time, self.values.real)
imagValues = interp1d(interpl_time, self.values.imag)
ts_return = TimeSeries(self.name+'_intpl', time, np.vectorize(complex)(realValues, imagValues))
return timeseries
@staticmethod
def multi_frequency_shift(timeseries_list, freqs_list):
""" Calculate shifted frequency results of all time series
in list by using the frequency with the same index in the frequency list.
:param timeseries_list: timeseries list retrieved from dpsim results
:param freq: frequency by which the timeseries should be shifted
:return: dict of shifted time series
"""
result_list = {}
for ts, freq in zip(timeseries_list, freqs_list):
ts_shift = ts.frequency_shift(freq)
result_list[ts.name] = ts_shift
return result_list
@staticmethod
def create_emt_from_dp(timeseries_list, freqs_list):
"""Calculate shifted frequency results of all time series
:param timeseries_list: timeseries list retrieved from dpsim results
:param freq: frequency by which the timeseries should be shifted
:return: list of shifted time series
"""
result = np.zeros_like(timeseries_list[0].values)
for ts, freq in zip(timeseries_list, freqs_list):
ts_shift = ts.frequency_shift(freq)
result = result + ts_shift.values
ts_result = TimeSeries('emt_signal', timeseries_list[0].time, result.real)
return ts_result
@staticmethod @staticmethod
def frequency_shift_list(timeseries_list, freq): def frequency_shift_list(timeseries_list, freq):
"""Calculate shifted frequency results of all time series """Calculate shifted frequency results of all time series
...@@ -57,7 +122,7 @@ class TimeSeries: ...@@ -57,7 +122,7 @@ class TimeSeries:
""" """
result_list = {} result_list = {}
for name, ts in timeseries_list.items(): for name, ts in timeseries_list.items():
ts_emt = ts.frequency_shift(ts.name, freq) ts_emt = ts.frequency_shift(freq)
result_list[ts.name] = ts_emt result_list[ts.name] = ts_emt
return result_list return result_list
...@@ -93,78 +158,11 @@ class TimeSeries: ...@@ -93,78 +158,11 @@ class TimeSeries:
interp_vals_ts2 = np.interp(time, ts2.time, ts2.values) interp_vals_ts2 = np.interp(time, ts2.time, ts2.values)
ts_diff = TimeSeries(name, time, (interp_vals_ts2 - interp_vals_ts1)) ts_diff = TimeSeries(name, time, (interp_vals_ts2 - interp_vals_ts1))
return ts_diff return ts_diff
def frequency_shift(self, name, freq):
""" Shift dynamic phasor values to EMT by frequency freq.
Assumes the same time steps for both timeseries.
:param name: name of returned time series
:param freq: shift frequency
:return: new timeseries with shifted time domain values
"""
ts_shift = TimeSeries(name, self.time, self.values.real*np.cos(2*np.pi*freq*self.time)
- self.values.imag*np.sin(2*np.pi*freq*self.time))
return ts_shift
def calc_freq_spectrum(self):
""" Calculates frequency spectrum of the time series using FFT
:param name: name of returned time series
:param freq: shift frequency
:return: new timeseries with shifted time domain values
"""
Ts = self.time[1]-self.time[0]
fft_values = np.fft.fft(self.values)
freqs_num = int(len(fft_values)/2)
fft_freqs = np.fft.fftfreq(len(fft_values),d=Ts)
return fft_freqs[:freqs_num], np.abs(fft_values[:freqs_num])/freqs_num
def interpolate_cmpl(self, name, timestep):
""" Not tested yet!
Interpolates complex timeseries with timestep
:param name:
:param timestep:
:return:
"""
interpl_time = np.arange(self.time[0], self.time[-1], timestep)
realValues = interp1d(interpl_time, self.values.real)
imagValues = interp1d(interpl_time, self.values.imag)
ts_return = TimeSeries(name, time, np.vectorize(complex)(realValues, imagValues))
return timeseries
@staticmethod
def check_node_number_comp(ts_list_comp, node):
"""
Check if node number is available in complex time series.
:param ts_comp: complex time series list
: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_list, node):
"""
Check if node number is available in time series.
:param ts: time series list
: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
@staticmethod @staticmethod
def complex_abs(name, ts_real, ts_imag): def complex_abs(name, ts_real, ts_imag):
""" Calculate absolute value of complex variable. """ Calculate absolute value of complex variable.
Assumes the same time steps for both timeseries. Assumes the same time steps for both timeseries.
""" """
ts_complex = np.vectorize(complex)(ts_real.values, ts_imag.values) ts_complex = np.vectorize(complex)(ts_real.values, ts_imag.values)
ts_abs = TimeSeries(name, ts_real.time, np.absolute(ts_complex)) ts_abs = TimeSeries(name, ts_real.time, np.absolute(ts_complex))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment