refactor with own translation package

This commit is contained in:
matthias@quintern.xyz 2025-02-17 02:16:22 +01:00
parent 3e172175a7
commit 921d2b099a
22 changed files with 1233 additions and 675 deletions

81
scripts/formulary.py Normal file
View File

@ -0,0 +1,81 @@
#!/usr/bin env python3
import os
import matplotlib.pyplot as plt
import numpy as np
import math
import scipy as scp
import matplotlib as mpl
mpl.rcParams["font.family"] = "serif"
mpl.rcParams["mathtext.fontset"] = "stix"
mpl.rcParams["text.usetex"] = True
mpl.rcParams['text.latex.preamble'] = r'\usepackage{amsmath}\usepackage{siunitx}'
if __name__ == "__main__": # make relative imports work as described here: https://peps.python.org/pep-0366/#proposed-change
if __package__ is None:
__package__ = "formulary"
import sys
filepath = os.path.realpath(os.path.abspath(__file__))
sys.path.insert(0, os.path.dirname(os.path.dirname(filepath)))
from util.mpl_colorscheme import set_mpl_colorscheme
import util.colorschemes as cs
from util.gen_tex_colorscheme import generate_latex_colorscheme
# SET THE COLORSCHEME
# hard white and black
# cs.p_gruvbox["fg0"] = "#000000"
# cs.p_gruvbox["bg0"] = "#ffffff"
# COLORSCHEME = cs.gruvbox_light()
# COLORSCHEME = cs.gruvbox_dark()
# cs.p_tum["fg0"] = cs.p_tum["alt-blue"]
COLORSCHEME = cs.tum()
# COLORSCHEME = cs.legacy()
tex_src_path = "../src/"
img_out_dir = os.path.join(tex_src_path, "img")
filetype = ".pdf"
skipasserts = False
full = 8
size_half_half = (full/2, full/2)
size_third_half = (full/3, full/2)
size_half_third = (full/2, full/3)
def assert_directory():
if not skipasserts:
assert os.path.abspath(".").endswith("scripts"), "Please run from the `scripts` directory"
def texvar(var, val, math=True):
s = "$" if math else ""
s += f"\\{var} = {val}"
if math: s += "$"
return s
def export(fig, name, tight_layout=True):
assert_directory()
filename = os.path.join(img_out_dir, name + filetype)
if tight_layout:
fig.tight_layout()
fig.savefig(filename, bbox_inches="tight", pad_inches=0.0)
@np.vectorize
def smooth_step(x: float, left_edge: float, right_edge: float):
x = (x - left_edge) / (right_edge - left_edge)
if x <= 0: return 0.
elif x >= 1: return 1.
else: return 3*(x*2) - 2*(x**3)
# run even when imported
set_mpl_colorscheme(COLORSCHEME)
if __name__ == "__main__":
assert_directory()
s = \
"""% This file was generated by scripts/formulary.py\n% Do not edit it directly, changes will be overwritten\n""" + generate_latex_colorscheme(COLORSCHEME)
filename = os.path.join(tex_src_path, "util/colorscheme.tex")
print(f"Writing tex colorscheme to {filename}")
with open(filename, "w") as file:
file.write(s)

View File

@ -0,0 +1,10 @@
def color_latex_def(name, color):
# name = name.replace("-", "_")
color = color.strip("#")
return "\\definecolor{" + name + "}{HTML}{" + color + "}"
def generate_latex_colorscheme(palette):
s = ""
for n, c in palette.items():
s += color_latex_def(n, c) + "\n"
return s

View File

@ -47,45 +47,51 @@
\eng[electrolytic]{electrolytic}
\ger[electrolytic]{electrolytisch}
\Eng[working_electrode]{Working electrode}
\Eng[counter_electrode]{Counter electrode}
\Eng[reference_electrode]{Reference electrode}
\Ger[working_electrode]{Working electrode}
\Ger[counter_electrode]{Gegenelektrode}
\Ger[reference_electrode]{Referenzelektrode}
\Eng[potentiostat]{Potentiostat}
\Ger[potentiostat]{Potentiostat}
\begin{formula}{schematic}
\desc{Schematic}{}{}
\desc[german]{Aufbau}{}{}
\begin{tikzpicture}
\pgfmathsetmacro{\width}{3}
\pgfmathsetmacro{\height}{4}
\pgfmathsetmacro{\elWidth}{\width/9}
\begin{tikzpicture}[scale=1.0,transform shape]
\pgfmathsetmacro{\W}{6}
\pgfmathsetmacro{\H}{3}
\pgfmathsetmacro{\elW}{\W/20}
\draw[thick] (0,0) rectangle (\width,\height);
\fill[bg-blue] (-2,-2) rectangle (2,0.5);
\pgfmathsetmacro{\CEx}{1/6*\W}
\pgfmathsetmacro{\WEx}{3/6*\W}
\pgfmathsetmacro{\REx}{5/6*\W}
\fill[bg-blue] (0,0) rectangle (\W, \H/2);
\draw[ultra thick] (0,0) rectangle (\W,\H);
% Electrodes
\draw[thick, red] (-1,2) -- (-1,-1.2); % Reference electrode
\draw[thick, green] (0,2) -- (0,-1); % Counter electrode
\draw[thick, gray] (1,2) -- (1,-1.5); % Working electrode
% Labels
\node[left] at (-1,0) {Reference electrode};
\node[left] at (0,-0.5) {Counter electrode};
\node[right] at (1,-1) {Working electrode};
\node[left] at (-2,-1.5) {Electrolyte};
% Potentiostat
\draw[thick] (-2.5,3) rectangle (2.5,4);
\node at (0,3.5) {Potentiostat};
\draw[thick, fill=bg-gray] (\CEx-\elW,\H/5) rectangle (\CEx+\elW,\H);
\draw[thick, fill=bg-purple] (\WEx-\elW,\H/5) rectangle (\WEx+\elW,\H);
\draw[thick, fill=bg-yellow] (\REx-\elW,\H/5) rectangle (\REx+\elW,\H);
\node at (\CEx,3*\H/5) {C};
\node at (\WEx,3*\H/5) {W};
\node at (\REx,3*\H/5) {R};
% potentiostat
\pgfmathsetmacro{\potH}{\H+0.5+2}
\pgfmathsetmacro{\potM}{\H+0.5+1}
\draw[thick] (0,\H+0.5) rectangle (\W,\potH);
% Wires
\draw[thick] (-1,2) -- (-1,3);
\draw[thick] (0,2) -- (0,3);
\draw[thick] (1,2) -- (1,3);
\draw (\CEx,\H) -- (\CEx,\potM) to[voltmeter,-o] (\WEx,\potM) to[european voltage source] (\WEx+1/6*\W,\potM) to[ammeter] (\REx,\potM);
\draw (\WEx,\H) -- (\WEx,\H+1.5);
\draw (\REx,\H) -- (\REx,\H+1.5);
% Ammeter and Voltmeter
\draw[thick] (-1,2) to[ammeter] (-1,3);
\draw[thick] (0,2) -- (0,3);
\draw[thick] (1,2) to[voltmeter] (1,3);
% Connecting to potentiostat
\draw[thick] (-1,3.8) -- (-1,4);
\draw[thick] (1,3.8) -- (1,4);
% labels
\node[anchor=west, align=left] at (\W+0.2, 1*\H/4) {{\color{bg-gray} \blacksquare} \GT{counter_electrode}};
\node[anchor=west, align=left] at (\W+0.2, 2*\H/4) {{\color{bg-purple}\blacksquare} \GT{working_electrode}};
\node[anchor=west, align=left] at (\W+0.2, 3*\H/4) {{\color{bg-yellow}\blacksquare} \GT{reference_electrode}};
\node[anchor=west, align=left] at (\W+0.2, \potM) {\GT{potentiostat}};
\end{tikzpicture}
\end{formula}
@ -298,61 +304,89 @@
\eq{\eta_\text{act} = E_\text{electrode} - E_\text{ref}}
\end{formula}
\begin{formula}{concentration_overpotential}
\desc{Concentration overpotential}{Due to concentration gradient near the electrode, the ions need to \hyperref[f:ch:el:ion_cond:diffusion]{diffuse} to the electrode before reacting}{\ConstRef{universal_gas}, \QtyRef{temperature}, $\c_{0/\txS}$ ion concentration in the electrolyte / at the double layer, $z$ \qtyRef{charge_number}, \ConstRef{faraday}}
\desc[german]{Konzentrationsüberspannung}{Durch einen Konzentrationsgradienten an der Elektrode müssen Ionen erst zur Elektrode \hyperref[f:ch:el:ion_cond:diffusion]{diffundieren}, bevor sie reagieren können}{}
\eq{
\eta_\text{conc,anodic} &= -\frac{RT}{\alpha \,zF} \ln \left(\frac{c_\text{red}^0}{c_\text{red}^\txS}\right) \\
\eta_\text{conc,cathodic} &= -\frac{RT}{(1-\alpha) zF} \ln \left(\frac{c_\text{ox}^0}{c_\text{ox}^\txS}\right)
}
\end{formula}
\begin{formula}{diffusion_overpotential}
\desc{Diffusion overpotential}{}{}
\desc[german]{Diffusionsüberspannung}{}{}
\eq{\eta_\text{diff} = \frac{RT}{nF} \ln \left( \cfrac{\cfrac{c^\txs_\text{ox}}{c^0_\text{ox}}}{\cfrac{c^\txs_\text{red}}{c^0_\text{red}}} \right)}
\end{formula}
\begin{formula}{diffusion_layer}
\desc{Cell layers}{}{}
\desc[german]{Zellschichten}{}{}
\begin{tikzpicture}
\tikzset{
label/.style={color=fg1,anchor=center,rotate=90},
\Subsubsection[
\eng{Mass transport}
\ger{Massentransport}
]{mass}
\begin{formula}{concentration_overpotential}
\desc{Concentration overpotential}{Due to concentration gradient near the electrode, the ions need to \hyperref[f:ch:el:ion_cond:diffusion]{diffuse} to the electrode before reacting}{\ConstRef{universal_gas}, \QtyRef{temperature}, $\c_{0/\txS}$ ion concentration in the electrolyte / at the double layer, $z$ \qtyRef{charge_number}, \ConstRef{faraday}}
\desc[german]{Konzentrationsüberspannung}{Durch einen Konzentrationsgradienten an der Elektrode müssen Ionen erst zur Elektrode \hyperref[f:ch:el:ion_cond:diffusion]{diffundieren}, bevor sie reagieren können}{}
\eq{
\eta_\text{conc,anodic} &= -\frac{RT}{\alpha \,zF} \ln \left(\frac{c_\text{red}^0}{c_\text{red}^\txS}\right) \\
\eta_\text{conc,cathodic} &= -\frac{RT}{(1-\alpha) zF} \ln \left(\frac{c_\text{ox}^0}{c_\text{ox}^\txS}\right)
}
\pgfmathsetmacro{\tkW}{8} % Total width
\pgfmathsetmacro{\tkH}{5} % Total height
\pgfmathsetmacro{\edW}{1} % electrode width
\pgfmathsetmacro{\hhW}{1} % helmholtz width
\pgfmathsetmacro{\ndW}{2} % nernst diffusion with
\pgfmathsetmacro{\eyW}{\tkW-\edW-\hhW-\ndW} % electrolyte width
\pgfmathsetmacro{\edX}{0} % electrode width
\pgfmathsetmacro{\hhX}{\edW} % helmholtz width
\pgfmathsetmacro{\ndX}{\edW+\hhW} % nernst diffusion with
\pgfmathsetmacro{\eyX}{\tkW-\eyW} % electrolyte width
\end{formula}
\draw[->] (0,0) -- (\tkW+0.2,0) node[anchor=north] {$x$};
\draw[->] (0,0) -- (0,\tkH+0.2) node[anchor=east] {$c$};
\path[fill=bg-orange] (\edX,0) rectangle (\edX+\edW,\tkH); \node[label] at (\edX+\edW/2,\tkH/2) {\GT{electrode}};
\path[fill=bg-green!90!bg0] (\hhX,0) rectangle (\hhX+\hhW,\tkH); \node[label] at (\hhX+\hhW/2,\tkH/2) {\GT{helmholtz_layer}};
\path[fill=bg-green!60!bg0] (\ndX,0) rectangle (\ndX+\ndW,\tkH); \node[label] at (\ndX+\ndW/2,\tkH/2) {\GT{nernst_layer}};
\path[fill=bg-green!20!bg0] (\eyX,0) rectangle (\eyX+\eyW,\tkH); \node[label] at (\eyX+\eyW/2,\tkH/2) {\GT{elektrolyte}};
\draw (\hhX,2) -- (\ndX,3) -- (\tkW,3);
\tkYTick{2}{$c^\txS$};
\tkYTick{3}{$c^0$};
\end{tikzpicture}
\end{formula}
\Eng[c_surface]{surface \qtyRef{concentration}}
\Eng[c_bulk]{bulk \qtyRef{concentration}}
\Ger[c_surface]{Oberflächen-\qtyRef{concentration}}
\Ger[c_bulk]{Bulk-\qtyRef{concentration}}
\begin{formula}{diffusion_overpotential}
\desc{Diffusion overpotential}{Due to mass transport limitations}{$j_\infty$ \secEqRef{limiting_current}, $j_\text{meas}$ measured \qtyRef{current_density}, \ConstRef{universal_gas}, \QtyRef{temperature}, $n$ \qtyRef{charge_number}, \ConstRef{faraday}}
\desc[german]{Diffusionsüberspannung}{Durch Limit des Massentransports}{}
% \eq{\eta_\text{diff} = \frac{RT}{nF} \ln \left( \frac{\cfrac{c^\txs_\text{ox}}{c^0_\text{ox}}}{\cfrac{c^\txs_\text{red}}{c^0_\text{red}}} \right)}
\eq{\eta_\text{diff} = \frac{RT}{nF} \Ln{\frac{j_\infty}{j_\infty - j_\text{meas}}}}
\end{formula}
\begin{formula}{diffusion_layer}
\desc{Cell layers}{}{}
\desc[german]{Zellschichten}{}{}
\begin{tikzpicture}
\tikzset{
label/.style={color=fg1,anchor=center,rotate=90},
}
\pgfmathsetmacro{\tkW}{8} % Total width
\pgfmathsetmacro{\tkH}{4} % Total height
\pgfmathsetmacro{\edW}{1} % electrode width
\pgfmathsetmacro{\hhW}{1} % helmholtz width
\pgfmathsetmacro{\ndW}{2} % nernst diffusion with
\pgfmathsetmacro{\eyW}{\tkW-\edW-\hhW-\ndW} % electrolyte width
\pgfmathsetmacro{\edX}{0} % electrode width
\pgfmathsetmacro{\hhX}{\edW} % helmholtz width
\pgfmathsetmacro{\ndX}{\edW+\hhW} % nernst diffusion with
\pgfmathsetmacro{\eyX}{\tkW-\eyW} % electrolyte width
\path[fill=bg-orange] (\edX,0) rectangle (\edX+\edW,\tkH); \node[label] at (\edX+\edW/2,\tkH/2) {\GT{electrode}};
\path[fill=bg-green!90!bg0] (\hhX,0) rectangle (\hhX+\hhW,\tkH); \node[label] at (\hhX+\hhW/2,\tkH/2) {\GT{helmholtz_layer}};
\path[fill=bg-green!60!bg0] (\ndX,0) rectangle (\ndX+\ndW,\tkH); \node[label] at (\ndX+\ndW/2,\tkH/2) {\GT{nernst_layer}};
\path[fill=bg-green!20!bg0] (\eyX,0) rectangle (\eyX+\eyW,\tkH); \node[label] at (\eyX+\eyW/2,\tkH/2) {\GT{electrolyte}};
\draw (\hhX,2) -- (\ndX,3) -- (\tkW,3);
% axes
\draw[->] (0,0) -- (\tkW+0.2,0) node[anchor=north] {$x$};
\draw[->] (0,0) -- (0,\tkH+0.2) node[anchor=east] {$c$};
\tkYTick{2}{$c^\txS$};
\tkYTick{3}{$c^0$};
\end{tikzpicture}
\end{formula}
\Eng[c_surface]{surface \qtyRef{concentration}}
\Eng[c_bulk]{bulk \qtyRef{concentration}}
\Ger[c_surface]{Oberflächen-\qtyRef{concentration}}
\Ger[c_bulk]{Bulk-\qtyRef{concentration}}
\begin{formula}{diffusion_layer_thickness}
\desc{Nerst Diffusion layer thickness}{}{$c^0$ \GT{c_bulk}, $c^\txs$ \GT{c_surface}}
\desc[german]{Dicke der Nernstschen Diffusionsschicht}{}{}
\eq{\delta_\txN = \frac{c^0 - c^\txs}{\odv{c}{x}_{x=0}}}
\end{formula}
\begin{formula}{diffusion_layer_thickness}
\desc{Nerst Diffusion layer thickness}{}{$c^0$ \GT{c_bulk}, $c^\txS$ \GT{c_surface}}
\desc[german]{Dicke der Nernstschen Diffusionsschicht}{}{}
\eq{\delta_\txN = \frac{c^0 - c^\txS}{\odv{c}{x}_{x=0}}}
\end{formula}
\begin{formula}{limiting_current}
\desc{(Limiting) current density}{}{$n$ \QtyRef{charge_number}, \ConstRef{faraday}, $c^0$ \GT{c_bulk}, $D$ \qtyRef{diffusion_coefficient}, $\delta_\text{diff}$ \secEqRef{diffusion_layer_thickness}}
% \desc[german]{Limitierender Strom}{}{}
\eq{
\abs{j} &= nFD \frac{c^0-c^\txS}{\delta_\text{diff}}
\shortintertext{\GT{for} $c^\txS \to 0$}
\abs{j_\infty} &= nFD \frac{c^0}{\delta_\text{diff}}
}
\end{formula}
\begin{formula}{relation?}
\desc{Current - concentration relation}{}{$c^0$ \GT{c_bulk}, $c^\txS$ \GT{c_surface}, $j$ \secEqRef{limiting_current}}
\desc[german]{Strom - Konzentrationsbeziehung}{}{}
\eq{\frac{j}{j_\infty} = 1 - \frac{c^\txS}{c^0}}
\end{formula}
\begin{formula}{kinetic_current}
\desc{Kinetic current density}{}{$j_\text{meas}$ measured \qtyRef{current_density}, $j_\infty$ \secEqRef{limiting_current}}
\desc[german]{Kinetische Stromdichte}{}{$j_\text{meas}$ gemessene \qtyRef{current_density}, $j_\infty$ \secEqRef{limiting_current}}
\eq{j_\text{kin} = \frac{j_\text{meas} j_\infty}{j_\infty - j_\text{meas}}}
\end{formula}
\begin{formula}{roughness_factor}
\desc{Roughness factor}{Surface area related to electrode geometry}{}
@ -361,10 +395,10 @@
\begin{formula}{butler_volmer}
\desc{Butler-Volmer equation}{Reaction kinetics near the equilibrium potentential}
{$j$ \qtyRef{current_density}, $j_0$ exchange current density, $\eta$ \fqEqRef{ch:el:kin:overpotential}, \QtyRef{temperature}, $z$ \qtyRef{charge_number}, \ConstRef{faraday}, \ConstRef{universal_gas}, $\alpha_{\txC/\txA}$ cathodic/anodic charge transfer coefficient}
{$j$ \qtyRef{current_density}, $j_0$ exchange current density, $\eta$ \fqEqRef{ch:el:kin:overpotential}, \QtyRef{temperature}, $z$ \qtyRef{charge_number}, \ConstRef{faraday}, \ConstRef{universal_gas}, $\alpha_{\txC/\txA}$ cathodic/anodic charge transfer coefficient, $\text{rf}$ \secEqRef{roughness_factor}}
%Current through an electrode iof a unimolecular redox reaction with both anodic and cathodic reaction occuring on the same electrode
\desc[german]{Butler-Volmer-Gleichung}{Reaktionskinetik in der Nähe des Gleichgewichtspotentials}
{$j$ \qtyRef{current_density}, $j_0$ Austauschstromdichte, $\eta$ \fqEqRef{ch:el:kin:overpotential}, \QtyRef{temperature}, $z$ \qtyRef{charge_number}, \ConstRef{faraday}, \ConstRef{universal_gas}, $\alpha_{\txC/\txA}$ Ladungstransferkoeffizient an der Kathode/Anode}
{$j$ \qtyRef{current_density}, $j_0$ Austauschstromdichte, $\eta$ \fqEqRef{ch:el:kin:overpotential}, \QtyRef{temperature}, $z$ \qtyRef{charge_number}, \ConstRef{faraday}, \ConstRef{universal_gas}, $\alpha_{\txC/\txA}$ Ladungstransferkoeffizient an der Kathode/Anode, $\text{rf}$ \secEqRef{roughness_factor}}
\begin{gather}
j = j_0 \,\rfactor\, \left[ \Exp{\frac{(1-a_\txC) z F \eta}{RT}} - \Exp{-\frac{\alpha_\txC z F \eta}{RT}}\right]
\intertext{\GT{with}}
@ -434,46 +468,83 @@
\Subsubsection[
\eng{Cyclic voltammetry}
\ger{Zyklische Voltammetrie}
]{cycl_v}
\begin{formula}{duck}
]{cv}
\begin{bigformula}{duck}
\desc{Cyclic voltammogram}{}{}
% \desc[german]{}{}{}
\begin{tikzpicture}
\pgfmathsetmacro{\Ax}{-2.3}
\pgfmathsetmacro{\Ay}{ 0.0}
\pgfmathsetmacro{\Bx}{ 0.0}
\pgfmathsetmacro{\By}{ 1.0}
\pgfmathsetmacro{\Cx}{ 0.4}
\pgfmathsetmacro{\Cy}{ 1.5}
\pgfmathsetmacro{\Dx}{ 2.0}
\pgfmathsetmacro{\Dy}{ 0.5}
\pgfmathsetmacro{\Ex}{ 0.0}
\pgfmathsetmacro{\Ey}{-1.5}
\pgfmathsetmacro{\Fx}{-0.4}
\pgfmathsetmacro{\Fy}{-2.0}
\pgfmathsetmacro{\Gx}{-2.3}
\pgfmathsetmacro{\Gy}{-0.3}
\begin{axis}[ymin=-3,ymax=3,xmax=3,xmin=-3,
% equal axis,
minor tick num=1,
xlabel={$U$}, xlabel style={at={(axis description cs:0.5,+0.02)}},
ylabel={$I$}, ylabel style={at={(axis description cs:0.1,0.5)}},
anchor=center, at={(0,0)},
axis equal image,clip=false,
]
% CV with beziers
\draw[thick, fg-blue] (axis cs:\Ax,\Ay) coordinate (A) node[left] {A}
..controls (axis cs:\Ax+1.8, \Ay+0.0) and (axis cs:\Bx-0.2, \By-0.4) .. (axis cs:\Bx,\By) coordinate (B) node[left] {B}
..controls (axis cs:\Bx+0.1, \By+0.2) and (axis cs:\Cx-0.3, \Cy+0.0) .. (axis cs:\Cx,\Cy) coordinate (C) node[above] {C}
..controls (axis cs:\Cx+0.5, \Cy+0.0) and (axis cs:\Dx-1.3, \Dy+0.1) .. (axis cs:\Dx,\Dy) coordinate (D) node[right] {D}
..controls (axis cs:\Dx-2.0, \Dy-0.1) and (axis cs:\Ex+0.3, \Ey+0.8) .. (axis cs:\Ex,\Ey) coordinate (E) node[right] {E}
..controls (axis cs:\Ex-0.1, \Ey-0.2) and (axis cs:\Fx+0.2, \Fy+0.0) .. (axis cs:\Fx,\Fy) coordinate (F) node[below] {F}
..controls (axis cs:\Fx-0.2, \Fy+0.0) and (axis cs:\Gx+1.5, \Gy-0.2) .. (axis cs:\Gx,\Gy) coordinate (G) node[left] {G};
\node[above] at (A) {\rightarrow};
\end{axis}
\end{tikzpicture}
\begin{minipage}{0.44\textwidth}
\begin{tikzpicture}
\pgfmathsetmacro{\Ax}{-2.3}
\pgfmathsetmacro{\Ay}{ 0.0}
\pgfmathsetmacro{\Bx}{ 0.0}
\pgfmathsetmacro{\By}{ 1.0}
\pgfmathsetmacro{\Cx}{ 0.4}
\pgfmathsetmacro{\Cy}{ 1.5}
\pgfmathsetmacro{\Dx}{ 2.0}
\pgfmathsetmacro{\Dy}{ 0.5}
\pgfmathsetmacro{\Ex}{ 0.0}
\pgfmathsetmacro{\Ey}{-1.5}
\pgfmathsetmacro{\Fx}{-0.4}
\pgfmathsetmacro{\Fy}{-2.0}
\pgfmathsetmacro{\Gx}{-2.3}
\pgfmathsetmacro{\Gy}{-0.3}
\pgfmathsetmacro{\x}{3}
\pgfmathsetmacro{\y}{3}
\begin{axis}[ymin=-\y,ymax=\y,xmax=\x,xmin=-\x,
% equal axis,
minor tick num=1,
xlabel={$E$}, xlabel style={at={(axis description cs:0.5,-0.06)}},
ylabel={$j$}, ylabel style={at={(axis description cs:-0.06,0.5)}},
anchor=center, at={(0,0)},
axis equal image,clip=false,
]
% CV with beziers
\draw[thick, fg-blue] (axis cs:\Ax,\Ay) coordinate (A) node[left] {A}
..controls (axis cs:\Ax+1.8, \Ay+0.0) and (axis cs:\Bx-0.2, \By-0.4) .. (axis cs:\Bx,\By) coordinate (B) node[left] {B}
..controls (axis cs:\Bx+0.1, \By+0.2) and (axis cs:\Cx-0.3, \Cy+0.0) .. (axis cs:\Cx,\Cy) coordinate (C) node[above] {C}
..controls (axis cs:\Cx+0.5, \Cy+0.0) and (axis cs:\Dx-1.3, \Dy+0.1) .. (axis cs:\Dx,\Dy) coordinate (D) node[right] {D}
..controls (axis cs:\Dx-2.0, \Dy-0.1) and (axis cs:\Ex+0.3, \Ey+0.8) .. (axis cs:\Ex,\Ey) coordinate (E) node[right] {E}
..controls (axis cs:\Ex-0.1, \Ey-0.2) and (axis cs:\Fx+0.2, \Fy+0.0) .. (axis cs:\Fx,\Fy) coordinate (F) node[below] {F}
..controls (axis cs:\Fx-0.2, \Fy+0.0) and (axis cs:\Gx+1.5, \Gy-0.2) .. (axis cs:\Gx,\Gy) coordinate (G) node[left] {G};
\node[above] at (A) {\rightarrow};
\draw[dashed, fg2] (axis cs: \Bx,\By) -- (axis cs: \Ex, \Ey);
\draw[->] (axis cs:-\x-0.6, 0.4) -- (axis cs:-\x-0.6, \y) node[left=0.3cm, anchor=east, rotate=90] {Cath / Red};
\draw[->] (axis cs:-\x-0.6,-0.4) -- (axis cs:-\x-0.6,-\y) node[left=0.3cm, anchor=west, rotate=90] {An / Ox};
\end{axis}
\end{tikzpicture}
\end{minipage}
\begin{minipage}{0.55\textwidth}
\begin{ttext}
\eng{\begin{itemize}
\item {\color{fg-blue}A-D}: Diffusion layer growth \rightarrow decreased current after peak
\item {\color{fg-blue}D}: Switching potential
\item {\color{fg-blue}B,E}: Equal concentrations of reactants
\item {\color{fg-blue}C,F}: Formal potential of redox pair: $E \approx \frac{E_\txC - E_\txF}{2}$
\item {\color{fg-blue}C,F}: Peak separation for reverisble processes: $\Delta E_\text{rev} = E_\txC - E_\txF = n\,\SI{59}{\milli\volt}$
\item Information about surface chemistry
\item Double-layer capacity (horizontal lines): $I = C v$
\end{itemize}}
\end{ttext}
\end{minipage}
\end{bigformula}
\begin{formula}{peak_current}
\desc{Randles-Sevcik equation}{For reversible reaction.\\Peak current depends on square root of the scan rate}{$n$ \qtyRef{charge_number}, \ConstRef{faraday}, $A$ electrode surface area, $c^0$ bulk \qtyRef{concentration}, $v$ \qtyRef{scan_rate}, $D_\text{ox}$ \qtyRef{diffusion_coefficient} of oxidized analyte, \ConstRef{universal_gas}, \QtyRef{temperature}}
\desc[german]{Randles-Sevcik Gleichung}{Spitzenstrom}{}
\eq{i_\text{peak} = 0.446\,nFAc^0 \sqrt{\frac{nFvD_\text{ox}}{RT}}}
\end{formula}
\begin{hiddenformula}{scan_rate}
\desc{Scan rate}{}{}
\desc[german]{Scanrate}{}{}
\quantity{v}{\volt\per\s}{s}
\end{hiddenformula}
\begin{formula}{upd}
\desc{Underpotential deposition (UPD)}{}{}
\desc[german]{}{}{}
@ -483,7 +554,7 @@
\Subsubsection[
\eng{Rotating disk electrodes}
% \ger{}
]{rde}
]{rde} \abbrLink{rde}{RDE}
\begin{formula}{viscosity}
\desc{Dynamic viscosity}{}{}
\desc[german]{Dynamisch Viskosität}{}{}
@ -504,8 +575,9 @@
\end{formula}
\begin{formula}{limiting_current}
\desc{Limiting current}{}{$n$ \QtyRef{charge_number}, \ConstRef{faraday}, $c^0$ \GT{c_bulk}, $D$ \qtyRef{diffusion_coefficient}, $\delta_\text{diff}$ \secEqRef{diffusion_layer_thickness}, $\nu$ \qtyRef{kinematic_viscosity}, \QtyRef{angular_frequency}}
\desc{Limiting current density}{for a \abbrRef{rde}}{$n$ \QtyRef{charge_number}, \ConstRef{faraday}, $c^0$ \GT{c_bulk}, $D$ \qtyRef{diffusion_coefficient}, $\delta_\text{diff}$ \secEqRef{diffusion_layer_thickness}, $\nu$ \qtyRef{kinematic_viscosity}, \QtyRef{angular_frequency}}
% \desc[german]{Limitierender Strom}{}{}
\eq{j^\infty = nFD \frac{c^0}{\delta_\text{diff}} = \frac{1}{1.61} nFD^{\frac{2}{3}} v^{\frac{-1}{6}} c^0 \sqrt{\omega}}
\eq{j_\infty = nFD \frac{c^0}{\delta_\text{diff}} = \frac{1}{1.61} nFD^{\frac{2}{3}} v^{\frac{-1}{6}} c^0 \sqrt{\omega}}
\end{formula}

View File

@ -90,18 +90,26 @@
\end{formula}
\Eng[cyanide]{Cyanide}
\Ger[cyanide]{Zyanid}
\Eng[ammonia]{Ammonia}
\Ger[ammonia]{Ammoniak}
\begin{formula}{common_chemicals}
\desc{Common chemicals}{}{}
\desc[german]{Häufige Chemikalien}{}{}
\begin{tabular}{l|c}
\GT{name} & \GT{formula} \\ \hline\hline
\GT{cyanide} & \ce{CN} \\ \hline
\GT{ammonia} & \ce{NH3}
\GT{name} & \GT{formula} \\ \hline\hline
\begin{ttext}[cyanide]\eng{Cyanide}\ger{Zyanid}\end{ttext} & \ce{CN} \\ \hline
\begin{ttext}[ammonia]\eng{Ammonia}\ger{Ammoniak}\end{ttext} & \ce{NH3} \\ \hline
\begin{ttext}[hydrogen peroxide]\eng{Hydrogen Peroxide}\ger{Wasserstoffperoxid}\end{ttext} & \ce{H2O2} \\ \hline
\begin{ttext}[sulfuric acid]\eng{Sulfuric Acid}\ger{Schwefelsäure}\end{ttext} & \ce{H2SO4} \\ \hline
\begin{ttext}[ethanol]\eng{Ethanol}\ger{Ethanol}\end{ttext} & \ce{C2H5OH} \\ \hline
\begin{ttext}[acetic acid]\eng{Acetic Acid}\ger{Essigsäure}\end{ttext} & \ce{CH3COOH} \\ \hline
\begin{ttext}[methane]\eng{Methane}\ger{Methan}\end{ttext} & \ce{CH4} \\ \hline
\begin{ttext}[hydrochloric acid]\eng{Hydrochloric Acid}\ger{Salzsäure}\end{ttext} & \ce{HCl} \\ \hline
\begin{ttext}[sodium hydroxide]\eng{Sodium Hydroxide}\ger{Natriumhydroxid}\end{ttext} & \ce{NaOH} \\ \hline
\begin{ttext}[nitric acid]\eng{Nitric Acid}\ger{Salpetersäure}\end{ttext} & \ce{HNO3} \\ \hline
\begin{ttext}[calcium carbonate]\eng{Calcium Carbonate}\ger{Calciumcarbonat}\end{ttext} & \ce{CaCO3} \\ \hline
\begin{ttext}[glucose]\eng{Glucose}\ger{Glukose}\end{ttext} & \ce{C6H12O6} \\ \hline
\begin{ttext}[benzene]\eng{Benzene}\ger{Benzol}\end{ttext} & \ce{C6H6} \\ \hline
\begin{ttext}[acetone]\eng{Acetone}\ger{Aceton}\end{ttext} & \ce{C3H6O} \\ \hline
\begin{ttext}[ethylene]\eng{Ethylene}\ger{Ethylen}\end{ttext} & \ce{C2H4} \\ \hline
\begin{ttext}[potassium permanganate]\eng{Potassium Permanganate}\ger{Kaliumpermanganat}\end{ttext} & \ce{KMnO4} \\ \hline
\end{tabular}
\end{formula}

View File

@ -279,7 +279,7 @@
\ttxt{\eng{
\begin{itemize}
\item Use empirical interaction potential instead of electronic structure
\baditem Force fields need to be fitted for specific material \Rightarrorw not transferable
\baditem Force fields need to be fitted for specific material \Rightarrow not transferable
\gooditem Faster than \abbrRef{bomd}
\item Example: \absRef{lennard_jones}
\end{itemize}

View File

@ -8,7 +8,7 @@
]{models}
\begin{formula}{heg}
\desc{Homogeneous electron gas (HEG)}{Also "Jellium"}{}
\desc[german]{}{}{}
% \desc[german]{}{}{}
\ttxt{
\eng{Both positive (nucleus) and negative (electron) charges are distributed uniformly.}
}

View File

@ -45,3 +45,10 @@
}
\end{formula}
\begin{formula}{charge}
\desc{Unit charge}{}{}
\desc[german]{Elementarladung}{}{}
\constant{e}{def}{
\val{1.602176634\xE{-19}}{\coulomb}
}
\end{formula}

View File

@ -2,7 +2,7 @@
% (for vimtex)
\documentclass[11pt, a4paper]{article}
% SET LANGUAGE HERE
\usepackage[english]{babel}
\usepackage[german]{babel}
\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}
% ENVIRONMENTS etc
\usepackage{adjustbox}
@ -31,11 +31,6 @@
\usepackage{array} % more array options
\newcolumntype{C}{>{$}c<{$}} % math-mode version of "c" column type
% \usepackage{sectsty}
% TRANSLATION
\usepackage{translations}
\input{util/translation.tex}
\input{util/colorscheme.tex}
\input{util/colors.tex} % after colorscheme
% GRAPHICS
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
@ -74,6 +69,7 @@
\sisetup{separate-uncertainty}
\sisetup{per-mode = power}
\sisetup{exponent-product=\ensuremath{\cdot}}
% DEBUG
% \usepackage{lua-visual-debug}
% DUMB STUFF
@ -88,46 +84,12 @@
% \def\nu{\temoji{unicorn}}
% \def\mu{\temoji{mouse}}
\newcommand{\TODO}[1]{{\color{fg-red}TODO:#1}}
\newcommand{\ts}{\textsuperscript}
% \usepackage{xstring}
% LUA sutff
\newcommand\luavar[1]{\directlua{tex.sprint(#1)}}
\directlua{
function string.startswith(s, start)
return string.sub(s,1,string.len(start)) == start
end
}
% Write directlua command to aux and run it as well
% This one expands the argument in the aux file:
\newcommand\directLuaAuxExpand[1]{
\immediate\write\luaAuxFile{\noexpand\directlua{#1}}
\directlua{#1}
}
% This one does not:
\newcommand\directLuaAux[1]{
\immediate\write\luaAuxFile{\noexpand\directlua{\detokenize{#1}}}
\directlua{#1}
}
% read
\IfFileExists{\jobname.lua.aux}{%
\input{\jobname.lua.aux}%
}{%
% \@latex@warning@no@line{"Lua aux not loaded!"}
}
\def\luaAuxLoaded{False}
% write
\newwrite\luaAuxFile
\immediate\openout\luaAuxFile=\jobname.lua.aux
\immediate\write\luaAuxFile{\noexpand\def\noexpand\luaAuxLoaded{True}}%
\AtEndDocument{\immediate\closeout\luaAuxFile}
% Create a text file with relevant labels for vim-completion
\newwrite\labelsFile
@ -137,14 +99,21 @@
}
\AtEndDocument{\immediate\closeout\labelsFile}
\input{util/fqname.tex}
\input{circuit.tex}
\input{util/macros.tex}
\input{util/environments.tex} % requires util/translation.tex to be loaded first
\input{util/periodic_table.tex} % requires util/translation.tex to be loaded first
\usepackage{pkg/mqlua}
\usepackage{pkg/mqfqname}
% TRANSLATION
% \usepackage{translations}
\usepackage{pkg/mqtranslation}
\input{util/colorscheme.tex}
\input{util/colors.tex} % after colorscheme
\usepackage{pkg/mqconstant}
\usepackage{pkg/mqquantity}
\usepackage{pkg/mqformula}
\usepackage{pkg/mqperiodictable}
% INPUT
% 1: starting pattern of files to input using the Input command. All other files are ignored
@ -159,7 +128,6 @@
}
}
\title{Formelsammlung}
\author{Matthias Quintern}
\date{\today}
@ -168,12 +136,6 @@
\input{\jobname.translations.aux}
}{}
\def\translationsAuxLoaded{False}
\newwrite\translationsaux
\immediate\openout\translationsaux=\jobname.translations.aux
\immediate\write\translationsaux{\noexpand\def\noexpand\translationsAuxLoaded{True}}%
\AtEndDocument{\immediate\closeout\translationsaux}
\makeatletter\let\percentchar\@percentchar\makeatother
\maketitle
@ -183,7 +145,7 @@
\input{util/translations.tex}
% \InputOnly{comp}
% \InputOnly{ch}
\Input{math/math}
\Input{math/linalg}
@ -215,7 +177,6 @@
\Input{cm/topo}
\Input{cm/mat}
\Input{particle}
\Input{quantum_computing}
@ -253,7 +214,7 @@
]{elements}
\printAllElements
\newpage
\Input{test}
% \Input{test}
% \bibliographystyle{plain}
% \bibliography{ref}

View File

@ -96,7 +96,8 @@
\Subsection[
\eng{Misc}
\ger{Misc}
]{misc}
\begin{formula}{normal_equation}

62
src/pkg/mqconstant.sty Normal file
View File

@ -0,0 +1,62 @@
\ProvidesPackage{mqconstant}
\RequirePackage{mqlua}
\RequirePackage{etoolbox}
\directLuaAux{
if constants == nil then
constants = {}
end
}
% [1]: label to point to
% 2: key
% 3: symbol
% 4: either exp or def; experimentally or defined constant
\newcommand{\constant@new}[4][\relax]{
\directLuaAux{
constants["#2"] = {}
constants["#2"]["symbol"] = [[\detokenize{#3}]]
constants["#2"]["exp_or_def"] = [[\detokenize{#4}]]
constants["#2"]["values"] = {} %-- array of {value, unit}
}
\ifstrempty{#1}{}{
\directLuaAuxExpand{
constants["#2"]["linkto"] = [[#1]] %-- fqname required for getting the translation key
}
}
}
% 1: key
% 2: value
% 3: units
\newcommand{\constant@addValue}[3]{
\directlua{
table.insert(constants["#1"]["values"], { value = [[\detokenize{#2}]], unit = [[\detokenize{#3}]] })
}
}
% 1: key
\newcommand\constant@print[1]{
\begingroup % for label
Symbol: $\luavar{constants["#1"]["symbol"]}$
% \\Unit: $\directlua{split_and_print_units(constants["#1"]["units"])}$
\directlua{
tex.print("\\\\\\GT{const:"..constants["#1"]["exp_or_def"].."}")
}
\directlua{
%--tex.sprint("Hier steht Luatext" .. ":", #constVals)
for i, pair in ipairs(constants["#1"]["values"]) do
tex.sprint("\\\\\\hspace*{1cm}${", pair["value"], "}\\,\\si{", pair["unit"], "}$")
%--tex.sprint("VALUE ", i, v)
end
}
% label it only once
\directlua{
if constants["#1"]["labeled"] == nil then
constants["#1"]["labeled"] = true
tex.print("\\label{const:#1}")
end
}
\endgroup
}
\newcounter{constant}

250
src/pkg/mqformula.sty Normal file
View File

@ -0,0 +1,250 @@
\ProvidesPackage{mqformula}
\RequirePackage{mqfqname}
\RequirePackage{mqconstant}
\RequirePackage{mqquantity}
%
% FORMULA ENVIRONMENT
% The following commands are meant to be used with the formula environment
%
% Name in black and below description in gray
% [1]: minipage width
% 2: fqname of name
% 3: fqname of a translation that holds the explanation
\newcommand{\NameWithDescription}[3][\descwidth]{
\begin{minipage}{#1}
\IfTranslationExists{#2}{
\raggedright
\GT{#2}
}{\detokenize{#2}}
\IfTranslationExists{#3}{
\\ {\color{fg1} \GT{#3}}
}{}
\end{minipage}
}
% TODO: rename
\newsavebox{\contentBoxBox}
% [1]: minipage width
% 2: fqname of a translation that holds the explanation
\newenvironment{ContentBoxWithExplanation}[2][\eqwidth]{
\def\ContentFqName{#2}
\begin{lrbox}{\contentBoxBox}
\begin{minipage}{#1}
}{
\IfTranslationExists{\ContentFqName}{%
\smartnewline
\noindent
\begingroup
\color{fg1}
\GT{\ContentFqName}
% \edef\temp{\GT{#1_defs}}
% \expandafter\StrSubstitute\expandafter{\temp}{:}{\\}
\endgroup
}{}
\end{minipage}
\end{lrbox}
\fbox{\usebox{\contentBoxBox}}
}
% Class defining commands shared by all formula environments
% 1: key
\newenvironment{formulainternal}[1]{
% [1]: language
% 2: name
% 3: description
% 4: definitions/links
\newcommand{\desc}[4][english]{
% language, name, description, definitions
\ifblank{##2}{}{\dt[#1]{##1}{##2}}
\ifblank{##3}{}{\dt[#1_desc]{##1}{##3}}
\ifblank{##4}{}{\dt[#1_defs]{##1}{##4}}
}
\directlua{n_formulaEntries = 0}
% makes this formula referencable with \abbrRef{<name>}
% [1]: label to use
% 2: Abbreviation to use for references
\newcommand{\abbrLabel}[2][#1]{
\abbrLink[f:\fqname]{##1}{##2}
}
% makes this formula referencable with \absRef{<name>}
% [1]: label to use
\newcommand{\absLabel}[1][#1]{
\absLink[f:\fqname]{##1}
}
\newcommand{\newFormulaEntry}{
\directlua{
if n_formulaEntries > 0 then
tex.print("\\vspace{0.3\\baselineskip}\\hrule\\vspace{0.3\\baselineskip}")
end
n_formulaEntries = n_formulaEntries + 1
}
% \par\noindent\ignorespaces
}
% 1: equation for align environment
\newcommand{\eq}[1]{
\newFormulaEntry
\begin{align}
% \label{eq:\fqname:#1}
##1
\end{align}
}
% 1: equation for alignat environment
\newcommand{\eqAlignedAt}[2]{
\newFormulaEntry
\begin{flalign}%
\TODO{\text{remove macro}}
% dont place label when one is provided
% \IfSubStringInString{label}\unexpanded{#3}{}{
% \label{eq:#1}
% }
##1%
\end{flalign}
}
% 1: equation for flalign environment
\newcommand{\eqFLAlign}[2]{
\newFormulaEntry
\begin{alignat}{##1}%
% dont place label when one is provided
% \IfSubStringInString{label}\unexpanded{#3}{}{
% \label{eq:#1}
% }
##2%
\end{alignat}
}
\newcommand{\fig}[2][1.0]{
\newFormulaEntry
\centering
\includegraphics[width=##1\textwidth]{##2}
}
% 1: content for the ttext environment
\newcommand{\ttxt}[2][#1:desc]{
\newFormulaEntry
\begin{ttext}[##1]
##2
\end{ttext}
}
% 1: symbol
% 2: units
% 3: comment key to translation
\newcommand{\quantity}[3]{%
\quantity@new[\fqname]{#1}{##1}{##2}{##3}
\newFormulaEntry
\quantity@print{#1}
}
% must be used only in third argument of "constant" command
% 1: value
% 2: unit
\newcommand{\val}[2]{
\constant@addValue{#1}{##1}{##2}
}
% 1: symbol
% 2: either exp or def; experimentally or defined constant
% 3: one or more \val{value}{unit} commands
\newcommand{\constant}[3]{
\constant@new[\fqname]{#1}{##1}{##2}
\begingroup
##3
\endgroup
\newFormulaEntry
\constant@print{#1}
}
}{}
\newenvironment{formula}[1]{
\begin{formulainternal}{#1}
\begingroup
\label{f:\fqname:#1}
\storeLabel{\fqname:#1}
\par\noindent\ignorespaces
% \textcolor{gray}{\hrule}
% \vspace{0.5\baselineskip}
\NameWithDescription[\descwidth]{\fqname:#1}{\fqname:#1_desc}
\hfill
\begin{ContentBoxWithExplanation}{\fqname:#1_defs}
}{
\end{ContentBoxWithExplanation}
\endgroup
\separateEntries
% \textcolor{fg3}{\hrule}
% \vspace{0.5\baselineskip}
\ignorespacesafterend
\end{formulainternal}
}
% BIG FORMULA
\newenvironment{bigformula}[1]{
\begin{formulainternal}{#1}
\edef\tmpFormulaName{#1}
\par\noindent
\begin{minipage}{\textwidth} % using a minipage to now allow line breaks within the bigformula
\label{f:\fqname:#1}
\par\noindent\ignorespaces
% \textcolor{gray}{\hrule}
% \vspace{0.5\baselineskip}
\textbf{
\IfTranslationExists{\fqname:#1}{%
\raggedright
\GT{\fqname:#1}
}{\detokenize{#1}}
}
\IfTranslationExists{\fqname:#1_desc}{
: {\color{fg1} \GT{\fqname:#1_desc}}
}{}
\hfill
\par
}{
\edef\tmpContentDefs{\fqname:\tmpFormulaName_defs}
\IfTranslationExists{\tmpContentDefs}{%
\smartnewline
\noindent
\begingroup
\color{fg1}
\GT{\tmpContentDefs}
% \edef\temp{\GT{#1_defs}}
% \expandafter\StrSubstitute\expandafter{\temp}{:}{\\}
\endgroup
}{}
\end{minipage}
\separateEntries
% \textcolor{fg3}{\hrule}
% \vspace{0.5\baselineskip}
\ignorespacesafterend
\end{formulainternal}
}
\newenvironment{hiddenformula}[1]{
\begin{formulainternal}{#1}
\renewcommand{\eq}[1]{}
\renewcommand{\eqAlignedAt}[2]{}
\renewcommand{\eqFLAlign}[2]{}
\renewcommand{\fig}[2][1.0]{}
\renewcommand{\ttxt}[2][#1:desc]{}
% 1: symbol
% 2: units
% 3: comment key to translation
\renewcommand{\quantity}[3]{%
\quantity@new[\fqname]{#1}{##1}{##2}{##3}
}
% 1: symbol
% 2: either exp or def; experimentally or defined constant
% 3: one or more \val{value}{unit} commands
\renewcommand{\constant}[3]{
\constant@new[\fqname]{#1}{##1}{##2}
\begingroup
##3
\endgroup
}
}{
\end{formulainternal}
}

209
src/pkg/mqfqname.sty Normal file
View File

@ -0,0 +1,209 @@
\ProvidesPackage{mqfqname}
\RequirePackage{mqlua}
\RequirePackage{etoolbox}
\directlua{
sections = sections or {}
function fqnameEnter(name)
table.insert(sections, name)
% table.sort(sections)
end
function fqnameLeave()
if table.getn(sections) > 0 then
table.remove(sections)
end
end
function fqnameGet()
return table.concat(sections, ":")
end
function fqnameLeaveOnlyFirstN(n)
if n >= 0 then
while table.getn(sections) > n do
table.remove(sections)
end
end
end
}
\newcommand{\mqfqname@update}{%
\edef\fqname{\luavar{fqnameGet()}}
}
\newcommand{\mqfqname@enter}[1]{%
\directlua{fqnameEnter("\luaescapestring{#1}")}%
\mqfqname@update
}
\newcommand{\mqfqname@leave}{%
\directlua{fqnameLeave()}%
\mqfqname@update
}
\newcommand{\mqfqname@leaveOnlyFirstN}[1]{%
\directlua{fqnameLeaveOnlyFirstN(#1)}%
}
% SECTIONING
% start <section>, get heading from translation, set label
% secFqname is the fully qualified name of sections: the keys of all previous sections joined with a ':'
% fqname is secFqname:<key> where <key> is the key/id of some environment, like formula
% [1]: code to run after setting \fqname, but before the \part, \section etc
% 2: key
\newcommand{\Part}[2][desc]{
\newpage
\mqfqname@leaveOnlyFirstN{0}
\mqfqname@enter{#2}
\edef\secFqname{\fqname}
#1
% this is necessary so that \part/\section... takes the fully expanded string. Otherwise the pdf toc will have just the fqname
\edef\fqnameText{\GT{\fqname}}
\part{\fqnameText}
\label{sec:\fqname}
}
\newcommand{\Section}[2][]{
\mqfqname@leaveOnlyFirstN{1}
\mqfqname@enter{#2}
\edef\secFqname{\fqname}
#1
\edef\fqnameText{\GT{\fqname}}
\section{\fqnameText}
\label{sec:\fqname}
}
\newcommand{\Subsection}[2][]{
\mqfqname@leaveOnlyFirstN{2}
\mqfqname@enter{#2}
\edef\secFqname{\fqname}
#1
\edef\fqnameText{\GT{\fqname}}
\subsection{\fqnameText}
\label{sec:\fqname}
}
\newcommand{\Subsubsection}[2][]{
\mqfqname@leaveOnlyFirstN{3}
\mqfqname@enter{#2}
\edef\secFqname{\fqname}
#1
\edef\fqnameText{\GT{\fqname}}
\subsubsection{\fqnameText}
\label{sec:\fqname}
}
\edef\fqname{NULL}
\newcommand\printFqName{\expandafter\detokenize\expandafter{\fqname}}
\newcommand\luaDoubleFieldValue[3]{%
\directlua{
if #1 \string~= nil and #1[#2] \string~= nil and #1[#2][#3] \string~= nil then
tex.sprint(#1[#2][#3])
return
end
luatexbase.module_warning('luaDoubleFieldValue', 'Invalid indices to `#1`: `#2` and `#3`');
tex.sprint("???")
}%
}
% REFERENCES
% All xyzRef commands link to the key using the translated name
% Uppercase (XyzRef) commands have different link texts, but the same link target
% 1: key/fully qualified name (without qty/eq/sec/const/el... prefix)
% Equations/Formulas
% \newrobustcmd{\fqEqRef}[1]{%
\newrobustcmd{\fqEqRef}[1]{%
% \edef\fqeqrefname{\GT{#1}}
% \hyperref[eq:#1]{\fqeqrefname}
\hyperref[f:#1]{\GT{#1}}%
}
% Formula in the current section
\newrobustcmd{\secEqRef}[1]{%
% \edef\fqeqrefname{\GT{#1}}
% \hyperref[eq:#1]{\fqeqrefname}
\hyperref[f:\secFqname:#1]{\GT{\secFqname:#1}}%
}
% Section
% <name>
\newrobustcmd{\fqSecRef}[1]{%
\hyperref[sec:#1]{\GT{#1}}%
}
% Quantities
% <symbol>
\newrobustcmd{\qtyRef}[1]{%
\edef\tempname{\luaDoubleFieldValue{quantities}{"#1"}{"linkto"}}%
\hyperref[qty:#1]{\expandafter\GT\expandafter{\tempname:#1}}%
}
% <symbol> <name>
\newrobustcmd{\QtyRef}[1]{%
$\luaDoubleFieldValue{quantities}{"#1"}{"symbol"}$ \qtyRef{#1}%
}
% Constants
% <name>
\newrobustcmd{\constRef}[1]{%
\edef\tempname{\luaDoubleFieldValue{constants}{"#1"}{"linkto"}}%
\hyperref[const:#1]{\expandafter\GT\expandafter{\tempname:#1}}%
}
% <symbol> <name>
\newrobustcmd{\ConstRef}[1]{%
$\luaDoubleFieldValue{constants}{"#1"}{"symbol"}$ \constRef{#1}%
}
% Element from periodic table
% <symbol>
\newrobustcmd{\elRef}[1]{%
\hyperref[el:#1]{{\color{fg0}#1}}%
}
% <name>
\newrobustcmd{\ElRef}[1]{%
\hyperref[el:#1]{\GT{el:#1}}%
}
% "LABELS"
% These currently do not place a label,
% instead they provide an alternative way to reference an existing label
\directLuaAux{
absLabels = absLabels or {}
abbrLabels = abbrLabel or {}
}
% [1]: target (fqname to point to)
% 2: key
\newcommand{\absLink}[2][sec:\fqname]{
\directLuaAuxExpand{
absLabels["#2"] = [[#1]]
}
}
% [1]: target (fqname to point to)
% 2: key
% 3: label (abbreviation)
\newcommand{\abbrLink}[3][sec:\fqname]{
\directLuaAuxExpand{
abbrLabels["#2"] = {}
abbrLabels["#2"]["abbr"] = [[#3]]
abbrLabels["#2"]["fqname"] = [[#1]]
}
}
% [1]:
\newrobustcmd{\absRef}[2][\relax]{%
\directlua{
if absLabels["#2"] == nil then
tex.sprint("\\detokenize{#2}???")
else
if "#1" == "" then %-- if [#1] is not given, use translation of key as text, else us given text
tex.sprint("\\hyperref[" .. absLabels["#2"] .. "]{\\GT{" .. absLabels["#2"] .. "}}")
else
tex.sprint("\\hyperref[" .. absLabels["#2"] .. "]{\luaescapestring{#1}}")
end
end
}
}
\newrobustcmd{\abbrRef}[1]{%
\directlua{
if abbrLabels["#1"] == nil then
tex.sprint("\\detokenize{#1}???")
else
tex.sprint("\\hyperref[" .. abbrLabels["#1"]["fqname"] .. "]{" .. abbrLabels["#1"]["abbr"] .. "}")
end
}
}

88
src/pkg/mqlua.sty Normal file
View File

@ -0,0 +1,88 @@
\ProvidesPackage{mqlua}
\RequirePackage{luacode}
\LuaCodeDebugOn
\newcommand\luavar[1]{\directlua{tex.sprint(#1)}}
\begin{luacode*}
function warning(message)
-- Get the current file name and line number
-- local info = debug.getinfo(2, "Sl")
-- local file_name = info.source
-- local line_number = info.currentline
-- tex.error(string.format("Warning %s at %s:%d", message, file_name, line_number))
texio.write("\nWARNING: " .. message .. "\n")
end
OUTDIR = os.getenv("TEXMF_OUTPUT_DIRECTORY") or "."
function fileExists(file)
local f = io.open(file, "rb")
if f then f:close() end
return f ~= nil
end
warning("TEST")
\end{luacode*}
% units: siunitx units arguments, possibly chained by '='
% returns: 1\si{unit1} = 1\si{unit2} = ...
\directlua{
function split_and_print_units(units)
if units == nil then
tex.print("1")
return
end
local parts = {}
for part in string.gmatch(units, "[^=]+") do
table.insert(parts, part)
end
local result = ""
for i, unit in ipairs(parts) do
if i > 1 then result = result .. " = " end
result = result .. "\\SI{1}{" .. unit .. "}"
end
tex.print(result)
end
}
% STRING UTILITY
\luadirect{
function string.startswith(s, start)
return string.sub(s,1,string.len(start)) == start
end
function string.sanitize(s)
% -- Use gsub to replace the specified characters with an empty string
local result = s:gsub("[_^&]", "")
return result
end
}
% Write directlua command to aux and run it as well
% This one expands the argument in the aux file:
\newcommand\directLuaAuxExpand[1]{
\immediate\write\luaAuxFile{\noexpand\directlua{#1}}
\directlua{#1}
}
% This one does not:
\newcommand\directLuaAux[1]{
\immediate\write\luaAuxFile{\noexpand\directlua{\detokenize{#1}}}
\directlua{#1}
}
% read
\IfFileExists{\jobname.lua.aux}{%
\input{\jobname.lua.aux}%
}{%
% \@latex@warning@no@line{"Lua aux not loaded!"}
}
\def\luaAuxLoaded{False}
% write
\newwrite\luaAuxFile
\immediate\openout\luaAuxFile=\jobname.lua.aux
\immediate\write\luaAuxFile{\noexpand\def\noexpand\luaAuxLoaded{True}}%
\AtEndDocument{\immediate\closeout\luaAuxFile}

View File

@ -1,3 +1,6 @@
\ProvidesPackage{mqperiodictable}
\RequirePackage{mqtranslation}
\RequirePackage{mqlua}
% Store info about elements in a lua table
% Print as list or as periodic table
% The data is taken from https://pse-info.de/de/data as json and parsed by the scripts/periodic_table.py
@ -164,7 +167,4 @@
end
}
\end{tikzpicture}
}

43
src/pkg/mqquantity.sty Normal file
View File

@ -0,0 +1,43 @@
\ProvidesPackage{mqquantity}
\RequirePackage{mqlua}
\RequirePackage{etoolbox}
\directLuaAux{
if quantities == nil then
quantities = {}
end
}
% [1]: label to point to
% 2: key - must expand to a valid lua string!
% 3: symbol
% 4: units
% 5: comment key to translation
\newcommand{\quantity@new}[5][\relax]{%
\directLuaAux{
quantities["#2"] = {}
quantities["#2"]["symbol"] = [[\detokenize{#3}]]
quantities["#2"]["units"] = [[\detokenize{#4}]]
quantities["#2"]["comment"] = [[\detokenize{#5}]]
}
\ifstrempty{#1}{}{
\directLuaAuxExpand{
quantities["#2"]["linkto"] = [[#1]] %-- fqname required for getting the translation key
}
}
}
% 1: key
\newcommand\quantity@print[1]{
\begingroup % for label
Symbol: $\luavar{quantities["#1"]["symbol"]}$
\\Unit: $\directlua{split_and_print_units(quantities["#1"]["units"])}$
% label it only once
\directlua{
if quantities["#1"]["labeled"] == nil then
quantities["#1"]["labeled"] = true
tex.print("\\label{qty:#1}")
end
}
\endgroup
}

177
src/pkg/mqtranslation.sty Normal file
View File

@ -0,0 +1,177 @@
\ProvidesPackage{mqtranslation}
\RequirePackage{mqfqname}
\RequirePackage{etoolbox}
\RequirePackage{amsmath}
\RequirePackage{mqlua}
% TODO resolve circular dependency with fqname
\begin{luacode}
translations = translations or {}
-- string to append to missing translations
-- unknownTranslation = "???"
unknownTranslation = ""
language = "\languagename"
fallbackLanguage = "english"
-- using additional .aux extension because vimtex wouldnt stop compiling otherwise
translationsFilepath = OUTDIR .. "/translations.lua.aux" or "/tmp/translations.lua"
function tlAdd(language, key, value)
if value == "" then
return
end
if translations[language] == nil then
translations[language] = {}
end
translations[language][key] = value
end
function tlExists(language, key)
return not (translations[language] == nil or translations[language][key] == nil)
end
function tlExistsFallback(language, key)
if tlExists(language, key) then
return true
end
return tlExists(fallbackLanguage, key)
end
function tlGet(language, key)
if tlExists(language, key) then
return translations[language][key]
end
return string.sanitize(key .. unknownTranslation)
end
function tlGetFallback(language, key)
if tlExists(language, key) then
return translations[language][key]
end
if language ~= fallbackLanguage then
if tlExists(fallbackLanguage, key) then
return translations[fallbackLanguage][key]
end
end
return string.sanitize(key .. unknownTranslation)
end
function tlGetCurrent(key)
return tlGet(language, key)
end
function tlGetFallbackCurrent(key)
return tlGetFallback(language, key)
end
\end{luacode}
% Write the translations table as lua code to an auxiliary file
% If the file exists, read it when loading the package.
% This way, translations may be used before they are defined, since it will exist in the second compilation.
\begin{luacode*}
function serialize(tbl)
local result = {}
for k, v in pairs(tbl) do
local key = type(k) == "string" and ("[\"%s\"]"):format(k) or "[" .. tostring(k) .. "]"
-- using level 2 multiline string to avoid problems when a string ends with ]
local value = type(v) == "table" and serialize(v) or "[==[" .. tostring(v) .. "]==]"
table.insert(result, key .. " = " .. value)
end
return "{" .. table.concat(result, ",\n" ) .. "}\n"
end
function dumpTranslations()
local file = io.open(translationsFilepath, "w")
file:write("return " .. serialize(translations) .. "\n")
file:close()
end
if fileExists(translationsFilepath) then
translations = dofile(translationsFilepath) or {}
end
\end{luacode*}
\AtEndDocument{\directlua{dumpTranslations()}}
%
% TRANSLATION COMMANDS
%
% The lower case commands use \fqname based keys, the upper case absolute keys.
% Example:
% \dt[example]{german}{Beispiel} % defines the key \fqname:example
% \ger[example]{Beispiel} % defines the key \fqname:example
% \DT[example]{german}{Beispiel} % defines the key example
% \Ger[example]{Beispiel} % defines the key example
%
% For ease of use in the ttext environment and the optional argument of the \Part, \Section, ... commands,
% all "define translation" commands use \fqname as default key
% Get a translation
% expandafter required because the translation commands dont expand anything
% shortcuts for translations
% 1: key
\newcommand{\gt}[1]{\luavar{tlGetFallbackCurrent(\luastring{\fqname:#1})}}
\newrobustcmd{\robustGT}[1]{\luavar{tlGetFallbackCurrent(\luastring{#1})}}
\newcommand{\GT}[1]{\luavar{tlGetFallbackCurrent(\luastring{#1})}}
% text variants for use in math mode
\newcommand{\tgt}[1]{\text{\gt{#1}}}
\newcommand{\tGT}[1]{\text{\GT{#1}}}
% Define a new translation
% [1]: key, 2: lang, 3: translation
\newcommand{\dt}[3][\fqname]{%
\directlua{
if \luastring{#1} == \luastring{\fqname} then
tlAdd(\luastring{#2}, \luastring{\fqname}, \luastringN{#3})
else
tlAdd(\luastring{#2}, \luastring{\fqname:#1}, \luastringN{#3})
end
}
}
% Define a new translation
% [1]: key, 2: lang, 3: translation
\newcommand{\DT}[3][\fqname]{%
\directlua{
if \luastring{#1} == \luastring{\fqname} then
tlAdd(\luastring{#2}, \luastring{\fqname}, \luastringN{#3})
else
tlAdd(\luastring{#2}, \luastring{#1}, \luastringN{#3})
end
}
}
% [1]: key, 2: translation
\newcommand{\ger}[2][\fqname]{\dt[#1]{german}{#2}}
\newcommand{\eng}[2][\fqname]{\dt[#1]{english}{#2}}
\newcommand{\Ger}[2][\fqname]{\DT[#1]{german}{#2}}
\newcommand{\Eng}[2][\fqname]{\DT[#1]{english}{#2}}
\newcommand{\IfTranslationExists}[3]{%
\directlua{
if tlExistsFallback(language, \luastring{#1}) then
tex.sprint(\luastringN{#2})
else
tex.sprint(\luastringN{#3})
end
}
}
% use this to define text in different languages for the key <env arg>
% the translation for <env arg> is printed when the environment ends.
% (temporarily change fqname to the \fqname:<env arg> to allow
% the use of \eng and \ger without the key parameter)
% [1]: key
\newenvironment{ttext}[1][desc]{%
\mqfqname@enter{#1}%
}{%
\GT{\fqname}%
\mqfqname@leave%
}

View File

@ -82,6 +82,13 @@
\quantity{\tau}{\newton\m=\kg\m^2\per\s^2}{v}
\end{formula}
\begin{formula}{pressure}
\desc{Pressure}{}{}
\desc[german]{Druck}{}{}
\quantity{p}{\newtone\per\m^2}{}
\end{formula}
\Subsection[
\eng{Thermodynamics}
\ger{Thermodynamik}
@ -106,9 +113,10 @@
\desc[german]{Ladung}{}{}
\quantity{q}{\coulomb=\ampere\s}{}
\end{formula}
\begin{formula}{charge_number}
\desc{Charge number}{}{}
\desc[german]{ladungszahl}{Anzahl der Elementarladungen}{}
\desc[german]{Ladungszahl}{Anzahl der Elementarladungen}{}
\quantity{Z}{}{}
\end{formula}
\begin{formula}{charge_density}
@ -136,6 +144,12 @@
\eq{T = \frac{1}{f}}
\end{formula}
\begin{formula}{conductivity}
\desc{Conductivity}{}{}
\desc[german]{Leitfähigkeit}{}{}
\quantity{\sigma}{\per\ohm\m}{}
\end{formula}
\Subsection[
\eng{Others}
\ger{Sonstige}

View File

@ -22,8 +22,12 @@
\ger{Gates}
]{gates}
\begin{formula}{gates}
\desc{}{}{}
\desc[german]{}{}{}
\desc{Gates}{}{}
\desc[german]{Gates}{}{}
\eng[bitflip]{Bitflip}
\eng[bitphaseflip]{Bit-Phase flip}
\eng[phaseflip]{Phaseflip}
\eng[hadamard]{Hadamard}
\begin{alignat}{2}
& \text{\gt{bitflip}:} & \hat{X} &= \sigma_x = \sigmaxmatrix \\
& \text{\gt{bitphaseflip}:} & \hat{Y} &= \sigma_y = \sigmaymatrix \\
@ -456,7 +460,7 @@
\eq{\Gamma_1 = \frac{1}{T_1} = \Gamma_{1\uparrow} + \Gamma_{1\downarrow}}
\end{formula}
\begin{ttext}[long]
\begin{ttext}[longdesc]
\eng{$\Gamma_{1\uparrow}$ is supressed at low temperatures because of detailed balance}
\ger{$\Gamma_{1\uparrow}$ ist bei niedrigen Temperaturen unterdrückt wegen detailed balance}
\end{ttext}

View File

@ -1,17 +1,24 @@
\part{Testing}
% \directlua{tex.sprint("Compiled in directory: \\detokenize{" .. lfs.currentdir() .. "}")} \\
% \directlua{tex.sprint("Jobname: " .. tex.jobname)} \\
% \directlua{tex.sprint("Output directory \\detokenize{" .. os.getenv("TEXMF_OUTPUT_DIRECTORY") .. "}")} \\
% \directlua{tex.sprint("String sanitize \\detokenize{" .. string.sanitize("m_a^th?") .. "}")}
\languagename
\paragraph{File loading}
\noindent Lua Aux loaded? \luaAuxLoaded\\
Translations Aux loaded? \translationsAuxLoaded\\
% Translations Aux loaded? \translationsAuxLoaded\\
Input only: \inputOnlyFile
\paragraph{Testing GT, GetTranslation, IfTranslationExists, IfTranslation}
\addtranslation{english}{ttest}{This is the english translation of \texttt{ttest}}
\noindent
GT: ttest = \GT{ttest}\\
GetTranslation: ttest = \GetTranslation{ttest}\\
Is english? = \IfTranslation{english}{ttest}{yes}{no} \\
Is german? = \IfTranslation{german}{ttest}{yes}{no} \\
% GetTranslation: ttest = \GetTranslation{ttest}\\
% Is english? = \IfTranslation{english}{ttest}{yes}{no} \\
% Is german? = \IfTranslation{german}{ttest}{yes}{no} \\
Is defined = \IfTranslationExists{ttest}{yes}{no} \\
\paragraph{Testing translation keys containing macros}
@ -24,11 +31,11 @@ Is defined = \IfTranslationExists{ttest}{yes}{no} \\
\DT[\ttest:name]{german}{DT Mit Variable}
\noindent
GT: {\textbackslash}ttest:name = \GT{\ttest:name}\\
GetTranslation: {\textbackslash}ttest:name = \GetTranslation{\ttest:name}\\
Is english? = \IfTranslation{english}{\ttest:name}{yes}{no} \\
Is german? = \IfTranslation{german}{\ttest:name}{yes}{no} \\
Is defined? = \IfTranslationExists{\ttest:name}{yes}{no} \\
Is defined? = \expandafter\IfTranslationExists\expandafter{\ttest:name}{yes}{no}
% GetTranslation: {\textbackslash}ttest:name = \GetTranslation{\ttest:name}\\
% Is english? = \IfTranslation{english}{\ttest:name}{yes}{no} \\
% Is german? = \IfTranslation{german}{\ttest:name}{yes}{no} \\
% Is defined? = \IfTranslationExists{\ttest:name}{yes}{no} \\
% Is defined? = \expandafter\IfTranslationExists\expandafter{\ttest:name}{yes}{no}
\paragraph{Testing relative translations}
\begingroup

View File

@ -1,28 +1,38 @@
% This file was generated by scripts/formulary.py
% Do not edit it directly, changes will be overwritten
\definecolor{fg0}{HTML}{1d2021}
\definecolor{bg0}{HTML}{f9f5d7}
\definecolor{fg1}{HTML}{3c3836}
\definecolor{fg2}{HTML}{504945}
\definecolor{fg3}{HTML}{665c54}
\definecolor{fg4}{HTML}{7c6f64}
\definecolor{bg1}{HTML}{ebdbb2}
\definecolor{bg2}{HTML}{d5c4a1}
\definecolor{bg3}{HTML}{bdae93}
\definecolor{bg4}{HTML}{a89984}
\definecolor{fg-red}{HTML}{9d0006}
\definecolor{fg-orange}{HTML}{af3a03}
\definecolor{fg-yellow}{HTML}{b57614}
\definecolor{fg-green}{HTML}{79740e}
\definecolor{fg-blue}{HTML}{072140}
\definecolor{bg-blue}{HTML}{5E94D4}
\definecolor{alt-blue}{HTML}{3070B3}
\definecolor{bg-yellow}{HTML}{FED702}
\definecolor{fg-yellow}{HTML}{CBAB01}
\definecolor{alt-yellow}{HTML}{FEDE34}
\definecolor{bg-orange}{HTML}{F7811E}
\definecolor{fg-orange}{HTML}{D99208}
\definecolor{alt-orange}{HTML}{F9BF4E}
\definecolor{bg-purple}{HTML}{B55CA5}
\definecolor{fg-purple}{HTML}{9B468D}
\definecolor{alt-purple}{HTML}{C680BB}
\definecolor{bg-red}{HTML}{EA7237}
\definecolor{fg-red}{HTML}{D95117}
\definecolor{alt-red}{HTML}{EF9067}
\definecolor{bg-green}{HTML}{9FBA36}
\definecolor{fg-green}{HTML}{7D922A}
\definecolor{alt-green}{HTML}{B6CE55}
\definecolor{bg-gray}{HTML}{475058}
\definecolor{fg-gray}{HTML}{20252A}
\definecolor{alt-gray}{HTML}{333A41}
\definecolor{bg-aqua}{HTML}{689d6a}
\definecolor{fg-aqua}{HTML}{427b58}
\definecolor{fg-blue}{HTML}{076678}
\definecolor{fg-purple}{HTML}{8f3f71}
\definecolor{fg-gray}{HTML}{7c6f64}
\definecolor{bg-red}{HTML}{fb4934}
\definecolor{bg-orange}{HTML}{f38019}
\definecolor{bg-yellow}{HTML}{fabd2f}
\definecolor{bg-green}{HTML}{b8bb26}
\definecolor{bg-aqua}{HTML}{8ec07c}
\definecolor{bg-blue}{HTML}{83a598}
\definecolor{bg-purple}{HTML}{d3869b}
\definecolor{bg-gray}{HTML}{a89984}
\definecolor{fg0-hard}{HTML}{000000}
\definecolor{fg0}{HTML}{000000}
\definecolor{fg0-soft}{HTML}{20252A}
\definecolor{fg1}{HTML}{072140}
\definecolor{fg2}{HTML}{333A41}
\definecolor{fg3}{HTML}{475058}
\definecolor{fg4}{HTML}{6A757E}
\definecolor{bg0-hard}{HTML}{FFFFFF}
\definecolor{bg0}{HTML}{FBF9FA}
\definecolor{bg0-soft}{HTML}{EBECEF}
\definecolor{bg1}{HTML}{DDE2E6}
\definecolor{bg2}{HTML}{E3EEFA}
\definecolor{bg3}{HTML}{F0F5FA}

View File

@ -1,17 +1,3 @@
% use this to define text in different languages for the key <env arg>
% the translation for <env arg> is printed when the environment ends.
% (temporarily change fqname to the \fqname:<env arg> to allow
% the use of \eng and \ger without the key parameter)
% [1]: key
\newenvironment{ttext}[1][desc]{
\edef\realfqname{\fqname}
\edef\fqname{\fqname:#1}
}{
\expandafter\GT\expandafter{\fqname}% \\
\edef\fqname{\realfqname}
}
\def\descwidth{0.3\textwidth}
\def\eqwidth{0.6\textwidth}
@ -22,336 +8,6 @@
}
%
% FORMULA ENVIRONMENT
% The following commands are meant to be used with the formula environment
%
% Name in black and below description in gray
% [1]: minipage width
% 2: fqname of name
% 3: fqname of a translation that holds the explanation
\newcommand{\NameWithDescription}[3][\descwidth]{
\begin{minipage}{#1}
\IfTranslationExists{#2}{
\raggedright
\GT{#2}
}{\detokenize{#2}}
\IfTranslationExists{#3}{
\\ {\color{fg1} \GT{#3}}
}{}
\end{minipage}
}
% TODO: rename
\newsavebox{\contentBoxBox}
% [1]: minipage width
% 2: fqname of a translation that holds the explanation
\newenvironment{ContentBoxWithExplanation}[2][\eqwidth]{
\def\ContentFqName{#2}
\begin{lrbox}{\contentBoxBox}
\begin{minipage}{#1}
}{
\IfTranslationExists{\ContentFqName}{%
\smartnewline
\noindent
\begingroup
\color{fg1}
\GT{\ContentFqName}
% \edef\temp{\GT{#1_defs}}
% \expandafter\StrSubstitute\expandafter{\temp}{:}{\\}
\endgroup
}{}
\end{minipage}
\end{lrbox}
\fbox{\usebox{\contentBoxBox}}
}
\newenvironment{formula}[1]{
% [1]: language
% 2: name
% 3: description
% 4: definitions/links
\newcommand{\desc}[4][english]{
% language, name, description, definitions
\ifblank{##2}{}{\dt[#1]{##1}{##2}}
\ifblank{##3}{}{\dt[#1_desc]{##1}{##3}}
\ifblank{##4}{}{\dt[#1_defs]{##1}{##4}}
}
\directlua{n_formulaEntries = 0}
% makes this formula referencable with \abbrRef{<name>}
% [1]: label to use
% 2: Abbreviation to use for references
\newcommand{\abbrLabel}[2][#1]{
\abbrLink[f:\fqname]{##1}{##2}
}
% makes this formula referencable with \absRef{<name>}
% [1]: label to use
\newcommand{\absLabel}[1][#1]{
\absLink[f:\fqname]{##1}
}
\newcommand{\newFormulaEntry}{
\directlua{
if n_formulaEntries > 0 then
tex.print("\\vspace{0.3\\baselineskip}\\hrule\\vspace{0.3\\baselineskip}")
end
n_formulaEntries = n_formulaEntries + 1
}
% \par\noindent\ignorespaces
}
% 1: equation for align environment
\newcommand{\eq}[1]{
\newFormulaEntry
\begin{align}
% \label{eq:\fqname:#1}
##1
\end{align}
}
% 1: equation for alignat environment
\newcommand{\eqAlignedAt}[2]{
\newFormulaEntry
\begin{flalign}%
\TODO{\text{remove macro}}
% dont place label when one is provided
% \IfSubStringInString{label}\unexpanded{#3}{}{
% \label{eq:#1}
% }
##1%
\end{flalign}
}
% 1: equation for flalign environment
\newcommand{\eqFLAlign}[2]{
\newFormulaEntry
\begin{alignat}{##1}%
% dont place label when one is provided
% \IfSubStringInString{label}\unexpanded{#3}{}{
% \label{eq:#1}
% }
##2%
\end{alignat}
}
\newcommand{\fig}[2][1.0]{
\newFormulaEntry
\centering
\includegraphics[width=##1\textwidth]{##2}
}
% 1: content for the ttext environment
\newcommand{\ttxt}[2][#1:desc]{
\newFormulaEntry
\begin{ttext}[##1]
##2
\end{ttext}
}
% 1: key - must expand to a valid lua string!
% 2: symbol
% 3: units
% 4: comment key to translation
\newcommand{\quantity}[3]{%
\directLuaAux{
quantities["#1"] = {}
quantities["#1"]["symbol"] = [[\detokenize{##1}]]
quantities["#1"]["units"] = [[\detokenize{##2}]]
quantities["#1"]["comment"] = [[\detokenize{##3}]]
}\directLuaAuxExpand{
quantities["#1"]["fqname"] = [[\fqname]] %-- fqname required for getting the translation key
}
\newFormulaEntry
\printQuantity{#1}
}
% must be used only in third argument of "constant" command
% 1: value
% 2: unit
\newcommand{\val}[2]{
\directLuaAux{
table.insert(constants["#1"]["values"], { value = [[\detokenize{##1}]], unit = [[\detokenize{##2}]] })
}
}
% 1: symbol
% 2: either exp or def; experimentally or defined constant
% 3: one or more \val{value}{unit} commands
\newcommand{\constant}[3]{
\directLuaAux{
constants["#1"] = {}
constants["#1"]["symbol"] = [[\detokenize{##1}]]
constants["#1"]["exp_or_def"] = [[\detokenize{##2}]]
constants["#1"]["values"] = {} %-- array of {value, unit}
}\directLuaAuxExpand{
constants["#1"]["fqname"] = [[\fqname]] %-- fqname required for getting the translation key
}
\begingroup
##3
\endgroup
\newFormulaEntry
\printConstant{#1}
}
\begingroup
\label{f:\fqname:#1}
\storeLabel{\fqname:#1}
\par\noindent\ignorespaces
% \textcolor{gray}{\hrule}
% \vspace{0.5\baselineskip}
\NameWithDescription[\descwidth]{\fqname:#1}{\fqname:#1_desc}
\hfill
\begin{ContentBoxWithExplanation}{\fqname:#1_defs}
}{
\end{ContentBoxWithExplanation}
\endgroup
\separateEntries
% \textcolor{fg3}{\hrule}
% \vspace{0.5\baselineskip}
\ignorespacesafterend
}
% BIG FORMULA
\newenvironment{bigformula}[1]{
% [1]: language
% 2: name
% 3: description
% 4: definitions/links
\newcommand{\desc}[4][english]{
% language, name, description, definitions
\ifblank{##2}{}{\dt[#1]{##1}{##2}}
\ifblank{##3}{}{\dt[#1_desc]{##1}{##3}}
\ifblank{##4}{}{\dt[#1_defs]{##1}{##4}}
}
\directlua{n_formulaEntries = 0}
\newcommand{\newFormulaEntry}{
\directlua{
if n_formulaEntries > 0 then
tex.print("\\vspace{0.3\\baselineskip}\\hrule\\vspace{0.3\\baselineskip}")
end
n_formulaEntries = n_formulaEntries + 1
}
% \par\noindent\ignorespaces
}
% 1: equation for align environment
\edef\tmpFormulaName{#1}
\par\noindent
\begin{minipage}{\textwidth} % using a minipage to now allow line breaks within the bigformula
\label{f:\fqname:#1}
\par\noindent\ignorespaces
% \textcolor{gray}{\hrule}
% \vspace{0.5\baselineskip}
\textbf{
\IfTranslationExists{\fqname:#1}{%
\raggedright
\GT{\fqname:#1}
}{\detokenize{#1}}
}
\IfTranslationExists{\fqname:#1_desc}{
: {\color{fg1} \GT{\fqname:#1_desc}}
}{}
\hfill
\par
}{
\edef\tmpContentDefs{\fqname:\tmpFormulaName_defs}
\IfTranslationExists{\tmpContentDefs}{%
\smartnewline
\noindent
\begingroup
\color{fg1}
\GT{\tmpContentDefs}
% \edef\temp{\GT{#1_defs}}
% \expandafter\StrSubstitute\expandafter{\temp}{:}{\\}
\endgroup
}{}
\end{minipage}
\separateEntries
% \textcolor{fg3}{\hrule}
% \vspace{0.5\baselineskip}
\ignorespacesafterend
}
%
% QUANTITY
%
% units: siunitx units arguments, possibly chained by '='
% returns: 1\si{unit1} = 1\si{unit2} = ...
\directlua{
function split_and_print_units(units)
if units == nil then
tex.print("1")
return
end
local parts = {}
for part in string.gmatch(units, "[^=]+") do
table.insert(parts, part)
end
local result = ""
for i, unit in ipairs(parts) do
if i > 1 then result = result .. " = " end
result = result .. "\\SI{1}{" .. unit .. "}"
end
tex.print(result)
end
}
% % for TOC
% \refstepcounter{constant}%
% % \addquantity{\expandafter\gt\expandafter{\qtyname}}%
% % \noindent\textbf{My Environment \themyenv: #1}\par%
% }
\directLuaAux{
if constants == nil then
constants = {}
end
}
\newcommand\printConstant[1]{
\begingroup % for label
Symbol: $\luavar{constants["#1"]["symbol"]}$
% \\Unit: $\directlua{split_and_print_units(constants["#1"]["units"])}$
\directlua{
tex.print("\\\\\\GT{const:"..constants["#1"]["exp_or_def"].."}")
}
\directlua{
%--tex.sprint("Hier steht Luatext" .. ":", #constVals)
for i, pair in ipairs(constants["#1"]["values"]) do
tex.sprint("\\\\\\hspace*{1cm}${", pair["value"], "}\\,\\si{", pair["unit"], "}$")
%--tex.sprint("VALUE ", i, v)
end
}
% label it only once
\directlua{
if constants["#1"]["labeled"] == nil then
constants["#1"]["labeled"] = true
tex.print("\\label{const:#1}")
end
}
\endgroup
}
\newcounter{constant}
\directLuaAux{
if quantities == nil then
quantities = {}
end
}
\newcommand\printQuantity[1]{
\begingroup % for label
Symbol: $\luavar{quantities["#1"]["symbol"]}$
\\Unit: $\directlua{split_and_print_units(quantities["#1"]["units"])}$
% label it only once
\directlua{
if quantities["#1"]["labeled"] == nil then
quantities["#1"]["labeled"] = true
tex.print("\\label{qty:#1}")
end
}
\endgroup
}
% Custon environment with table of contents, requires etoolbox?
% Define a custom list

View File

@ -1,102 +0,0 @@
%
% TRANSLATION COMMANDS
%
% The lower case commands use \fqname based keys, the upper case absolute keys.
% Example:
% \dt[example]{german}{Beispiel} % defines the key \fqname:example
% \ger[example]{Beispiel} % defines the key \fqname:example
% \DT[example]{german}{Beispiel} % defines the key example
% \Ger[example]{Beispiel} % defines the key example
%
% For ease of use in the ttext environment and the optional argument of the \Part, \Section, ... commands,
% all "define translation" commands use \fqname as default key
% Get a translation
% expandafter required because the translation commands dont expand anything
% shortcuts for translations
% 1: key
\newcommand{\IfTranslationExists}[1]{%
% only check english. All translations must be defined for english
\def\tempiftranslation{\IfTranslation{english}}%
\expandafter\tempiftranslation\expandafter{#1}%
}
\newcommand{\iftranslation}[1]{%
\IfTranslation{english}{\fqname:#1}
% \expandafter\IfTranslationExists\expandafter{\fqname:#1}
}
\newrobustcmd{\robustGt}[1]{%
\IfTranslationExists{\fqname:#1}{%
\expandafter\GetTranslation\expandafter{\fqname:#1}%
}{%
\printFqName:\detokenize{#1}%
}%
}
\newcommand{\gt}[1]{%
\IfTranslationExists{\fqname:#1}{%
\expandafter\GetTranslation\expandafter{\fqname:#1}%
}{%
\printFqName:\detokenize{#1}%
}%
}
\newrobustcmd{\GT}[1]{%\expandafter\GetTranslation\expandafter{#1}}
\IfTranslationExists{#1}{%
\expandafter\GetTranslation\expandafter{#1}%
}{% ??
\detokenize{#1}%
}%
}
% text variants for use in math mode
\newcommand{\tgt}[1]{\text{\gt{#1}}}
\newcommand{\tGT}[1]{\text{\GT{#1}}}
% Define a translation and also make the fallback if it is the english translation
% 1: lang, 2: key, 3: translation
\newcommand{\addtranslationcustom}[3]{
\ifstrequal{#1}{english}{
\addtranslationfallback{#2}{#3}
\immediate\write\translationsaux{\noexpand\addtranslationfallback{#2}{\detokenize{#3}}}
% \immediate\write\translationsaux{\noexpand\addtranslationfallback{#2}{{#3}}}%
}{}
\immediate\write\translationsaux{\noexpand\addtranslation{#1}{#2}{\detokenize{#3}}}
\addtranslation{#1}{#2}{#3}
}
% Define a new translation
% [1]: key, 2: lang, 3: translation
\newcommand{\dt}[3][\fqname]{
\ifstrempty{#3}{}{ % dont add empty translations so that the fallback will be used instead
% hack because using expandafter on the second arg didnt work
\def\tempaddtranslation{\addtranslationcustom{#2}}
\ifstrequal{#1}{\fqname}{
% \expandafter\tempaddtranslation\expandafter{\fqname}{#3}
\addtranslationcustom{#2}{#1}{#3}
}{
\addtranslationcustom{#2}{\fqname:#1}{#3}
% \expandafter\tempaddtranslation\expandafter{\fqname:#1}{#3}
}
}
}
% Define a new translation
% [1]: key, 2: lang, 3: translation
\newcommand{\DT}[3][dummy]{
\ifstrempty{#3}{}{ % dont add empty translations so that the fallback will be used instead
% hack because using expandafter on the second arg didnt work
\def\tempaddtranslation{\addtranslationcustom{#2}}
\ifstrequal{#1}{dummy}{
% \expandafter\tempaddtranslation\expandafter{\fqname}{#3}
\addtranslationcustom{#2}{\fqname}{#3}
}{
% \expandafter\tempaddtranslation\expandafter{#1}{#3}
\addtranslationcustom{#2}{#1}{#3}
}
}
}
% [1]: key, 2: translation
\newcommand{\ger}[2][\fqname]{\dt[#1]{german}{#2}}
\newcommand{\eng}[2][\fqname]{\dt[#1]{english}{#2}}
\newcommand{\Ger}[2][\fqname]{\DT[#1]{german}{#2}}
\newcommand{\Eng}[2][\fqname]{\DT[#1]{english}{#2}}