diff --git a/data_visualization/src/data_visualization/core.py b/data_visualization/src/data_visualization/core.py new file mode 100644 index 0000000..d04ea72 --- /dev/null +++ b/data_visualization/src/data_visualization/core.py @@ -0,0 +1,66 @@ +from __future__ import annotations +import logging +from dataclasses import dataclass +from typing import List +import numpy as np +import matplotlib.pyplot as plt + + +__all__ = ["plot_spectrum", "FrequencyDataRow"] + + +@dataclass +class FrequencyDataRow: + """Repräsentiert eine einzelne Zeile von Frequenzdaten.""" + frequency_hz: float + amplitude_db: float + + def __post_init__(self) -> None: + if not isinstance(self.frequency_hz, (float, int)): + raise TypeError(f"frequency_hz muss float sein, nicht {type(self.frequency_hz)}") + if not isinstance(self.amplitude_db, (float, int)): + raise TypeError(f"amplitude_db muss float sein, nicht {type(self.amplitude_db)}") + + +# Einrichtung eines einfachen Loggers für reproduzierbares Debugging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +def plot_spectrum(frequency_data: List[float]) -> plt.Figure: + """Erzeugt ein Frequenzspektrum-Plot aus gegebenen Frequenzdaten. + + Args: + frequency_data: Liste von [frequency_hz, amplitude_db]-Paaren. + + Returns: + Matplotlib-Figur mit dem dargestellten Frequenzspektrum. + """ + if not frequency_data: + raise ValueError("frequency_data darf nicht leer sein.") + + # Validierung und Konvertierung + validated_rows: List[FrequencyDataRow] = [] + for idx, row in enumerate(frequency_data): + if not (isinstance(row, (list, tuple)) and len(row) == 2): + raise ValueError(f"Ungültiges Datenformat in Zeile {idx}: {row!r}") + freq, amp = row + validated_rows.append(FrequencyDataRow(float(freq), float(amp))) + + # Konvertierung in numpy-Arrays + freqs = np.array([r.frequency_hz for r in validated_rows], dtype=float) + amps = np.array([r.amplitude_db for r in validated_rows], dtype=float) + + # Plot-Erstellung + fig, ax = plt.subplots(figsize=(8, 4)) + ax.plot(freqs, amps, color="royalblue", linewidth=1.2) + ax.set_xlabel("Frequency (Hz)") + ax.set_ylabel("Amplitude (dBFS)") + ax.set_title("Frequency Spectrum") + ax.grid(True, linestyle="--", alpha=0.5) + + # Validierungs-Check für CI + assert isinstance(fig, plt.Figure), "plot_spectrum soll eine Matplotlib-Figur zurückgeben." + logger.info("Frequenzspektrum erfolgreich erstellt: %d Punkte", len(freqs)) + + return fig