Skip to content

Instantly share code, notes, and snippets.

@JGalego
Created August 4, 2025 01:16
Show Gist options
  • Select an option

  • Save JGalego/15d56c0df1f8a4bc28e88a019de1326a to your computer and use it in GitHub Desktop.

Select an option

Save JGalego/15d56c0df1f8a4bc28e88a019de1326a to your computer and use it in GitHub Desktop.
Fetches author names from an arXiv paper and visually superimposes them in a centered stack πŸ“œ Inspired by the SIGTBD 2023 paper "Every Author as First Author" by Erik and Martin Demaine
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "pillow >= 9.2.0",
# ]
# ///
"""
Fetches author names from an arXiv paper and visually superimposes them in a centered stack.
This script uses the arXiv API to retrieve metadata for a given paper, extracts the list of authors,
and renders their names stacked on top of each other in a single image.
Inspired by the SIGTBD 2023 paper "Every Author as First Author" by Erik and Martin Demaine,
the visualization emphasizes author equality by overlapping names in a unified display.
Usage:
python script.py <arxiv_url_or_id>
Args:
sys.argv[1] (str): The arXiv paper URL or ID to fetch author data from.
Returns:
Displays a semi-transparent stack of author names in a pop-up image window.
"""
import argparse
import urllib.request
import xml.etree.ElementTree as ET
from urllib.parse import urlparse
from PIL import Image, ImageDraw, ImageFont
def parse_args():
"""
Parses command-line arguments for customizing the author stack visualization.
Arguments:
input (str): arXiv paper ID or URL to retrieve author metadata.
--font (str): Optional path to a .ttf font file for rendering text. Defaults to 'arial.ttf'.
--width (int): Optional width of the output image in pixels. Defaults to 600.
--height (int): Optional height of the output image in pixels. Defaults to 200.
Returns:
argparse.Namespace: Parsed arguments object containing user inputs.
"""
parser = argparse.ArgumentParser(description="Stack arXiv author names on an image.")
parser.add_argument("input", help="arXiv paper ID or URL")
parser.add_argument("--font", default="arial.ttf", help="Path to a .ttf font file")
parser.add_argument("--width", type=int, default=600, help="Width of the image")
parser.add_argument("--height", type=int, default=200, help="Height of the image")
return parser.parse_args()
def fetch_arxiv_authors(arxiv_id):
"""
Queries the arXiv API for a paper and extracts the list of author names.
For more information, see info.arxiv.org/help/api/basics.html
Args:
arxiv_id (str): The arXiv paper ID.
Returns:
list of str: Author names.
"""
url = 'http://export.arxiv.org/api/query?id_list=' + arxiv_id
response = urllib.request.urlopen(url)
data = response.read().decode('utf-8')
ns = {'atom': 'http://www.w3.org/2005/Atom'}
xmldoc = ET.ElementTree(ET.fromstring(data))
return [name.text for name in xmldoc.findall('.//atom:author/atom:name', ns)]
def draw_name_stack(names, image_size=(600, 200), font_path=None):
"""
Draws a stack of names centered on a blank canvas.
Args:
names (list of str): List of names to superimpose on the image.
image_size (tuple): Size of the image in pixels (width, height).
font_path (str): Path to a .ttf font file. Defaults to None.
Returns:
PIL.Image: Image object with the names drawn on it.
"""
# Create a blank image with white background
img = Image.new('RGBA', image_size, 'white')
draw = ImageDraw.Draw(img)
# Load font
if font_path:
font = ImageFont.truetype(font_path or "arial.ttf", size=40)
else:
font = None
# Center coordinates
x = image_size[0] // 2
y = image_size[1] // 2
for name in names:
# Get text bounding box
bbox = draw.textbbox((0, 0), name, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
# Center the text
text_x = x - text_width // 2
text_y = y - text_height // 2
# Draw the name with semi-transparent black
draw.text((text_x, text_y), name, fill=(0, 0, 0, 128), font=font)
img.show()
return img
if __name__ == "__main__":
args = parse_args()
arxiv_id = urlparse(args.input).path.split("/")[-1]
authors = fetch_arxiv_authors(arxiv_id)
draw_name_stack(authors, image_size=(args.width, args.height), font_path=args.font)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment