Shell Scripts
Some useful shell scripts and aliases I frequently use.
Track File Changes
To keep track of changes in a file, I use the following shell function:
Script
stamp() {
filename=${1%.*}
ext=${1##*.}
filetime=$(date +%Y%m%d_%H%M%S)
cp -i "$1" "${filename}_${filetime}.${ext}"
}
Usage
stamp file.tex
Output
This creates a timestamped copy of file.tex:
file_20260806_211114.tex
PDF Printing
For printing documents with multiple pages on a single sheet, I use the following aliases:
2 Pages on 1 Sheet
alias pdf1x2="pdfjam --nup 2x1 --landscape --paper a4"
4 Pages on 1 Sheet
alias pdf2x2="pdfjam --nup 2x2 --landscape --paper a4"
Note: These aliases use pdfjam, a convenient tool for PDF manipulation.
Calibre
Here is a python script I use for scanning the barcodes of book and sending the information to calibre.
I use this script with MacOS.
The script calibre_barcode.py activates the camera, scans the barcode, and ask if the user wants to scan another barcode.
When all the scans are performed the information is added to the calibre database specified by the path CALIBREDB_PATH
The full script is given below
# -*- coding: utf-8 -*-
# Author: Pierre Vanhove
# Date: August 9, 2026
# Description: A script for generating barcodes for Calibre library management.
import cv2
import numpy as np
import subprocess
from pyzbar.pyzbar import decode
# Path to the Calibre command-line tool on macOS
CALIBREDB_PATH = "/Applications/calibre.app/Contents/MacOS/calibredb"
# Initialize the webcam
cap = cv2.VideoCapture(0)
scanned_barcodes = set()
books_to_add = []
scanning_active = True
print("Camera starting... Please hold up a barcode.")
while scanning_active:
# Capture frame-by-frame
ret, frame = cap.read()
if not ret:
print("Failed to grab frame.")
break
# Decode barcodes in the frame
decoded_objects = decode(frame)
for obj in decoded_objects:
barcode_type = obj.type
barcode_data = obj.data.decode('utf-8')
# Draw a rectangle around the barcode (UI formatting)
points = obj.polygon
if len(points) > 4:
hull = cv2.convexHull(np.array([point for point in points], dtype=np.int32))
cv2.polylines(frame, [hull], True, (0, 255, 0), 2)
else:
points = [(point.x, point.y) for point in points]
for j in range(len(points)):
cv2.line(frame, points[j], points[(j + 1) % len(points)], (0, 255, 0), 2)
cv2.putText(frame, barcode_data, (obj.rect.left, obj.rect.top - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
# Process only if we haven't seen this barcode yet
if barcode_data not in scanned_barcodes:
print(f"\n--- New Barcode Detected ---")
print(f"Type: {barcode_type}")
print(f"Data: {barcode_data}")
# Add to our tracking lists
scanned_barcodes.add(barcode_data)
# We only want to send EAN13 (ISBN) codes to Calibre
if barcode_type == 'EAN13':
books_to_add.append(barcode_data)
# Write to our backup text file
with open("scanned_barcodes.txt", "a") as file:
file.write(f"Type: {barcode_type}, Data: {barcode_data}\n")
# Briefly update the OpenCV window to show the green box before pausing
cv2.imshow('Barcode Reader', frame)
cv2.waitKey(1)
# Pause and ask the user in the terminal
while True:
user_choice = input("\nIs there another barcode to scan? (yes/no): ").strip().lower()
if user_choice in ['yes', 'y']:
print("Resuming camera... Please present the next barcode.")
break # Break the prompt loop, resume camera
elif user_choice in ['no', 'n']:
scanning_active = False
break # Break the prompt loop, prepare to exit
else:
print("Please answer 'yes' or 'no'.")
# Break out of the decoded_objects for-loop so we don't process multiple in one frame
# while trying to handle the user input
break
# Display the resulting frame (only updates if not paused waiting for input)
if scanning_active:
cv2.imshow('Barcode Reader', frame)
# Break the loop if 'q' is pressed on the video window
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Turn off the camera immediately after answering "no"
cap.release()
cv2.destroyAllWindows()
# --- CALIBRE BATCH UPLOAD SECTION ---
if books_to_add:
print(f"\nCamera closed. Preparing to send {len(books_to_add)} books to Calibre...")
for isbn in books_to_add:
print(f"Adding ISBN {isbn} to Calibre...")
try:
# Run the calibredb command to add an empty book with the ISBN
subprocess.run([
CALIBREDB_PATH,
"add",
"--empty",
"--isbn",
isbn
], check=True)
print(f"-> Successfully added {isbn}!")
except FileNotFoundError:
print(f"-> Error: Could not find Calibre at {CALIBREDB_PATH}.")
break # Stop trying if Calibre isn't installed
except subprocess.CalledProcessError as e:
print(f"-> Error adding {isbn} to Calibre: {e}")
print("\nAll done! You can open Calibre now.")
else:
print("\nNo ISBNs were scanned. Exiting program.")
Mathematica
Symanzik Polynomials for Feynman Graphs
The first and second Symanzik polynomials of Feynman graphs can be computed by calculating determinants, as explained in the paper: On Motives Associated to Graph Polynomials by Spencer Bloch, Hélène Esnault, and Dirk Kreimer.
Mathematica Implementation
Here’s how I implemented it in Mathematica:
Function to Compute Symanzik Polynomials
UF[listprop_, listloop_] :=
Module[{l0, Utmp, Ftmp, Qtmp, Qhomtmp, itmp},
{
Qtmp = Sum[x[itmp] listprop[[itmp]], {itmp, Length[listprop]}];
Utmp = Det[HessianMatrix[Qtmp, listloop]] 2;
Qhomtmp = HomogenizePoly[Qtmp, listloop, l0];
Ftmp = Det[HessianMatrix[Qhomtmp, Join[{l0}, listloop]]];
{Utmp, Ftmp}
} / 2^(Length[listloop] + 1)
]
Hessian Matrix Function
To use the HessianMatrix function from the Wolfram Function Repository:
ClearAll[HessianMatrix]
HessianMatrix[args___] :=
Module[{res},
update[];
res = Symbol["ResourceFunctionHelpers`HessianMatrix"][args];
res /; Head@res =!= Symbol["ResourceFunctionHelpers`HessianMatrix"]
]
Homogenization Function
A helper function to homogenize polynomials:
ClearAll[HomogenizePoly];
HomogenizePoly[poly_, vars_, hvar_] :=
Module[{deg},
deg = Max[Total /@ CoefficientRules[poly, vars][[All, 1]]];
Expand[hvar^deg*(poly /. Thread[vars -> vars/hvar])]
]