Stufe 7: Reproduzierbare Abbildungen (TikZ + mplstyle)

This commit is contained in:
Cedric Fritzsch 2026-05-03 17:22:04 +02:00
parent 38c33ea6a3
commit baec87278b
6 changed files with 79 additions and 38 deletions

View File

@ -9,8 +9,8 @@ automatisierte Auswertung erfolgte in Python~\cite{python2024}.
\begin{figure}[ht] \begin{figure}[ht]
\centering \centering
\includegraphics[width=0.8\textwidth]{aufbau.png} \input{blockdiagramm.tex}
\caption{Multiplot der Frequenzgangmessung (BORIS-Screenshot).} \caption{Messaufbau (TikZ, Vektorgrafik).}
\label{fig:setup} \label{fig:setup}
\end{figure} \end{figure}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

19
blockdiagramm.tex Normal file
View File

@ -0,0 +1,19 @@
% Eingebunden in paper.tex via \input{blockdiagramm.tex}
% Vektor, reproduzierbar, Schrift passt automatisch zum Paper.
\begin{tikzpicture}[
node distance=1.4cm and 1.6cm,
block/.style={draw, thick, rectangle, rounded corners=2pt,
minimum height=1.0cm, minimum width=2.0cm,
align=center, font=\sffamily\small},
signal/.style={-{Stealth[length=2.5mm]}, thick}
]
\node[block] (sin) {Sinus-\\Generator};
\node[block, right=of sin] (str) {Drehzahl-\\Strecke};
\node[block, right=of str] (mp) {Multi-\\plot};
\node[block, below=of str] (pc) {PC\\(BORIS)};
\draw[signal] (sin) -- node[above]{\scriptsize $u_\mathrm{in}$} (str);
\draw[signal] (str) -- node[above]{\scriptsize $n_\mathrm{ist}$} (mp);
\draw[signal] (pc) -- (sin);
\draw[signal] (mp) |- (pc);
\end{tikzpicture}

View File

@ -1,27 +1,27 @@
% ===================================================================== % =====================================================================
% STUFE 5 -- Cross-References % STUFE 7 -- Reproduzierbare Abbildungen (Endzustand)
% -------------------------------------------------------------------- % --------------------------------------------------------------------
% Was sich gegenueber Stufe 4 geaendert hat: % Was sich gegenueber Stufe 5/6 geaendert hat:
% + \usepackage[ngerman]{cleveref} -> automatische Praefixe % + aufbau.png -> blockdiagramm.tex (TikZ, Vektorgrafik)
% (cleveref muss NACH hyperref geladen werden -- hyperref ist % + plt.style.use('thn.mplstyle') -> Plot-Stil zentral definiert
% bereits in der Praeambel des Templates aktiv) % + Schrift im Diagramm passt automatisch zum Paper
% + \label{...} an Figures, Tables, Equations % + Versionsverwaltung (Stufe 6) bleibt aktiv
% + \cref{fig:setup} statt "Abb.~1" hand-getippt
% + \eqref{eq:fg} fuer Gleichungen
% + Verschiebt man eine Abbildung -> Nummer wandert mit
% %
% Was noch unschoen ist: % Ergebnis:
% - Versionsverlauf existiert nicht (Regel 6) % Beliebig zoom- und druckbar, reproduzierbar, konsistent.
% - aufbau.png noch pixelig (Regel 7)
% ===================================================================== % =====================================================================
\documentclass[a4paper, parskip=half, titlepage=yes, 11pt, BCOR=12mm, toc=flat]{scrreprt} \documentclass[a4paper, parskip=half, titlepage=yes, 11pt, BCOR=12mm, toc=flat]{scrreprt}
\input{01_AbschlussarbeitPraeambel} \input{01_AbschlussarbeitPraeambel}
% Cross-References (cleveref muss nach hyperref geladen werden) % Cross-References (cleveref nach hyperref)
\usepackage[ngerman]{cleveref} \usepackage[ngerman]{cleveref}
% TikZ fuer reproduzierbare Diagramme (neu in Stufe 7)
\usepackage{tikz}
\usetikzlibrary{positioning, arrows.meta, shapes.geometric}
\input{werte.tex} \input{werte.tex}
\newcommand{\thn}{TH N\"urnberg Georg Simon Ohm} \newcommand{\thn}{TH N\"urnberg Georg Simon Ohm}

42
plot.py
View File

@ -1,27 +1,28 @@
""" """
plot.py -- erzeugt aus messwerte.csv: plot.py -- finale Version mit zentralem Plot-Stil.
* plot.pdf Bode-Diagramm (Betrag und Phase)
* tabelle.tex LaTeX-Tabelle (mit siunitx S-Spalten)
* werte.tex LaTeX-Makros mit Rohzahlen (1.59 statt 1{,}59)
Aenderung gegenueber Stufe 2: Aenderung gegenueber Stufe 3:
siunitx (\\SI{...}{...}) im paper.tex formatiert die Zahlen jetzt + plt.style.use("thn.mplstyle")
selber -- wir geben hier nur Rohzahlen mit Punkt aus. Das macht Der Plot-Stil (Schrift, Farben, Liniendicken) wird einmal in
plot.py einfacher (kein "Komma-Bastel" mehr). thn.mplstyle definiert -- alle Plots im Paper sehen automatisch
gleich aus. Aenderst du den Stil, aktualisieren sich alle Plots.
""" """
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
# Plot-Stil zentral aus Datei laden
plt.style.use("thn.mplstyle")
# 1) CSV einlesen ------------------------------------------------------ # 1) CSV einlesen ------------------------------------------------------
daten = np.loadtxt("messwerte.csv", delimiter=",", skiprows=1) daten = np.loadtxt("messwerte.csv", delimiter=",", skiprows=1)
omega = daten[:, 0] # Kreisfrequenz in rad/s omega = daten[:, 0]
betrag = daten[:, 1] # Amplitudengang in dB betrag = daten[:, 1]
phase = daten[:, 2] # Phasengang in Grad phase = daten[:, 2]
# 2) Theoretische Knickfrequenz (aus Identifikation der Strecke) ------- # 2) Theoretische Knickfrequenz ----------------------------------------
omega_K_theor = 56 # PT2-Modell, omega_n omega_K_theor = 56
K_s_dB = betrag[0] # DC-Verstaerkung (tiefste Frequenz) K_s_dB = betrag[0]
# 3) Gemessene Knickfrequenz: dort wo der Betrag um 3 dB faellt -------- # 3) Gemessene Knickfrequenz: dort wo der Betrag um 3 dB faellt --------
ziel_dB = K_s_dB - 3 ziel_dB = K_s_dB - 3
@ -29,20 +30,18 @@ omega_K_mess = np.interp(ziel_dB, np.flip(betrag), np.flip(omega))
abweichung = abs(omega_K_mess - omega_K_theor) / omega_K_theor * 100 abweichung = abs(omega_K_mess - omega_K_theor) / omega_K_theor * 100
# 4) Bode-Diagramm zeichnen -------------------------------------------- # 4) Bode-Diagramm zeichnen --------------------------------------------
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(5, 4), sharex=True) fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
ax1.semilogx(omega, betrag, "o-") ax1.semilogx(omega, betrag, "o-")
ax1.axhline(ziel_dB, linestyle=":", color="gray", ax1.axhline(ziel_dB, linestyle=":", color="gray",
label=f"$K_s - 3$ dB = {ziel_dB:.2f} dB") label=f"$K_s - 3$ dB = {ziel_dB:.2f} dB")
ax1.axvline(omega_K_theor, linestyle="--", color="gray", ax1.axvline(omega_K_theor, linestyle="--", color="gray",
label=f"$\\omega_K$ theor. = {omega_K_theor} rad/s") label=f"$\\omega_K$ theor. = {omega_K_theor} rad/s")
ax1.set_ylabel("Betrag in dB") ax1.set_ylabel("Betrag in dB")
ax1.legend(loc="lower left", fontsize=8) ax1.legend(loc="lower left")
ax1.grid(True, which="both", alpha=0.3)
ax2.semilogx(omega, phase, "o-") ax2.semilogx(omega, phase, "o-")
ax2.set_xlabel("Kreisfrequenz $\\omega$ in rad/s") ax2.set_xlabel("Kreisfrequenz $\\omega$ in rad/s")
ax2.set_ylabel("Phase in Grad") ax2.set_ylabel("Phase in Grad")
ax2.grid(True, which="both", alpha=0.3)
fig.tight_layout() fig.tight_layout()
fig.savefig("plot.pdf") fig.savefig("plot.pdf")
@ -62,13 +61,10 @@ zeilen.append(r"\end{tabular}")
with open("tabelle.tex", "w", encoding="utf-8") as datei: with open("tabelle.tex", "w", encoding="utf-8") as datei:
datei.write("\n".join(zeilen) + "\n") datei.write("\n".join(zeilen) + "\n")
# 6) Werte als LaTeX-Makros (Rohzahlen -- siunitx formatiert deutsch) -- # 6) Werte als LaTeX-Makros --------------------------------------------
with open("werte.tex", "w", encoding="utf-8") as datei: with open("werte.tex", "w", encoding="utf-8") as datei:
datei.write(f"\\newcommand{{\\omegaKtheorie}}{{{omega_K_theor}}}\n") datei.write(f"\\newcommand{{\\omegaKtheorie}}{{{omega_K_theor}}}\n")
datei.write(f"\\newcommand{{\\omegaKmess}}{{{omega_K_mess:.1f}}}\n") datei.write(f"\\newcommand{{\\omegaKmess}}{{{omega_K_mess:.1f}}}\n")
datei.write(f"\\newcommand{{\\abweichung}}{{{abweichung:.1f}}}\n") datei.write(f"\\newcommand{{\\abweichung}}{{{abweichung:.1f}}}\n")
print("Fertig: plot.pdf, tabelle.tex, werte.tex") print("Fertig: plot.pdf, tabelle.tex, werte.tex (mit thn.mplstyle).")
print(f" theoretisch: omega_K = {omega_K_theor} rad/s")
print(f" gemessen: omega_K = {omega_K_mess:.2f} rad/s")
print(f" Abweichung: {abweichung:.1f} %")

26
thn.mplstyle Normal file
View File

@ -0,0 +1,26 @@
# Matplotlib-Stylesheet -- ein Plot, immer derselbe Look.
font.family : serif
font.serif : Computer Modern Roman, Times New Roman, DejaVu Serif
font.size : 10
axes.prop_cycle : cycler('color', ['c8102e', '004680', '009e73', 'd55e00'])
axes.titlesize : 11
axes.labelsize : 10
axes.spines.top : False
axes.spines.right : False
axes.grid : True
grid.linestyle : --
grid.alpha : 0.4
lines.linewidth : 1.6
lines.markersize : 4
legend.frameon : False
legend.fontsize : 9
figure.figsize : 5.0, 4.0
figure.dpi : 120
savefig.dpi : 300
savefig.bbox : tight
savefig.format : pdf