102 lines
2.9 KiB
Python
102 lines
2.9 KiB
Python
import numpy as np
|
|
|
|
def detect_step_segments(signal,
|
|
diff_threshold=0.05,
|
|
min_length=20):
|
|
"""
|
|
Erkennt automatisch Step-Up/Step-Down-Segmente aus einem gemessenen Tiefpass-Signal.
|
|
Arbeitet über die erste Ableitung statt über absolute Schwellen.
|
|
|
|
signal : 1D array
|
|
diff_threshold : float
|
|
Minimale Änderung pro Sample, um einen Step zu erkennen.
|
|
Für deine Daten funktioniert ~0.05 gut.
|
|
min_length : int
|
|
Minimale Länge eines Segments (Samples).
|
|
|
|
Returns:
|
|
list of (start_idx, end_idx)
|
|
"""
|
|
|
|
s = np.asarray(signal)
|
|
diff = np.diff(s)
|
|
|
|
# Step-Up dort, wo diff stark positiv ist
|
|
ups = np.where(diff > diff_threshold)[0]
|
|
|
|
# Step-Down dort, wo diff stark negativ ist
|
|
downs = np.where(diff < -diff_threshold)[0]
|
|
|
|
segments = []
|
|
|
|
# Beide Listen sind ungeordnet, aber Step-Up sollte vor Step-Down kommen
|
|
up_idx = 0
|
|
down_idx = 0
|
|
|
|
while up_idx < len(ups) and down_idx < len(downs):
|
|
start = ups[up_idx]
|
|
|
|
# Nimm das nächste Down-Event, das nach dem Start liegt
|
|
while down_idx < len(downs) and downs[down_idx] <= start:
|
|
down_idx += 1
|
|
|
|
if down_idx >= len(downs):
|
|
break
|
|
|
|
end = downs[down_idx]
|
|
|
|
if end - start >= min_length:
|
|
segments.append((start, end))
|
|
|
|
up_idx += 1
|
|
down_idx += 1
|
|
|
|
return merge_close_segments(segments)
|
|
|
|
def merge_close_segments(segments, max_start_gap=10, max_end_gap=10):
|
|
"""
|
|
Fasst Segmente zusammen, deren Starts und Ends nahe beieinander liegen.
|
|
|
|
segments : list of (start, end)
|
|
max_start_gap : max Abstand zwischen Starts, um zusammenzufassen
|
|
max_end_gap : max Abstand zwischen Ends, um zusammenzufassen
|
|
|
|
Returns:
|
|
merged list of (start, end)
|
|
"""
|
|
if not segments:
|
|
return []
|
|
|
|
# Sortiere nach Start
|
|
segments = sorted(segments, key=lambda x: x[0])
|
|
|
|
merged = []
|
|
current_start, current_end = segments[0]
|
|
|
|
for start, end in segments[1:]:
|
|
# Prüfen, ob sowohl Start als auch End nah genug sind
|
|
if start - current_start <= max_start_gap and abs(end - current_end) <= max_end_gap:
|
|
# Segment gehört zum Cluster
|
|
current_end = max(current_end, end)
|
|
else:
|
|
merged.append((current_start, current_end))
|
|
current_start, current_end = start, end
|
|
|
|
merged.append((current_start, current_end))
|
|
return merged
|
|
|
|
|
|
def laenge_laengstes_array(arrays):
|
|
"""
|
|
Gibt die Länge des längsten Arrays in einem Array von Arrays zurück.
|
|
|
|
Parameters:
|
|
arrays (list of list or ndarray): Liste von Arrays
|
|
|
|
Returns:
|
|
int: Länge des längsten Arrays
|
|
"""
|
|
# Konvertiere in ein NumPy-Array, um die Länge der inneren Arrays zu messen
|
|
laengen = np.array([len(a) for a in arrays])
|
|
return np.max(laengen)
|