Gallery: Scientific Plot Organizer

Python 3.8+ License: MIT

Create responsive HTML galleries for scientific plot collections. Convert PDFs to PNG, organize plots hierarchically, and generate beautiful static websites.

Features

Core Functionality

  • PDF to PNG Conversion: Automatic high-quality thumbnail generation using ImageMagick
  • Incremental Updates: Only processes files when source is newer than target
  • Responsive Design: Mobile-friendly interface with multiple view modes
  • Hierarchical Organization: Support for nested folder structures
  • Search & Navigation: Real-time search with fuzzy matching

Advanced Features

  • Plot Comparison: Side-by-side comparison tool for analyzing differences
  • Metadata Management: YAML/JSON metadata with inheritance and display, to properly label each folder
  • Recent Plots: Quick access to recently viewed items
  • Theme Support: Dark/light theme toggle
  • Keyboard Shortcuts: Power-user navigation

Developer-Friendly

  • Python API: Import and use programmatically in other projects
  • CLI Interface: Command-line command gallery with subcommands
  • TUI Interface: Textual-based terminal UI gallery tui
  • Configuration Flexibility: Config file stored under user $HOME/.config/gallery
  • Source Override: Process single directories without full regeneration

📸 Screenshots

gallery_view

Metadata Display

metadata

Plot Comparison Tool

plot_comparison

Search Functionality

🚀 Installation

From GitLab

Pip install:

pip install git+https://gitlab.com/kschmidt/web.git

Or git clone and pip install .. After installation the gallery command is available in your shell. Verify with:

gallery --help

Dependencies

  • Python 3.8+
  • Python packages are installed automatically by pip (Jinja2, PyYAML, PyMuPDF, Textual, argcomplete, platformdirs)
  • ImageMagick is optional — used as a fallback if PyMuPDF is not available

Shell Completion (optional)

Install tab-completion for bash/zsh/fish:

gallery install-completion

Then restart your shell or follow the printed instructions to activate it.

🖥️ CLI Usage

The gallery command has four subcommands: generate, config, tui, and install-completion.

Quick start

# 1. Set your web output directory
gallery config set paths.web_folder /path/to/your/public_html

# 2. Add one or more plot source directories
gallery config add-source --path /path/to/plots --name my_analysis

# 3. Generate the gallery
gallery generate
# Full regeneration
gallery generate

# Verbose output
gallery generate --verbose

# Clean rebuild (delete output before generating)
gallery generate --clean

# Regenerate a single source only
gallery generate --source /path/to/plots

# Use a non-default config file
gallery --config /path/to/config.yaml generate
# Show all configuration values
gallery config list

# Show the resolved config file path
gallery config path

# List configured sources
gallery config sources

# Get a single value
gallery config get gallery.png_dpi

# Set a value (all standard YAML types accepted)
gallery config set gallery.png_dpi 300
gallery config set metadata.cache_enabled true

# Add a source directory
gallery config add-source --path /path/to/plots --name my_plots

# Remove a source
gallery config remove-source my_plots

Serving locally

python -m http.server 8000 -d /path/to/public_html

Then open http://localhost:8000/gallery/ in your browser.

🖱️ TUI Usage

The TUI is a terminal user interface built with Textual. It lets you edit the configuration and trigger generation without leaving your terminal.

gallery tui

TUI Overview

The TUI is divided into collapsible sections and a persistent footer:

Section Contents
Paths Web output folder
Gallery Settings Plot root, PNG DPI, backup folder, cache and metadata options
Sources Editable list of source directories — add or remove rows inline
Generation Status indicator, scrollable log output

The footer bar is always visible at the bottom:

Button Keyboard Action
Save Config Ctrl+S Write current values to config file
Generate Run gallery generate in background
Quit Ctrl+Q Exit the TUI

An unsaved changes indicator (● unsaved changes) appears in the title bar whenever a field has been modified but not yet saved.

Generation runs in a background thread and streams output line-by-line into the log widget. The status button changes colour: blue (idle) → yellow (running) → green (success) / red (error).

⚙️ Configuration

The config file lives at $HOME/.config/gallery/config.yaml by default. You can point to a different file with gallery --config /path/to/config.yaml <subcommand>.

config.yaml Structure

paths:
  web_folder: "/web/user/public_html"   # required

gallery:
  plot_root: "gallery"       # subdirectory inside web_folder
  png_dpi: 400               # thumbnail resolution
  backup_folder: ""          # optional backup path

sources:
  - name: "analysis_results"
    path: "/path/to/plots/directory"
  - name: "specific_plot"
    path: "/path/to/another/directory"

metadata:
  cache_enabled: true
  inherit_from_parent: true

Metadata Files

Create metadata.yaml files in your source directories. Fields are arbitrary and rendered via YAML object interpretation (dict, list, …). Lower-level files override parent values — useful for labelling specific experiments.

# metadata.yaml
title: "Analysis Results"
description: "Results for my analysis"
experiment: "CMS"
dataset: "Run2_2016_nano_v9"

parameters:
  luminosity: "35.9 fb^{-1}"
  center_of_mass_energy: "13 TeV"
  selection: "baseline"

tags:
  - "physics"
  - "analysis"
  - "cms"

authors:
  - "Researcher A"
  - "Researcher B"

LaTeX formulas are supported in metadata values and rendered with MathJax:

formula: "$$E = mc^2$$"

🎮 User Interface Guide

Navigation Controls

Button Function Keyboard Shortcut
🔍 Search Real-time plot search Ctrl+K
📋 Recent Recently viewed plots Ctrl+R
⚖️ Compare Side-by-side comparison Ctrl+C
☀️ Theme Toggle dark/light theme Ctrl+T

View Modes

  • Grid View: Thumbnail grid with metadata overlay
  • Large List: Detailed list with larger previews
  • Compact List: Dense list for quick scanning

🛠️ Development Guide

Project Structure

gallery/
├── api.py                    # generate() — primary public entry point
├── builder.py                # build_gallery() recursive traversal; template/assets
├── cli.py                    # gallery CLI command (argparse + argcomplete)
├── tui.py                    # gallery tui (Textual TUI)
├── config/
│   └── __init__.py           # GalleryConfig, GallerySource, ConfigManager
├── utils/
│   ├── metadata.py           # YAML/JSON loading, inheritance, caching
│   ├── processing.py         # PDF→PNG conversion; needs_update(); render_gallery_page()
│   ├── stats.py              # Directory size/file count statistics
│   ├── backup.py             # Backup functionality
│   └── datetime_utils.py     # Date/time utilities for templates
├── templates/
│   └── gallery.html          # Single Jinja2 template for all pages
└── assets/
    ├── css/                  # Modular CSS; main.css imports all via @import
    └── js/                   # Vanilla ES modules; GalleryApp orchestrates all managers

Running Tests

pytest tests/
pytest tests/test_generate_gallery.py -v
pytest tests/test_generate_gallery.py::test_needs_update_missing_target -v

Adding New Features

CSS component

/* gallery/assets/css/new-feature.css */
.new-feature { }

Add @import url('./new-feature.css'); to main.css.

JavaScript module

// gallery/assets/js/new-feature.js
export class NewFeature { ... }

Import in gallery-app.js and instantiate in GalleryApp.

🔧 Troubleshooting

Common Issues

Issue Solution
gallery command not found Run pip install -e . from the repo root
PDF conversion fails — no renderer Install PyMuPDF: pip install pymupdf (or apt-get install imagemagick as fallback)
PDF conversion fails — corrupt file Verify the PDF opens in a viewer; try pip install --upgrade pymupdf
Permission denied on web dir Check file permissions and web directory access
Metadata not showing Check YAML syntax with python -c "import yaml; yaml.safe_load(open('metadata.yaml'))"

ImageMagick memory limits (fallback backend only)

export MAGICK_MEMORY_LIMIT=2GB
export MAGICK_MAP_LIMIT=2GB
gallery generate --verbose

Debug / clean rebuild

gallery generate --verbose
gallery generate --clean --verbose

📄 License

This project is licensed under the MIT License — see the LICENSE file for details.

🙏 Acknowledgments

Disclaimer

This project was made entirely using Claude Sonnet 4.0 and GPT 4.1. 100% of the code was AI generated and no human hand was involved other than prompting the Agent. I do not claim any part of this project as my own work.

Packages

  • PyMuPDF for PDF to PNG conversion (pure Python, no system dependencies)
  • ImageMagick as optional fallback PDF renderer
  • Jinja2 for templating
  • Textual for the terminal UI
  • MathJax for LaTeX rendering
  • PyYAML for YAML processing
  • argcomplete for shell tab-completion
S
Description
No description provided
Readme MIT 2.9 MiB
Languages
Python 49.6%
JavaScript 24.4%
CSS 19.5%
HTML 6%
Dockerfile 0.3%
Other 0.2%