Skip to content

BenHuddart/gleplot

Repository files navigation

gleplot - Matplotlib-like Plotting for GLE

A Python library that provides a matplotlib-compatible API for creating scientific plots that directly generate GLE (Graphics Layout Engine) scripts for publication-quality vector graphics.

Quick Start

import numpy as np
import gleplot as glp

# Create data
x = np.linspace(0, 2*np.pi, 100)

# Create figure and plot
fig = glp.figure(figsize=(8, 6))
ax = fig.add_subplot(111)
ax.plot(x, np.sin(x), color='blue', label='sin(x)')
ax.plot(x, np.cos(x), color='red', linestyle='--', label='cos(x)')

# Configure plot
ax.set_xlabel('x (radians)')
ax.set_ylabel('y')
ax.set_title('Trigonometric Functions')
ax.legend()

# Save as PDF (auto-compiles via GLE)
fig.savefig('trig.pdf')

# Or save as GLE script for manual editing
fig.savefig('trig.gle')

# Keep the script, compiled output, and data sidecars together
fig.savefig('trig.pdf', folder=True)

Features

Matplotlib-Compatible API - All familiar functions work identically
Direct GLE Generation - Optimized script output (1-2 KB)
Vector Graphics - PDF, PNG, EPS export with publication quality
Full Plotting Support - Lines, scatter, bars, fill_between, errorbar
Error Bars - Symmetric, asymmetric, vertical and horizontal
File-Based Series - Plot directly from existing data columns (no extra sidecar files)
Subplots - Multi-panel figures with flexible grid layouts
Subplot Layout Control - Fine-tune margins and inter-panel spacing with subplots_adjust
Publication Ready - Suitable for all major academic journals
Lightweight - Pure Python, minimal dependencies

GUI Editor

gleplot also ships a desktop editor (PySide6) for building figures without writing code: load data, pick columns, style series, arrange subplots, annotate, and export -- all with a live preview.

Install

pip install "gleplot[gui]"

Launch

gleplot-gui

Features

Live Preview - Debounced, async GLE compile as you edit, as a vector SVG by default (with an automatic, sticky PNG fallback if SVG isn't usable)
On-Canvas Annotations - Add, drag, double-click-edit, and delete free-form text labels directly on the preview, kept in sync with a dedicated Texts tab
Data Manager - Load CSV/.dat files, pick columns, import data or reference the file in place
Named Data Columns - Generated .dat sidecars carry real column names (from your series labels) instead of anonymous placeholders
Property Panels - Layout, Figure, Axes, Series, and Texts tabs for point-and-click styling
Native .gle Files - Save and open your work directly as .gle (the same format GLE renders) via File ▸ Save / Open -- unrecognized content is preserved as raw GLE
Export Dialog - PDF, PNG, EPS, SVG, JPG, or raw GLE script, with an optional folder bundle
Undo/Redo - Full editing history
Programmatic-.gle Preview - Files using GLE programming constructs open as a read-only render + export

Requirements

The editor needs GLE 4.3+ installed and discoverable (via GLE_PATH or PATH) to render the live preview and export non-.gle formats -- see Installation above. The status bar shows the detected GLE path (or "not found").

Prebuilt Windows and macOS builds are attached to each GitHub Release.

See the GUI Editor Guide for a full walkthrough, and examples/gui/ for a ready-to-open sample project.

Documentation

📚 Live Sphinx Documentation - Complete API reference and guides

Key Documentation Resources:

Installation

Requirements

  • Python 3.7+
  • numpy

Optional

  • GLE 4.3+ (for PDF/PNG/EPS compilation)

    # Verify installation
    gle -info

    Install GLE from the official upstream sources:

    GLE upstream also recommends installing runtime dependencies:

    • Ghostscript
    • LaTeX distribution (e.g., TeX Live or MiKTeX)

    Quick first-time verification:

    # Locate Ghostscript/LaTeX and other runtime dependencies
    gle -finddeps
    
    # Confirm GLE is installed and discover paths
    gle -info

Install gleplot

pip install -e .

Or in development mode:

pip install -e ".[dev]"

Project Structure

gleplot/
├── src/gleplot/                    # Source code
│   ├── __init__.py                # Main API
│   ├── figure.py                  # Figure class
│   ├── axes.py                    # Axes class  
│   ├── colors.py                  # Color utilities
│   ├── markers.py                 # Marker definitions
│   ├── dataio.py                  # Delimited data-file loading
│   ├── writer.py                  # GLE script writer
│   ├── compiler.py                # GLE compiler wrapper
│   ├── config.py                  # Configuration system
│   ├── parser/                    # Parse existing .gle back into the object model
│   └── gui/                       # PySide6 desktop editor
│
├── tests/                          # Test suite
│   ├── unit/                      # Unit tests
│   ├── integration/               # Integration tests
│   ├── parser/                    # GLE parser tests
│   ├── gui/                       # GUI editor tests
│   ├── agent/                     # Agent tests
│   ├── test_gleplot.py            # Core test suite
│   └── generate_test_graphics.py  # Graphics generation tests
│
├── examples/                       # Example scripts
│   ├── basic/                     # Basic plotting examples
│   │   ├── line_plots.py
│   │   ├── scatter_plots.py
│   │   ├── bar_charts.py
│   │   └── error_bars.py
│   ├── advanced/                  # Advanced examples
│   │   ├── subplots.py
│   │   ├── shared_axes.py
│   │   ├── fill_between.py
│   │   ├── log_scale.py
│   │   └── combined_plots.py
│   └── gleplot_examples.py        # Main examples runner
│
├── docs/                           # Documentation
│   ├── guides/                    # User guides
│   ├── agent/                     # Development notes
│   └── source/                    # Sphinx source files
│
├── pyproject.toml                 # Package configuration
├── README.md                       # This file
└── LICENSE                        # GPL-2.0+

Usage

Line Plots

ax.plot(x, y, color='blue', linestyle='--', label='data')

Scatter Plots

ax.scatter(x, y, color='red', marker='o', s=50, label='points')

Bar Charts

ax.bar([1, 2, 3], [10, 20, 30], color=['red', 'green', 'blue'])

Fill Between

ax.fill_between(x, y1, y2, color='lightblue', alpha=0.3)

Error Bars

# Symmetric vertical error bars
ax.errorbar(x, y, yerr=0.5, marker='o', color='blue', label='Data')

# Asymmetric vertical error bars
ax.errorbar(x, y, yerr=([lower_arr], [upper_arr]), marker='s', fmt='none')

# Both vertical and horizontal error bars
ax.errorbar(x, y, yerr=yerr, xerr=xerr, marker='o', capsize=3)

File-Based Series

# Error bars from existing file columns (1-based column indices)
ax.errorbar_from_file(
  'experiment.dat',
  x_col=1,
  y_col=2,
  yerr_col=3,
  marker='o',
  color='blue',
  label='Measurement'
)

# Overlay fit/model line from the same file without creating data_*.dat
ax.line_from_file(
  'experiment.dat',
  x_col=1,
  y_col=4,
  color='red',
  linestyle='--',
  linewidth=2,
  label='Model fit'
)

Foldered Exports

# Creates trig.gleplot/trig.pdf, trig.gleplot/trig.gle, and data files
fig.savefig('trig.pdf', folder=True)

Secondary Y-Axis

# Plot data with different scales on same graph
fig = glp.figure()
ax = fig.add_subplot(111)

# Plot on left y-axis (default)
ax.plot(days, temperature, color='red', label='Temperature', yaxis='y')
ax.set_ylabel('Temperature (°C)', axis='y')
ax.set_ylim(10, 30, axis='y')

# Plot on right y-axis
ax.plot(days, humidity, color='blue', label='Humidity', yaxis='y2')
ax.set_ylabel('Humidity (%)', axis='y2')
ax.set_ylim(30, 90, axis='y2')

# Log scale on secondary axis
ax.set_yscale('log', axis='y2')

ax.legend()
fig.savefig('dual_axis.pdf')

Subplots

# Using subplots() convenience function
fig, axes = glp.subplots(2, 2, figsize=(12, 10))
axes[0].plot(x, y1)        # top-left
axes[1].scatter(x, y2)     # top-right
axes[2].bar(x, y3)         # bottom-left
axes[3].errorbar(x, y4, yerr=err)  # bottom-right
fig.savefig('grid.pdf')

# Using add_subplot() method
fig = glp.figure(figsize=(14, 6))
ax1 = fig.add_subplot(1, 2, 1)  # left panel
ax2 = fig.add_subplot(1, 2, 2)  # right panel

# Shared axes for tighter layouts (stacked plots)
fig, axes = glp.subplots(3, 1, sharex=True, figsize=(8, 10))
# Only bottom subplot shows x-axis label and ticks
axes[0].plot(x, signal)
axes[1].plot(x, noise)
axes[2].plot(x, combined)
axes[2].set_xlabel('Time')  # Only need to label bottom

# Shared axes for side-by-side comparisons
fig, axes = glp.subplots(1, 3, sharey=True, figsize=(18, 5))
# Only leftmost subplot shows y-axis label and ticks
axes[0].scatter(x1, y1)
axes[0].set_ylabel('Response')  # Only need to label left
axes[1].scatter(x2, y2)
axes[2].scatter(x3, y3)

# Fine-tune multi-panel layout (matplotlib-compatible)
fig.subplots_adjust(
  left=0.12,
  right=0.98,
  bottom=0.1,
  top=0.92,
  wspace=0.35,
  hspace=0.4,
)

Axis Control

ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_title('My Plot')
ax.set_xlim(0, 10)
ax.set_ylim(0, 100)
ax.set_xscale('log')
ax.set_yscale('log')
ax.legend(loc='upper left')

Testing

Run the comprehensive test suite:

cd tests
python -m pytest test_gleplot.py -v

Or run directly:

python test_gleplot.py

Expected output: a comprehensive test suite (unit, integration, parser, and GUI tests), all passing

Examples

Run the example scripts:

cd examples
python gleplot_examples.py

Or run specific example categories:

# Basic examples
python basic/line_plots.py
python basic/scatter_plots.py
python basic/bar_charts.py
python basic/error_bars.py

# Advanced examples
python advanced/subplots.py
python advanced/shared_axes.py
python advanced/secondary_yaxis.py
python advanced/fill_between.py
python advanced/log_scale.py
python advanced/combined_plots.py
python advanced/multiple_styles.py

Each example generates GLE script files and optionally compiles them to PDFs.

API Reference

Figure

fig = glp.figure(figsize=(8, 6), dpi=100)

Axes

ax = fig.add_subplot(111)
ax.plot(...)
ax.scatter(...)
ax.bar(...)
ax.fill_between(...)

Module-level convenience

glp.figure()
glp.plot(x, y)
glp.scatter(x, y)
glp.xlabel('X')
glp.savefig('plot.pdf')

Comparison: gleplot vs matplotlib

Feature gleplot matplotlib
API 100% compatible Reference implementation
Output GLE vector graphics PNG/PDF raster + vector
File size 1-2 KB script 50-100 KB PNG
Compilation GLE → PDF/PNG Built-in
Learning curve None (familiar API) Moderate
Use case Publication graphics General-purpose plotting

Troubleshooting

GLE not found

If compilation fails, ensure GLE is installed and in PATH:

which gle
gle -info

Import errors

Make sure gleplot is properly installed:

pip install -e .

Test failures

Run tests with verbose output:

python -m pytest tests/ -vv

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new features
  4. Run: python -m pytest tests/
  5. Submit pull request

License

gleplot is licensed under GPL-2.0+ (compatible with GLE license).

References

Status

Production Ready
All Tests Passing
Multiple Example Categories
Full Documentation
Automatic Semantic Versioning

Repository


For questions, issues, or feature requests, please open an issue on GitHub.

Happy plotting! 📊

About

Matplotlib-compatible Python library for creating publication-quality plots with GLE (Graphics Layout Engine)

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors