Posts tagged ‘LaTeX’

Neue Version des varsfromjobname Pakets

Letzten Montag habe ich die neue Version meines varsfromjobname Pakets auf CTAN hochgeladen, es gibt auch ein Github Repo dazu: https://github.com/UweZiegenhagen/VarsFromJobname

What does this package do?

Using varsfromjobname.sty one can easily extract information from the filename, if it follows a certain form.

The standard LaTeX command \jobname returns the name of the LaTeX (master) file. If the filename consists of tokens separated by hyphen we can easily extract certain tokens that can be used inside the document.

The package expects the filename to be of the form one-two-three-four-five-six-seven-eight-nine.tex and offers the following commands:


\getfromjobname{param}, with param in the range of 1 to 9 (a highlevel interface to the following commands)

\getonefromjobname
\gettwofromjobname
\getthreefromjobname
\getfourfromjobname
\getfivefromjobname
\getsixfromjobname
\getsevenfromjobname
\geteightfromjobname
\getninefromjobname

Why can it be useful?

You can use this package for example to define the date of the document in the filename, personally I use it e.g. for scrlttr2 letters.

Change History

  • Version 0.5, as of January 11th 2009: Initial version published
  • Version 1.0, to be published May 2017: Added various commands which extract necessary information also from included documents. Modified code as suggested by egreg

Shortcomings

  • \getfromjobname is not fully expandable, use one of the other commands if you need expansion
  • Version 1.0 cannot extract information from included sub-documents
  • The package cannot handle more than nine tokens, see the reference to egreg’s answer on TSX below for an updated version

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Generating a normal distribution table with SciPy

Here’s a simple example how one can generate a normal distribution table with Python and scipy so that it can be imported into LaTeX.

Example-03.zip

# -*- coding: utf-8 -*-
"""
Created on Mon Mar 13 21:14:17 2017
@author: Uwe Ziegenhagen, ziegenhagen@gmail.com
 
Creates a CDF table for the standard normal distribution
 
use booktabs package in the preamble and put 
the generated numbers inside (use only one backslash!)
 
\\begin{tabular}{r|cccccccccc} \\toprule
<output here>
\\end{tabular}
"""
 
from scipy.stats import norm
 
print(norm.pdf(0))
print(norm.cdf(0),'\r\n')
 
horizontal = range(0,10,1)
vertikal = range(0,37)
 
header = ''
for i in horizontal:
    header = header + '& ' + str(i/100)
 
print(header, '\\\\ \\midrule')
 
for j in vertikal:  
    x = j/10
    print('\\\\', x)
    for i in horizontal:
        y = x + i/100
        print('& ', "{:10.4f}".format(norm.cdf(y),4))
 
 
print('\\\\ \\bottomrule \r\n')

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

LaTeX-Dateien vergleich mit latexdiff

latexdiff ist Bestandteil von TeX Live und erlaubt es, die Unterschiede zwischen zwei LaTeX-Dateien hervorzuheben. Hier ein Beispiel mit einem kurzen Textschnipsel aus der Wikipedia:

Das Original (Giraffe1.tex)

\documentclass[12pt,ngerman]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{csquotes}
\begin{document}
 
Die Giraffen (Giraffa) sind eine Gattung der Säugetiere aus der Ordnung der Paarhufer. Ursprünglich wurden ihr mit Giraffa camelopardalis und der Trivialbezeichnung \enquote{Giraffe} nur eine einzige Art zugewiesen. Molekulargenetische Untersuchungen aus dem Jahr 2016 zeigen jedoch, dass die Gattung wenigstens vier Arten mit sieben eigenständigen Populationen umfasst. Die Giraffen stellen die höchsten landlebenden Tiere der Welt. Zur Unterscheidung vom verwandten Okapi (sogenannte \enquote{Waldgiraffe}) werden sie auch als Steppengiraffen bezeichnet.
 
\end{document}

Eine Version mit leichten Änderungen (Giraffe2.tex)

\documentclass[12pt,ngerman]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{csquotes}
\begin{document}
 
Die Giraffen (Giraffa) sind eine Gattung der Säugetiere aus der Ordnung der Paarhufer. Ursprünglich wurden ihr mit Giraffa camelopardalis und der Trivialbezeichnung \enquote{Giraffe} nur eine einzige Art zugewiesen. Untersuchungen aus dem Jahr 2016 zeigten jedoch, dass die Gattung wenigstens 4 Arten mit 7 eigenständigen Populationen umfasst. Die Giraffen stellen die höchsten landlebenden Tiere der Welt. Zur Unterscheidung vom verwandten Okapi (der sogenannten \enquote{Waldgiraffe}) werden sie auch als Steppengiraffen bezeichnet.
 
\end{document}

Auf der Kommandozeile ruft man jetzt auf latexdiff Giraffe1.tex Giraffe2.tex > Giraffediff.tex und übersetzt die neu erzeugte Datei nach PDF, das dann wie folgt aussieht:

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Plots mit pgfplots

Hier ein kleines Beispiel für pgfplots, das ich aus diversen TSX Beiträgen für einen Python Artikel zusammengebaut habe:

\documentclass[12pt,english]{standalone}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\pagestyle{empty}
 
\begin{document}
\begin{tikzpicture}
\begin{axis}[
    domain=0:9,
    axis lines = center,
    xlabel = {$x$},
    ylabel = {$y = f(x)$},
    height=8cm, width=11cm, grid=major,grid style={dashed, gray!30},
    xmin=-1, xmax=10, ymin=-1, ymax=7,xtick={1,2,...,10},ytick={1,2,...,6}]
 
\addplot[draw=red,domain=0:8]{-0.5*x+4};
\addplot[draw=blue,domain=1:3]{-3*x+9};
\end{axis}
\end{tikzpicture}
\end{document}

pff

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Parallel LaTeXing with Python Threads

Based on an example from stackexchange I have created a small example on parallel TeX compilation.

# -*- coding: utf-8 -*-
"""
Created on 2016-07-06
Uwe Ziegenhagen
based on http://stackoverflow.com/questions/16181121/python-very-simple-multithreading-parallel-url-fetching-without-queue
"""
 
from multiprocessing.pool import ThreadPool
from time import time as timer
import os
 
files = ['test-01.tex','test-02.tex','test-03.tex','test-04.tex','test-05.tex',
'test-06.tex','test-07.tex','test-08.tex','test-09.tex','test-10.tex']
 
def compile_file(cfile):
	try:
		result = os.system('pdflatex -interaction=batchmode ' + cfile)
		return cfile, None
	except Exception as e:
		return cfile, e	
 
start = timer()
results = ThreadPool(8).imap_unordered(compile_file, files)
for cfile, error in results:
	if error is None:
		print("%r compiled in %ss" % (cfile, timer() - start))
	else:
		print("Error compiling %r: %s" % (cfile, error))
		print("Elapsed Time: %s" % (timer() - start,))
 
print('Gesamtzeit',timer() - start)

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Das „Currentfile“ Paket

Hier ein Beispiel für das currentfile Paket. Während \jobname auch bei eingebundenen Dateien nur den Namen der Hauptdatei ausspuckt, kann man mit den Befehlen des currentfile Pakets auf die einzelnen Dateien zugreifen.

\documentclass{scrartcl}
\usepackage{filecontents}
\usepackage{currfile}
 
\begin{filecontents}{curr02.tex}
 
Ich bin der Inhalt einer Datei, die eingebunden wird. \verb|\jobname| enthält: \jobname
 
	\begin{itemize}
		\item \verb|\currfilebase|: \currfilebase
		\item \verb|\currfilename|: \currfilename
		\item \verb|\currfileext|: \currfileext
		\item \verb|\currfiledir|: \currfiledir
		\item \verb|\currfilepath|: \currfilepath
	\end{itemize}
 
\end{filecontents}
 
\begin{document}
 
	\begin{itemize}
		\item \verb|\currfilebase|: \currfilebase
		\item \verb|\currfilename|: \currfilename
		\item \verb|\currfileext|: \currfileext
		\item \verb|\currfiledir|: \currfiledir
		\item \verb|\currfilepath|: \currfilepath
	\end{itemize}
 
\input{curr02}
 
\end{document}

currfile

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Vortragsfolien „Klausurerstellung mit LaTeX“, Dante-Frühjahrstagung in Wuppertal

Hier meine Folien zum Vortrag in Wuppertal, zusammen mit den entsprechenden Quellen (auch für die Beamer Folien)

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Schnittmarken mit LaTeX entfernen

Vor ein paar Tagen wollte ich die Schnittmarken in einer PDF Datei entfernen. Da ich kein Adobe Acrobat oder einen ähnlichen PDF Editor habe, habe ich LaTeX genutzt. Nützlich ist die Fähigkeit des pdfpages Pakets, direkt beim Import eines PDF festzulegen, wie jede Seite zu croppen ist. Der trim Parameter bekommt dabei vier Maße übergeben, die für links unten rechts oben (left bottom right top) stehen.

\documentclass{scrartcl}
\usepackage{pdfpages}
\begin{document}
 
\includepdf[scale=1,pages=1-48,clip,trim=50mm 55mm 45mm 55mm]{Booklet.pdf}
 
\end{document}

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Spendenbescheinigungen erstellen mit LaTeX und pandas

Nach Buchungen auswerten mit Python Pandas hier der zweite Artikel zum Thema pandas.

Ausgangspunkt bilden die Formulare der Finanzdirektion, die ich in LaTeX umgesetzt habe; ihr findet sie unter https://github.com/UweZiegenhagen/spendenquittungen-mit-latex.

Wenn man dieses Formular mit entsprechenden Jinja2 Variablen anreichert (dazu später mehr), erhält man Sammelbestaetigung_Geldzuwendung (PDF) (TeX Code)

Die Aufgabe, die sich jetzt für das automatische Befüllen mittels pandas stellt, ist die folgende:

  1. Lies die Stammdaten ein und bereite sie auf
  2. Lies die Buchungen (aus Quicken 2015) ein und bereite sie auf
  3. Befüll das entsprechende LaTeX-Template
  4. Erzeuge die fertige PDF Datei

Hier der Quellcode nebst Erläuterung:

  • jinja2 nutzen wir als Template-Engine, os für die pdflatex-Aufrufe, codecs für ein wenig UTF8-Gewusel
  • cleanPLZ und prepareAddress sind einfache Hilfsfunktionen. Die erste reinigt die PLZ (pandas nimmt an, das hier Floats drinstehen), die zweite erzeugt den Adressstring für die Ausgabe
  • kardinal erzeugt das Zahlwort, siehe dazu den verlinkten Beitrag vom Finanzamt.
  • Richtig los geht es ab „##################### Prepare Stammdaten #####################“:
    • Ich lade die Stammdaten in einen Dataframe und ersetzte fehlende Werte durch “
    • Die PLZ wird bereinigt (geht sicher auch einfacher), ehemalige Mitglieder (mit Status ‚E‘) werden entfernt
    • Die Buchungen werden geladen, fehlende Werte durch 0 bzw. “ ersetzt.
    • Relevant sind nur Buchungstypen wie Mitgliedsbeitrag und Aufnahmegebühr, alles andere wird entfernt.
    • Die Jinja2 Komponente wird konfiguriert
    • Für jeden Stammdatensatz werden die Stammdaten aufbereitet und die Buchungen eingesammelt.
    • Ein wenig Python/pandas Magie bereitet die daten auf und schreibt alles in das Template
    • Dieses Template wird dann in eine TeX Datei geschrieben und nach PDF übersetzt.

Hier der Link zur Zip-Datei mit allen benötigten Dateien: AlleDateien

Update vom 18.01.2021: Der Python-Code in der Datei hat nicht mehr funktioniert. In der folgenden Datei daher das Code-Update.

prepareSpenden-04

import pandas as pd # pandas selbst
 
import jinja2
import os
import codecs
 
def cleanPLZ(stringToClean):
    return stringToClean.replace('.0','')
 
# Eine Funktion, die die Adresse vorbereitet
# keine überflüssigen Leerzeichen, wenn Feld nicht gefüllt ist
def prepareAddress(id, vorname, name, strasse, plz, ort):
    address = '' # + str(id) + ': '
    if len(vorname)==0:
        address = address + name
    else:
        address = address + vorname + ' ' + name
    if len(strasse)>0:
        address = address + ", " + strasse    
    if len(plz)>0:
        address = address + ", " + plz + ' ' + ort
    return address
 
# Zerlege die Gesamtsumme in einzelne Bestandteile, um Zahlwort auszugeben
# Siehe http://www.steuer-schutzbrief.de/fileadmin/downloads/BMF-Schreiben/BMF-Schreiben-Zuwendungsbestaetigung-2012-08-30.pdf
def kardinal(summenstring,separator,indicator):
	zahlen = {"1" : "Eins", "2":"Zwei", "3":"Drei", "4":"Vier","5":"Fünf","6":"Sechs","7":"Sieben","8":"Acht","9":"Neun","0":"Null"}
	zahlwort = ''
	zahl = summenstring.split(',')[0]
	for i in zahl:
		zahlwort = zahlwort + zahlen[i]+ separator
	return indicator + separator + zahlwort + indicator
 
# Diverse Konfigurationsvariablen
# http://chrisalbon.com/python/pandas_list_unique_values_in_column.html
# Set ipython's max row display
pd.set_option('display.max_row', 10000)
# Set iPython's max column width to 50
pd.set_option('display.max_columns', 50)
# A set number format to 2 digits
pd.set_option('display.float_format', lambda x: '%.2f' % x)
# http://stackoverflow.com/questions/20625582/how-to-deal-with-this-pandas-warning
# komische Fehlermeldung beim Drop von Spalten loswerden
pd.options.mode.chained_assignment = None  # default='warn'
 
##################### Prepare Stammdaten ##################### 
# lade Daten
stammdaten = pd.read_excel('Stammdaten.xlsx', 'Tabelle1')
 
# Remove NaN values by " for strings
stammdaten['Vorname'].fillna(value='',inplace=True)
stammdaten['Name'].fillna(value='',inplace=True)
stammdaten['Adresszusatz'].fillna(value='',inplace=True)
stammdaten['Strasse'].fillna(value='',inplace=True)
stammdaten['PLZ'].fillna(value='',inplace=True)
stammdaten['Ort'].fillna(value='',inplace=True)
stammdaten['eMail'].fillna(value='',inplace=True)
stammdaten['Mitgliedsart'].fillna(value='',inplace=True)
 
# convert PLZ to string
# apply str function first, then run cleanPLZ on the string
stammdaten['PLZ']= stammdaten.PLZ.apply(str)
stammdaten['PLZ']= stammdaten.PLZ.apply(cleanPLZ)
 
# entferne ehemalige Mitglieder
stammdaten  = stammdaten[stammdaten.Mitgliedsart != 'E']
 
################################ Prepare Buchungen
# lade die Buchungen
buchungen = pd.read_excel('Buchungen.xlsx', 'Tabelle1')
buchungen[['Klasse']] = buchungen[['Klasse']].astype(str)
buchungen[['Betrag']] = buchungen[['Betrag']].astype(float)
 
# Change format of 'Buchungstag' to datetime
buchungen['Buchungstag'] = pd.to_datetime(buchungen['Buchungstag'],dayfirst=True)
 
# Remove NaN values by " for strings or 0 for numbers 
buchungen['Vorgang'].fillna(value=0,inplace=True)
buchungen['Empfänger'].fillna(value='',inplace=True)
buchungen['Verwendungszweck'].fillna(value='',inplace=True)
buchungen['Kategorie'].fillna(value='',inplace=True)
buchungen['Klasse'].fillna(value='',inplace=True)
buchungen['Relevant']=True
buchungen.Kategorie.str.match('^Aufnahmegebühr|Zweckspende|Mitgliedsbeitrag|Spende$')
 
# entferne irrelevante Buchungen
buchungen = buchungen[buchungen.Relevant != False]
 
# http://stackoverflow.com/questions/20937538/how-to-display-pandas-dataframe-using-a-format-string-for-columns
#pd.options.display.float_format = '{:,.2f} EUR'.format
 
class CommaFloatFormatter:
    def __mod__(self, x):
        return str(x).replace('.',',')
 
latex_jinja_env = jinja2.Environment(
    block_start_string = '\BLOCK{',
    block_end_string = '}',
    variable_start_string = '\VAR{',
    variable_end_string = '}',
    comment_start_string = '\#{',
    comment_end_string = '}',
    line_statement_prefix = '%-',
    line_comment_prefix = '%#',
    trim_blocks = True,
    autoescape = False,
    loader = jinja2.FileSystemLoader(os.path.abspath('.'))
)
 
# Laden des Templates aus einer Datei
template = latex_jinja_env.get_template('Sammelbestaetigung_Geldzuwendung.tex')
 
for index, row in stammdaten.iterrows():
    print("ID:",row["ID"])
    address = prepareAddress(row["ID"],row['Vorname'],row['Name'],row['Strasse'],row['PLZ'],row['Ort'])
    print(address)
    beitraege = buchungen[buchungen.Klasse.str.contains('^' +  str(row["ID"]) + '$')]
    beitraege.drop('Klasse',axis=1,inplace=True)
    beitraege.drop('Verwendungszweck',axis=1,inplace=True)
    beitraege.drop('Relevant',axis=1,inplace=True)
    beitraege.drop('Empfänger',axis=1,inplace=True)
    beitraege.drop('Konto',axis=1,inplace=True)
    beitraege.drop('Vorgang',axis=1,inplace=True)
    gesamtsumme = beitraege.sum()[0]
 
    beitraege['Buchungstag'] = beitraege['Buchungstag'].apply(lambda x: x.strftime('%d-%m-%Y'))
    texbuchungen = beitraege.applymap(lambda x: str(x).replace('.',',0')).to_latex(index=False)    
    texbuchungen = beitraege.to_latex(index=False)    
    summe = str(gesamtsumme).replace('.',',0') + ' EUR'
    # kardinal(summe,'-','xxx')
    dokument = template.render(Spender=address, ID=row['ID'],Summe=summe,kardinal=kardinal(summe,'-','xxx'),Buchungen=texbuchungen)
    with codecs.open(''+str(row['ID']) + ".tex", "w","utf-8") as letter:
        letter.write(dokument);
        letter.close();
        os.system("pdflatex -interaction=batchmode " + str(row['ID']) + ".tex")
 
os.system("del *.log")
os.system("del *.aux")

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

EPUBs erstellen mit tex4ebook

This entry is part 1 of 1 in the series EPUBs mit LaTeX

Es gibt ein relativ neues LaTeX-Paket zum Erzeugen von EPUBs aus LaTeX heraus, hier ein kurzes Beispiel:

\documentclass[ngerman]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{csquotes}
\usepackage{xcolor}
 
\title{Testdokument für tex4ebook}
\author{Uwe Ziegenhagen}
 
\begin{document}
\maketitle
\tableofcontents
 
\section{Hallo}
 
Hallo Welt
 
\section{Welt}
 
\end{document}

In diesem einfachen Beispiel hat das generierte EPUB noch Probleme:

  • Umlaute sind kaputt
  • Das Inhaltsverzeichnis befindet sich hinter dem eigentlichen Text

In den nächsten Artikeln werde ich schauen, was mit dem Paket geht und wo seine Grenzen liegen.

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website