Implementierung der Leistungsdichtespektren PSD in Python - EL MOSTAPHA LOUBANE

Implementierung der Leistungsdichtespektren PSD in Python

Implementierung der Leistungsdichtespektren in Python

Überblick über den Code zur PSD-Extraktion

Einführung

Der folgende Code dient dazu, die Leistungsdichtespektren (Power Spectral Densities, PSD) von WAV-Dateien zu extrahieren und zu visualisieren. Die PSD zeigt, wie die Energie eines Signals über verschiedene Frequenzen verteilt ist, was in vielen Bereichen wie der Signalverarbeitung und der Akustik nützlich ist. Hier ist eine detaillierte Erklärung des Codes und seiner Funktionen:

Struktur des Codes

Importieren der Bibliotheken

import soundfile as sf
from scipy.signal import welch
import matplotlib.pyplot as plt
import os

- soundfile: Wird verwendet, um WAV-Dateien zu lesen.
- scipy.signal.welch: Berechnet die PSD eines Signals.
- matplotlib.pyplot: Zum Plotten der Ergebnisse.
- os: Zum Navigieren im Dateisystem.

Klassen

Merkmal_Extraktor

class Merkmal_Extraktor:
    def __init__(self, Basisordner, Name, XAchseBeschriftung, YAchseBeschriftung, ZAchseBeschriftung):
        self.Basisordner = Basisordner
        self.Name = Name
        self.XachseBeschriftung = XAchseBeschriftung
        self.YachseBeschriftung = YAchseBeschriftung
        self.ZachseBeschriftung = ZAchseBeschriftung
        self.para_dict = {}
        self.merkmal_daten = None

    def _voller_Wellenpfad(self):
        return self.Basisordner
    
    def _lese_Wav(self, Dateipfad):
        Data, Abtastrate = sf.read(Dateipfad)
        return Data, Abtastrate

Diese Klasse dient als Basisklasse für das Lesen und Verarbeiten von WAV-Dateien. Sie enthält grundlegende Attribute und Methoden:

  • __init__: Initialisiert die Klasse mit den notwendigen Parametern.
  • _voller_Wellenpfad: Gibt den Basisordner zurück.
  • _lese_Wav: Liest eine WAV-Datei und gibt die Daten und die Abtastrate zurück.

Merkmal_Extraktor_WelchPSD

class Merkmal_Extraktor_WelchPSD(Merkmal_Extraktor):
    def __init__(self, Basisordner, Name='WelchPSD'):
        super().__init__(Basisordner, Name, XAchseBeschriftung='Frequenzen', YAchseBeschriftung='Leistung', ZAchseBeschriftung='none')
        self.para_dict['Type'] = 'WelchPSD'
        self.para_dict['Type_Name'] = 'WelchPSD'
        self.set_hyperparameter()
        self.psd_daten = None
        self.frequenzen = None
    
    def set_hyperparameter(self, nperseg=256):
        self.para_dict['Hyperpara'] = {'nperseg': nperseg}
    
    def erstelle_aus_wav(self, Dateipfad):
        Data, Abtastrate = self._lese_Wav(Dateipfad)
        print(f"Abtastrate: {Abtastrate} Hz")
        if len(Data.shape) > 1:
            print(f"Zahl der Kanäle: {Data.shape[1]}")
        else:
            print("Anzahl der Kanäle: 1")
        psd_Liste = []
        frequenzen = None
        for i in range(Data.shape[1]):
            frequenzen, psd = welch(Data[:, i], fs=Abtastrate, nperseg=self.para_dict['Hyperpara']['nperseg'])
            psd_Liste.append(psd)
        self.frequenzen = frequenzen
        self.psd_daten = psd_Liste

    def merkmale_plotten(self, Titel, fig=None):
        if self.psd_daten is None oder self.frequenzen ist None:
            raise Exception('Keine Daten zum Plotten.')
        
        if fig is None:
            fig = plt.figure(figsize=(12, 6))
            plt.title(f'Welch PSD - {Titel}')
        
        for i, psd in enumerate(self.psd_daten):
            plt.plot(self.frequenzen, psd, label=f'{Titel} - Kanal {i+1}')
        plt.xlabel('Frequenz (Hz)')
        plt.ylabel('Leistungsdichtespektrum (PSD)')
        plt.legend()
        plt.tight_layout()

Diese Klasse erbt von Merkmal_Extraktor und fügt spezifische Methoden zur Berechnung und zum Plotten der PSD hinzu:

  • __init__: Initialisiert die Klasse und setzt Hyperparameter.
  • set_hyperparameter: Setzt den Hyperparameter für die PSD-Berechnung.
  • erstelle_aus_wav: Liest eine WAV-Datei, berechnet die PSD und speichert die Ergebnisse.
  • merkmale_plotten: Plottet die gespeicherten PSD-Daten.

Funktion zum Verarbeiten aller Dateien

def alle_dateien_verarbeiten(Basisordner):
    for ID_Ordner in sorted(os.listdir(Basisordner)):
        ID_Pfad = os.path.join(Basisordner, ID_Ordner)
        if os.path.isdir(ID_Pfad):
            print(f'Verzeichnis wird verarbeitet: {ID_Pfad}')
            fig = plt.figure(figsize=(12, 6))
            plt.title(f'Welch PSD - {ID_Ordner}')
            Kategorien = ['abnormal', 'normal']
            for Kategorie in Kategorien:
                Kategorie_ordner = os.path.join(ID_Pfad, Kategorie)
                alle_datein = [os.path.join(Kategorie_ordner, f) for f in os.listdir(Kategorie_ordner) if f.endswith('.wav')]
                for Datei_pfad in alle_datein:
                    print(f'Verarbeitung --> {Datei_pfad}')
                    Extraktor = Merkmal_Extraktor_WelchPSD(Basisordner)
                    try:
                        Extraktor.erstelle_aus_wav(Datei_pfad)
                        Extraktor.merkmale_plotten(Titel=f'{Kategorie.capitalize()} - {os.path.basename(Datei_pfad)}', fig=fig)
                    except ValueError as e:
                        print(f'Fehler bei der Verarbeitung von {Datei_pfad}: {e}')
            plt.show()
    return

Diese Funktion durchläuft das Basisverzeichnis, verarbeitet alle WAV-Dateien und plottet die Ergebnisse:

  • alle_dateien_verarbeiten: Durchläuft alle Unterverzeichnisse und Dateien im Basisordner, liest die WAV-Dateien und plottet die PSDs für jede ID in einer einzigen Figur.

Main-Funktion

if __name__ == "__main__":
    Basisordner = r'C:\Users\Andreas\Desktop\Projekt\data\6_dB_valve\valve'
    alle_dateien_verarbeiten(Basisordner)

Das Hauptskript ruft die alle_dateien_verarbeiten Funktion auf, um alle Dateien im angegebenen Basisordner zu verarbeiten.

Zusammenfassung

Der Code dient dazu, die PSD von WAV-Dateien zu berechnen und zu visualisieren. Er durchläuft einen Basisordner mit Unterverzeichnissen, liest die WAV-Dateien, berechnet die PSD mithilfe der Welch-Methode und plottet die Ergebnisse für jede ID in einer einzigen Figur. Die Implementierung ist modular aufgebaut, wobei Klassen zur Organisation und Wiederverwendbarkeit des Codes beitragen.

No comments :