From 30e75a240dd632f11e0afc06600b0b10b4a59c74 Mon Sep 17 00:00:00 2001 From: Mika Date: Fri, 3 Apr 2026 10:57:07 +0000 Subject: [PATCH] Add artifact.scatter_plot/src/artifact_scatter_plot/core.py --- .../src/artifact_scatter_plot/core.py | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 artifact.scatter_plot/src/artifact_scatter_plot/core.py diff --git a/artifact.scatter_plot/src/artifact_scatter_plot/core.py b/artifact.scatter_plot/src/artifact_scatter_plot/core.py new file mode 100644 index 0000000..4feb247 --- /dev/null +++ b/artifact.scatter_plot/src/artifact_scatter_plot/core.py @@ -0,0 +1,72 @@ +from __future__ import annotations + +import logging +from dataclasses import dataclass +from typing import List + +import matplotlib.pyplot as plt +import pandas as pd + + +logger = logging.getLogger(__name__) + + +@dataclass +class ScatterData: + """Repräsentiert einen einzelnen Messdatensatz für den Scatter-Plot.""" + + band_width: float + near_expiry_unpinned: float + + def __post_init__(self) -> None: + if not isinstance(self.band_width, (float, int)): + raise TypeError("band_width muss vom Typ float oder int sein.") + if not isinstance(self.near_expiry_unpinned, (float, int)): + raise TypeError("near_expiry_unpinned muss vom Typ float oder int sein.") + + self.band_width = float(self.band_width) + self.near_expiry_unpinned = float(self.near_expiry_unpinned) + + +def create_scatter_plot(data: List[ScatterData]) -> None: + """Erstellt und zeigt einen Scatter-Plot aus einer Liste von ScatterData-Objekten. + + Args: + data: Liste der Messpunkte mit band_width und near_expiry_unpinned-Werten. + + Raises: + ValueError: Falls die Eingabedaten leer oder ungültig sind. + """ + if not isinstance(data, list): + raise TypeError("data muss eine Liste von ScatterData-Objekten sein.") + if not data: + raise ValueError("Die Eingabedatenliste ist leer.") + + # Validierung und Konvertierung in DataFrame + records = [] + for idx, item in enumerate(data): + if not isinstance(item, ScatterData): + raise TypeError(f"Eintrag {idx} ist kein ScatterData-Objekt.") + records.append({ + "band_width": item.band_width, + "near_expiry_unpinned": item.near_expiry_unpinned, + }) + + df = pd.DataFrame.from_records(records) + + if df.empty: + raise ValueError("Keine gültigen Daten zum Plotten gefunden.") + + logger.debug("Erstelle Scatter-Plot mit %d Punkten", len(df)) + + plt.figure(figsize=(8, 6)) + plt.scatter(df["band_width"], df["near_expiry_unpinned"], alpha=0.7, edgecolors='k') + plt.title("Mix Freeze Scatter Analysis") + plt.xlabel("Band Width") + plt.ylabel("Near-Expiry Unpinned") + plt.grid(True) + plt.tight_layout() + + plt.show() + + logger.info("Scatter-Plot erfolgreich angezeigt.")