Algoritmus zum peak finden



  • Oder du nimmst die Nullstellen der ersten Ableitung usw. 😉



  • Hi,

    das Problem ist nicht gerade trivial. Google mal nach „peak picking“. Die OpenMS-Bibliothek enthält Methoden, die das sehr zuverlässig für Dich erledigen. Wenn Du's selbst implementieren willst, solltest Du fündig werden. Kurz zusammengefasst: Basislinien-Korrektur, Erosion, evtl. zerren und dann die Peaks rausfiltern.



  • Fellhuhn schrieb:

    Oder du nimmst die Nullstellen der ersten Ableitung usw. 😉

    Viel Spaß beim Finden einer sinnvollen Funktion (geschweige denn Ableitung) in einem Array mit diskreten Integers. 😉

    Einfache Differenzen reichen hier nicht aus.



  • Hmm.. dabei spuckt der mir alle werte raus und filtert gar nichts... 😞

    Wenn ich das richtig verstehe hast du dir doch so gedacht dass aus 3 werten der höchste gesucht wird. Sowas hab ich auch schon probiert, aber dann nimmt der auch jeden ausreißer mit. 😕



  • Konrad Rudolph schrieb:

    Einfache Differenzen reichen hier nicht aus.

    Im Grunde schon (ohne Filterung). Du rechnest die Differenzen für jeden Schritt aus und kommst so auf positive Werte für Steigung und negative für ... äh... Abfall? Mist, Wort entfallen...

    Auf jeden Fall muss dann nur geschaut werden an welcher Stelle ein negativer Wert auf einen positiven folgt. Dort ist dann ein Maximum. Ob ein lokales oder globales etc. ist dann Aufgabe eines anderen Filters herauszufinden.

    Einzig problematisch sind da wohl Werte nach dem Muster 10 20 20 10. Denn dort greift keiner der bisher genannten Algorithmen.



  • Fellhuhn schrieb:

    Auf jeden Fall muss dann nur geschaut werden an welcher Stelle ein negativer Wert auf einen positiven folgt. Dort ist dann ein Maximum. Ob ein lokales oder globales etc. ist dann Aufgabe eines anderen Filters herauszufinden.

    Ja, das Problem hierbei ist, dass Du keinerlei Informationen darüber bekommst, was Peaks sind und was Artefakte (denn die will man ja rausfiltern). Das Bestimmen aller hohen Werte ist über einen Schwellwert-Filter ja kein Problem.

    Einzig problematisch sind da wohl Werte nach dem Muster 10 20 20 10. Denn dort greift keiner der bisher genannten Algorithmen.

    Na, das ist ja quasi der Idealfall, da hast Du einen Nullwert und somit ein Plateau (= Peak).



  • Ich bedanke mich für die zahlreichen beiträge,

    also das mit den integern war nur ein beispiel. es handelt sich eigenlich um float werte, die zwischen 0 und 10000 jeden wert annehmen können.

    ich wert mal nach peak picking googlen. und mir mal gedanken über nullstellen machen. so dumm find ich die idee gar nicht. ich werd mal posten wenn ich was gefunden habe.

    für weiter lösungsansätze oder hilfen wäre ich trotzdem sehr dankbar.



  • Konrad Rudolph schrieb:

    Na, das ist ja quasi der Idealfall, da hast Du einen Nullwert und somit ein Plateau (= Peak).

    Ja, aber dieser Fall erfüllt nicht die (programmierte) Bedingung das der Vorgänger und Nachfolger jeweils niedriger sind. Daher ist, wenn mit solchen Fällen zu rechnen ist, ein etwas komplexerer Algorithmus nötig um überhaupt alle lokalen Maxima zu finden.
    Und dann natürlich die Frage ob das als 2 oder nur als 1 gewertet werden soll. Und wo ist dann der Index? Links? Rechts? Mittig? Was ist mittig bei nur 2 Elementen?

    Ohne richtige Anforderung schwer zu sagen. 😉

    Wie ist denn in diesem Fall die Definition eines Ausreißers? Wird das nach Gutdüngken(?) festgelegt? Das wäre problematisch. Wenn es dafür eine Spezifikation gibt sollte es kein Problem sein.



  • Wie ist denn in diesem Fall die Definition eines Ausreißers? Wird das nach Gutdüngken(?) festgelegt? Das wäre problematisch. Wenn es dafür eine Spezifikation gibt sollte es kein Problem sein.

    naja spezifikation gibt es direkt nicht dafür. ich hätte jetzt gesagt wenn unter vielen abfallenden werten mal ein etwas höherer dabei ist, dann ist es ein außreißer.



  • Fellhuhn schrieb:

    Wie ist denn in diesem Fall die Definition eines Ausreißers? Wird das nach Gutdüngken(?) festgelegt? Das wäre problematisch. Wenn es dafür eine Spezifikation gibt sollte es kein Problem sein.

    Es gibt keine. Ich habe keine Ahnung, welches Anwendungsgebiet dem OP vorschwebt, aber am Beispiel der Massenspekrometrie kann ich sagen, dass man als menschlicher Draufschauer Ausreißer erkennt, indem man zusätzliches Wissen einbringt: „hmm, das muss ein Ausreißer sein, dieses Peak ergibt keinen Sinn, weil es hier und hier nicht dupliziert ist, oder weil wir hier keinen Sauerstoff erwarten“ (Massenspekrometrie analysiert Moleküle). Sowas kann Peak-Picking natürlich nicht leisten. Allerdings ist es fast immer möglich, im Nachhinein statistische Merkmale zu finden, die die Ausreißer charakterisiert. Leider sind das eben nicht immer dieselben. Daher ist das Problem so kompliziert.

    Aber in den meisten Fällen findet man schon mit relativ einfachen Korrekturverfahren und Heuristiken recht zuverlässig Peaks. Soweit ich mich erinnere, werden irgendwo Support Vector Machines für die Klassifizierung eingesetzt.



  • Reicht da nicht die Berechnung des Durchschnitts mit der Annahme das die tatsächlichen Peaks über diesem liegen?



  • Fellhuhn schrieb:

    Reicht da nicht die Berechnung des Durchschnitts mit der Annahme das die tatsächlichen Peaks über diesem liegen?

    Nein. Wenn deine grundlegende Kurve nicht flach ist sondern beispielsweise eine Gauss-Kurve mit aufgesetzten Peaks, dann verlierst du die Haelfte der peaks und kriegst andere Punkte hinzu, die keien peaks sind.



  • pumuckl schrieb:

    Fellhuhn schrieb:

    Reicht da nicht die Berechnung des Durchschnitts mit der Annahme das die tatsächlichen Peaks über diesem liegen?

    Nein. Wenn deine grundlegende Kurve nicht flach ist sondern beispielsweise eine Gauss-Kurve mit aufgesetzten Peaks, dann verlierst du die Haelfte der peaks und kriegst andere Punkte hinzu, die keien peaks sind.

    Das könnte man mit einem 'fließenden Durchschnitt' in den Griff kriegen. Also man bestimmt den Durschnitt nicht von allen Punkten sondern nur von den N Punkten [P_(i-N/2),P_(i-N/2+N)) aus der Umgebung eines Punktes P_i.

    Es gibt sicher einen ganzen Haufen von Heuristiken das Problem in den Griff zu kriegen - wie ja auch die schon erwähnten Links zeigen. Wobei fragemann schon eine Idee davon haben sollte, wie diese Peaks aussehen.

    Ich würde mit einem Schwellwert starten. Das kann der Durchschnitt aller Messwerte sein, der fließende Durchschnitt (s.o.), ein von außen angegebener Wert oder ein Durchschnitt mit einem Delta oben drauf. Dann bestimme die Intervalle in denen die Messwerte oberhalb dieses Schwellwerts liegen. Anschließend bestimmt man die maximale Höhe und teilt das Quadrat der Höhe durch die Fläche - also die Summe aller Werte mal ihre Anzahl. Dann bekommt man etwas heraus, was der Streckung des Peaks entspricht. Dieser Wert sollte einen vorher festgelegten Wert eines Streckung-Minimums überschreiten, damit das gefundene Intervall als echter Peak durchgeht.

    Anschließend wird die genaue Position des Peaks bestimmt. Das kann der Schwerpunkt der Fläche sein, oder die Position des Maximums im Intervall oder die vordere oder hintere Flanke des Peaks. Flanke bestimmen geht über: Differenzen der Messwerte bilden, durch die drei größten Differenzen eine Parabel legen und schließlich deren Maximum bestimmen.

    Was davon geeignet und weniger geeignet ist, hängt ausschließlich davon ab, wie diese Peaks denn aussehen müssten, wenn die 'ideal' wären. Ein Verfahren welches bei einem idealen Peak den korrekten Wert liefert, wäre ein geeigneter Kandidat.

    Was sind das für Messwerte? Wie sähe ein idealer Peak aus? Welche physikalische Einheit haben die Messwerte und welche die 'Indizes' (z.B. Zeit oder Weg oder ..)?

    Gruß
    Werner



  • Also es handelt sich um eine spektralanalyse, die ein lichtspektrum zwischen 170 und 900 nm zeigt.

    ich hab das ganze mal grafisch dargestellt, und mit meiner momentanen berechung die peaks einzeichnen lassen.

    Momentan berechne ich die peaks in dem ich ein größenvergleich mache, unter tolleranz kann ich angeben wieviele werte vor bzw. nach einem bestimmten wert niedriger sein müssen, um es als peak zu identifizieren. das ganze funktioniert soweit ganz gut. es wird sich jetzt bei weiterer bearbeitung heraus stellen ob es ausreichend ist oder nicht.

    Sinn und zweck des ganzen soll nachher sein das ich den einzelnen peaks elemente zuweisen kann um dem ganzen nachher ein material zuordnen kann, bzw. eine Materialveränderung.

    hier mal ein bild vom aktuellen spektrum.

    http://www.jbopael.de/PeakAuswertung.jpg

    Ich bedank mich nochmals für die zahlreichen beiträge.



  • Ich würd es ganz anders machen: Pack das Zeugs in nen vector - am Besten als pair (<position, wert>) und hau jedes Pair mit erase raus, was ZWISCHEN den beiden umliegenden Werten liegt... So würd ichs zumindest machen... 🤡 Dann kannst du danach zur Not auch noch die "nicht wirklichen" Ausreiser raushauen, indem du noch mal nach den Positionswerten guckst und - falls die zu Nah an dem nächsten dranliegen - sie einfach raushauen...

    Byebye 🤡



  • Viel Spaß beim Finden einer sinnvollen Funktion (geschweige denn Ableitung) in einem Array mit diskreten Integers. 😉

    Nen 1D Sobel gibt ne brauchbare Approximation davon.


Anmelden zum Antworten