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

42
plot.py
View File

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

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