Implementierung eines Low pass Filters
Um meine Frage zu konkretisieren, zeige ich mal meine Minimafunktion auf.
Das ist der Code um die Minimas zu berechnen. Es findet zwar viele lokale Minimas, komischerweise ist sind 2 positive Peaks ebenfalls ein Minima, aber es sind viel zu viele.
Meine Bewegung sind die Bizepcurls, eine Wiederholung hat die Form von einem "M". Es erkennt pro Wiederholung mindestens 3 negative Peaks, was einer mindestens zu viel ist.
Wie man hier an dem Bild erkennt
https://ibb.co/7Krw6Vg
Es hängt denke ich mit der erwarteten Distanz der Peaks zusammen bzw, das die Distanz vergrößert werden muss genau die Funktion wie bei der Peak detection mit dem Parameter Distance.
Mit diesem Abschnitt wollte ich etwas ähnliches bewirken, jedoch wenn ich den Parameter erhöhe kommt einer Fehlermeldung.
https://ibb.co/51yzMMz
Das Problem war bei der Peak Detection nicht, wieso kommt es jetzt zu diesem Konflikt?
Ich habe dann versucht die gefilterten Daten auf die selbe Anzahl von shapes zu bringen wie die Daten mit denwas aber kläglich gescheitert ist.
Gibt es eine andere Lösung als die Shapes auf die selbe Anzahl zu bringen oder gibt es eine besser Alternative, als die Minima Funktion in meinem Code?
Code: Alles auswählen
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('Agg')
from scipy.signal import argrelextrema
def butter_lowpass(cutoff, fs, order=5):
nyq = fs/2
normal_cutoff = cutoff / nyq
b, a = butter(order, normal_cutoff, btype='low', analog=False)
return b, a
def butter_lowpass_filter(data, cutoff, fs, order=5):
b, a = butter_lowpass(cutoff, fs, order=order)
y = lfilter(b, a, data)
return y
data=pd.read_csv('hussein2_acc.csv',sep=";", decimal=",",encoding='latin-1')
sensor_data=data[['Euklidische Norm']]
sensor_data = np.array(sensor_data).ravel()
sensor_data = sensor_data - np.average(sensor_data) # eliminate DC
# Filter requirements.
order = 2
fs = 100 # sample rate, Hz
cutoff = 1
y = butter_lowpass_filter(sensor_data, cutoff, fs, order)
array_data = np.arange(start = 0, stop = 4098, step = 1, dtype='int')
minima_ind = argrelextrema(y, np.less)
minima_ind = minima_ind[0]
x_minima = minima_ind
y_minima = y[minima_ind]
print(y_minima,x_minima)
# plot the peaks
(fig, ax) = plt.subplots()
ax.plot(array_data, y)
ax.scatter(x_minima, y_minima,color = 'r', s = 25, label = 'Minima')
ax.legend
Meine Bewegung sind die Bizepcurls, eine Wiederholung hat die Form von einem "M". Es erkennt pro Wiederholung mindestens 3 negative Peaks, was einer mindestens zu viel ist.
Wie man hier an dem Bild erkennt
https://ibb.co/7Krw6Vg
Es hängt denke ich mit der erwarteten Distanz der Peaks zusammen bzw, das die Distanz vergrößert werden muss genau die Funktion wie bei der Peak detection mit dem Parameter Distance.
Code: Alles auswählen
array_data = np.arange(start = 0, stop = 4098, step = 1, dtype='int')
Code: Alles auswählen
Steps
https://ibb.co/51yzMMz
Das Problem war bei der Peak Detection nicht, wieso kommt es jetzt zu diesem Konflikt?
Ich habe dann versucht die gefilterten Daten auf die selbe Anzahl von shapes zu bringen wie die Daten mit den
Code: Alles auswählen
steps
Gibt es eine andere Lösung als die Shapes auf die selbe Anzahl zu bringen oder gibt es eine besser Alternative, als die Minima Funktion in meinem Code?
Wieso benutzt du nicht die peak detection? Die hat doch halbwegs gute Ergebnisse geliefert, und sollte auch bei negativen peaks funktionieren. Sollte sie das aus irgendwelchen Gründen nicht tun, ist es ja trivial, das zu reparieren - einfach * -1 nehmen.
Die Daten müssen ja *-1 genommen werden oder?
Also Sprich
Dann sieht es so aus
https://ibb.co/9Y43hQ7
Ich denke das sieht sehr gut spiegelverkehrt wie die Peakdetection aus. Vielen Dank für den Hinweis, ich habe viel zu kompliziert gedacht.
Jetzt brauche ich die Werte zwischen den Peaks jeweils für die Segmentierung oder?
Also Sprich
Code: Alles auswählen
peaks = find_peaks(y*-1, height = 0.00, threshold = None, distance=170) # *-1
eight = peaks[1]['peak_heights'] #list of heights of peaks
peak_pos = peaks[0]
print(peaks)
# plot the peaks
fig = plt.figure()
ax = fig.subplots()
ax.plot(y*-1) # *-1
ax.scatter(peak_pos, height,color = 'r', s = 25, label = 'Maxima')
ax.legend
plt.show()
https://ibb.co/9Y43hQ7
Ich denke das sieht sehr gut spiegelverkehrt wie die Peakdetection aus. Vielen Dank für den Hinweis, ich habe viel zu kompliziert gedacht.
Jetzt brauche ich die Werte zwischen den Peaks jeweils für die Segmentierung oder?
Ich habe soweit die negativen Peaks. Ich muss jetzt die Daten vom Low pass Filter in den jeweiligen Punkte schneiden wo die lokalen Peaks angesetzt sind, also heißt die Daten des Lowpassfilters in subarrays schneiden. Es soll dann geschnitten werden wenn es einen Peak findet richtig?
Also das sind meine lokalen Peaks. Die Arrays müssen so geschnitten werden das sie von dem Peak 0.061100887 bis 0.10401105 alle Daten in einem Array sind und von dem Peak 0.10401105 bis 0.07522478 alle Daten in ein Array etc.
Ich habe mich da ran probiert, aber irgendwie nicht erfolgreich, das Problem hierbei ist, das die Zahlen nach ihrem Wert in die Subarrays einteilt, glaube ich. Nicht, wenn es ein Peak findet.
Hängt es vielleicht auch mit der Struktur von meiner Variable y ab, ist das ein Integer Array?
Code: Alles auswählen
[0.06110087, 0.10401105, 0.07522478, 0.09554681, 0.08982648,
0.09118464, 0.09309628, 0.10440643, 0.08335122, 0.14826715,
0.09760258, 0.13332452, 0.11009777, 0.1806636 ]
Code: Alles auswählen
y = butter_lowpass_filter(sensor_data, cutoff, fs, order)
peaks = find_peaks(y*-1, height = 0.00, threshold = None, distance=170)
height = peaks[1]['peak_heights'] #list of heights of peaks
peak_pos = peaks[0]
def subdivise(arr,peak_heights):
intervals = [(min(peak_heights[i],peak_heights[i + 1]),max(peak_heights[i],peak_heights[i + 1]))
for i in range(len(peak_heights) - 1)]
subarrays = [[] for _ in range(len(intervals))]
for value in arr:
for subarray_index,interval in enumerate(intervals):
if value > interval[0] and value <= interval[1]:
subarrays[subarray_index].append(value)
return subarrays
print(subdivise(y,height))
Hängt es vielleicht auch mit der Struktur von meiner Variable y ab, ist das ein Integer Array?
Also ich habe etwas gefunden was etwas klappt, jedoch nicht so das rauskommt was ich brauche.
Es geht um diesen Codeabschnitt.
Es teilt die Daten in subarrays nach peaks, jedoch etwas komisch
Das sind meine Peaks.
Jedoch teilt es erst ab den 3.Peak richtig. Sprich ich bekomme die Daten zwischen 0.07522478 und 0.09554681. Davor aber teilt es komisch Zahlen, wie hier zu sehen sind.
https://ibb.co/kgD9vT0
Dabei enthält mein Graph nocht nicht mal so hohe Zahlen.
Wie hier zu sehen ist.
https://ibb.co/9Y43hQ7
Ich habe mir dann die Variable y ausprinten lassen und da sind tatsächlich solche Zahlen drin. Wie hier zusehen ist.
https://ibb.co/Cv74qK7
Meine Fragen:
Welche Strukur hat die Variable y und wie kann ich es machen das es nicht nur ab dem 3.Peak richtig schneidet und warum sind zuerst so komische Zahlen in der Variable y, so dass es erst ab dem 3. Peak richtig schneiden kann?
Wie hier auf dem Bild zusehen ist, den Wechsel von "komische" Zahlen zu "normalen" Zahl ( in dem Fall 3. Peak) habe ich markiert.
https://ibb.co/J78GGdQ
Und anstatt das es nach dem Peak aufhört zu schneiden, schneidet es vom letzten Peak bis zur letzten Zahl, jedoch soll nach dem letzten Peak alle anderen Zahlen ignoriert werden und auch alle Zahlen vor dem ersten Peak soll ignoriert werden.
Code: Alles auswählen
[
y = butter_lowpass_filter(sensor_data, cutoff, fs, order)
peaks = find_peaks(y*-1, height = 0.00, threshold = None, distance=170)
height = peaks[1]['peak_heights'] #list of heights of peaks
peak_pos = peaks[0]
print([y[pre: next] for pre, next in zip_longest(peak_pos,peak_pos[1:])])
Es teilt die Daten in subarrays nach peaks, jedoch etwas komisch
Das sind meine Peaks.
Code: Alles auswählen
[0.06110087, 0.10401105, 0.07522478, 0.09554681, 0.08982648,
0.09118464, 0.09309628, 0.10440643, 0.08335122, 0.14826715,
0.09760258, 0.13332452, 0.11009777, 0.1806636 ]
https://ibb.co/kgD9vT0
Dabei enthält mein Graph nocht nicht mal so hohe Zahlen.
Wie hier zu sehen ist.
https://ibb.co/9Y43hQ7
Ich habe mir dann die Variable y ausprinten lassen und da sind tatsächlich solche Zahlen drin. Wie hier zusehen ist.
https://ibb.co/Cv74qK7
Meine Fragen:
Welche Strukur hat die Variable y und wie kann ich es machen das es nicht nur ab dem 3.Peak richtig schneidet und warum sind zuerst so komische Zahlen in der Variable y, so dass es erst ab dem 3. Peak richtig schneiden kann?
Wie hier auf dem Bild zusehen ist, den Wechsel von "komische" Zahlen zu "normalen" Zahl ( in dem Fall 3. Peak) habe ich markiert.
https://ibb.co/J78GGdQ
Und anstatt das es nach dem Peak aufhört zu schneiden, schneidet es vom letzten Peak bis zur letzten Zahl, jedoch soll nach dem letzten Peak alle anderen Zahlen ignoriert werden und auch alle Zahlen vor dem ersten Peak soll ignoriert werden.
Das sind keine komischen Zahlen. Das ist einfach nur die Exponenten-Darstellung, auf die Python zurückgreift, wenn Zahlen kleiner oder größer sind, und dann eine ausgeschriebene Darstellung zu viel Platz beanspruchen würde.
0.000000000000000000001
vs
1E-20
(Ich mag mich verzählt haben, aber so in etwa).
Ich halte deinen ganzen Ansatz für problematisch. Du arbeitest dich gerade daran ab Code zu schrieben, der deine Curls sauber erkennt. Wenn du den erstellt hast, ist deine Aufgabe gelöst. Das ist aber nicht der Plan. Der Plan ist, Daten für ein ML Verfahren zu erzeugen, welches dann diese Erkennung durchführt. Das bereitstellen und Labeln dieser Daten ist eine manuelle Aufgabe (bei überwachten Verfahren zumindest). Keine automatische. Es spricht natürlich nichts dagegen, sich beim erstellen dieser Testdaten vom Rechner helfen zu lassen, wenn es wie hier zb gute Features wie die peaks gibt. Aber es ist dann trotzdem nötig, sowas wie Start und Ende hier händisch zu definieren. Für diese konkreten Daten! Andere sehen anders aus, und müssen anders bearbeitet werden.
0.000000000000000000001
vs
1E-20
(Ich mag mich verzählt haben, aber so in etwa).
Ich halte deinen ganzen Ansatz für problematisch. Du arbeitest dich gerade daran ab Code zu schrieben, der deine Curls sauber erkennt. Wenn du den erstellt hast, ist deine Aufgabe gelöst. Das ist aber nicht der Plan. Der Plan ist, Daten für ein ML Verfahren zu erzeugen, welches dann diese Erkennung durchführt. Das bereitstellen und Labeln dieser Daten ist eine manuelle Aufgabe (bei überwachten Verfahren zumindest). Keine automatische. Es spricht natürlich nichts dagegen, sich beim erstellen dieser Testdaten vom Rechner helfen zu lassen, wenn es wie hier zb gute Features wie die peaks gibt. Aber es ist dann trotzdem nötig, sowas wie Start und Ende hier händisch zu definieren. Für diese konkreten Daten! Andere sehen anders aus, und müssen anders bearbeitet werden.
Zu meiner Vorgehensweise:
Mein Ziel ist es alle Rohdaten (x,y,z) zwischen den Peaks zu bekommen und auf diesen Daten sollen die Features berechnet werden, die ich auswählen muss. Diese Daten sollen gelabelt werden und dann in die ML-Pipeline in Matlab eingespeist werden. Zumindest wird es uns so mehr oder weniger vorgegeben.
Ich merke gerade das ich das schneiden in die subarrays nicht mit den Daten des Low pass filter machen muss, sondern mit sensor_data. Also sprich nach peak positionen die Achsen (x,y,z) jeweils schneiden und mit diesen Daten sollen die Features berechnet werden.
Achja, zu den Zahlen: Aber wieso fangen die Zahlen mit -6.6 oder -7.7 an, ich habe doch nur Zahlen die eine 0 vor dem Komma haben?
Ich dachte das ich mit (peak_pos,peak_pos[1:]) den Start und Endpunkt definiere, also es soll ja vom ersten bis zum letzten Peak gehen.
Mein Ziel ist es alle Rohdaten (x,y,z) zwischen den Peaks zu bekommen und auf diesen Daten sollen die Features berechnet werden, die ich auswählen muss. Diese Daten sollen gelabelt werden und dann in die ML-Pipeline in Matlab eingespeist werden. Zumindest wird es uns so mehr oder weniger vorgegeben.
Ich merke gerade das ich das schneiden in die subarrays nicht mit den Daten des Low pass filter machen muss, sondern mit sensor_data. Also sprich nach peak positionen die Achsen (x,y,z) jeweils schneiden und mit diesen Daten sollen die Features berechnet werden.
Achja, zu den Zahlen: Aber wieso fangen die Zahlen mit -6.6 oder -7.7 an, ich habe doch nur Zahlen die eine 0 vor dem Komma haben?
Ich dachte das ich mit (peak_pos,peak_pos[1:]) den Start und Endpunkt definiere, also es soll ja vom ersten bis zum letzten Peak gehen.
Wieso sollen denn die Rohdaten statt der gefilterten genommen werden? Das ergibt doch gar keinen Sinn, wenn man als Grund für die Filterung das Sensorrauschen annimmt. Die Peaks findest du auch ohne Filter.
Und 7 durch 1**5 ist immer noch 0.00007. So ist diese Notation definiert, das solltest du mal nachlesen.
Mit zip_longest füllst du das Ende mit None, und damit bekommst du auch alles nach dem letzten Peak.
Und 7 durch 1**5 ist immer noch 0.00007. So ist diese Notation definiert, das solltest du mal nachlesen.
Mit zip_longest füllst du das Ende mit None, und damit bekommst du auch alles nach dem letzten Peak.
Ich frage mal meinen Professor, ob er das wirklich so meint, ob die Features mit den Rohdaten berechnet werden sollen.
Oh okay, ich werde mich mal schlau machen über die Notation, danke!
Ich möchte nicht die Daten nach dem letzten Peak haben. Es soll ja nach dem letzten Peak stoppen, weil da die Übung aufhört. Aber ich bekomme die Daten nach dem letzten Peak mit und ohne None.
Ich dachte das wenn man nichts hinsetzt, das es nur bis zum letzten Peak geht. Wie bekomme ich das hin das es nach dem letzten Peak stoppt?
Oh okay, ich werde mich mal schlau machen über die Notation, danke!
Ich möchte nicht die Daten nach dem letzten Peak haben. Es soll ja nach dem letzten Peak stoppen, weil da die Übung aufhört. Aber ich bekomme die Daten nach dem letzten Peak mit und ohne None.
Ich dachte das wenn man nichts hinsetzt, das es nur bis zum letzten Peak geht. Wie bekomme ich das hin das es nach dem letzten Peak stoppt?
In deinem Code steht quasi das hier:
Warum ist das dann ueberraschend fuer dich, wenn anfangs_index auch den Wert des letzten Peaks annimmt? Und damit ein Intervall nach dem letzten Peak erzeugt? Das hast du doch so festgelegt. Wenn du paarweise nur die Indizes bis zum *vorletzten* Startindex erzeugen willst, dann musst du das doch auch so angeben. Ganz aehnlich zu der Art, wie du das fuer den End-Index ja auch gemacht hast.
Code: Alles auswählen
for anfangs_index, end_index in zip(alle_peaks_inklusive_des_letzten_peaks, ..)):
Ich habe angegeben das es nur bis zum vorletzten Peak das Intervall starten soll mit dem Code:
Aber es ändert sich nichts, es nimmt immer noch die Werte nach dem letzen Peak. Dazu habe ich noch ein Phänomen festgestellt.
https://ibb.co/N1xnWQN
Auf de Bild sind die letzten beiden Subarrays angezeigt. Das vorletzte Array startet am vorletzten Peak soweit so gut, es endet aber nicht am letzten Peak, sondern erst zum letzten Punkt nach dem letzten Peak. Das seltsamste jedoch ist, das es noch ein Subarray erstellt mit nochmal allen Werten was nach dem letzten Peak kommt ?!
Ich habe im vorletzten Array die Zahl markiert wo die Zahlen nach dem letzten Peak anfangen und aufhören. Und genau die selben Zahlen kommen nochmal alleine vor im letzten subarray. Wieso werden diese Werte nochmal kopiert und es erzeugt sogar ein Subarray dafür?
Wie ist das zu erklären und was mache ich da falsch?
Code: Alles auswählen
print([sensor_x[pre: next] for pre, next in zip_longest(peak_pos,peak_pos[1:len(peak_pos)-2])])
https://ibb.co/N1xnWQN
Auf de Bild sind die letzten beiden Subarrays angezeigt. Das vorletzte Array startet am vorletzten Peak soweit so gut, es endet aber nicht am letzten Peak, sondern erst zum letzten Punkt nach dem letzten Peak. Das seltsamste jedoch ist, das es noch ein Subarray erstellt mit nochmal allen Werten was nach dem letzten Peak kommt ?!
Ich habe im vorletzten Array die Zahl markiert wo die Zahlen nach dem letzten Peak anfangen und aufhören. Und genau die selben Zahlen kommen nochmal alleine vor im letzten subarray. Wieso werden diese Werte nochmal kopiert und es erzeugt sogar ein Subarray dafür?
Wie ist das zu erklären und was mache ich da falsch?
Achsoo, jetzt funktioniert es, vielen Dank! Ich habe alle Werte zwischen den Peaks und beim letzten Subarray fängt es am vorletztem Peak an und hört beim letzten Peak auf ! Also egal was man macht zip_longest geht immer über alle Werte?
Ich bin gerade dabei Features zu berechnen auf meine Segmente. Ein Feature ist die cross-correlation die uns nahe gelegt wurde.
Der Code um meine Segmente zu teilen ist das
Da es ein Array ist mit mehreren subarrays habe ich folgenden Code geschrieben.
Hier ist das Ergebnis was mir geliefert wird.
https://ibb.co/cksVbFS
Ich bin mir nicht sicher ob es mir das richtige Ergebnis liefert. Dabei muss ich es auf jedem Segment berechnen muss, muss das jeweilige Segment mit allen weiteren Segmente die Cross-Correlation berechnet werden oder?
Ich bin mir bei dem Code nicht sicher, ob es das tut was es soll. Ich denke aber das es nur die Cross-Correlation mit dem nächsten Segment berechnet oder?
Der Code um meine Segmente zu teilen ist das
Code: Alles auswählen
y=[y[pre: next] for pre, next in zip(peak_pos,peak_pos[1:len(peak_pos)])]
Code: Alles auswählen
k = []
for elem in z:
k.append(np.correlate(elem,elem+1))
print (k)
https://ibb.co/cksVbFS
Ich bin mir nicht sicher ob es mir das richtige Ergebnis liefert. Dabei muss ich es auf jedem Segment berechnen muss, muss das jeweilige Segment mit allen weiteren Segmente die Cross-Correlation berechnet werden oder?
Ich bin mir bei dem Code nicht sicher, ob es das tut was es soll. Ich denke aber das es nur die Cross-Correlation mit dem nächsten Segment berechnet oder?