Skip to main content

cg-plot-capture

A custom Matplotlib backend designed for CodeGrade. This backend captures plots generated during script execution and handles them according to a configurable mode: displaying them in CodeGrade Code Editor output, saving them to disk, or both.

It uses the Matplotlib Canvas-based API and requires Matplotlib >= 3.6.

Installation

Installing the package can be done using pip:

python -m pip install cg-plot-capture

If you are using plotnine, you can install using the following command:

Optional: Install with plotnine or seaborn

To use plotnine you can install using pip:

python -m pip install cg-plot-capture[plotnine]

python -m pip install cg-plot-capture[seaborn]

Quick start

The simplest way to use the backend is to set the MPLBACKEND environment variable:

export MPLBACKEND=cg_plot_capture
python3 your_script.py

By default, plots are rendered as SVG and displayed in the CodeGrade Code Editor output. No files are saved to disk.

Configuration

Configuration is handled entirely via environment variables.

MPLBACKEND (Required)

  • Description: Used to set the backend so that anything output from Matplotlib will be correctly handled. Without this nothing will be displaying. It must be set for every script which uses it.
  • Values: cg_plot_capture

CG_PLOT_MODE (Optional)

  • Description: Determines the operation mode of the backend.
  • Values: display, save, both.
  • Default: 'display'

The backend operates in one of three modes, controlled by the CG_PLOT_MODE environment variable:

  1. display (Default): Renders plots as SVG and streams them via file descriptor 3 (fd3) to the CodeGrade Code Editor output.
  2. save: Renders plots to a specified format (see below for supported formats) and saves them to a local directory.
  3. both: Performs both displaying and saving.

CG_PLOT_FILENAME (Optional)

  • Description: Template for plot filenames. Controls both the filename and output location.
  • Default: 'plot_{i}.png'
  • Placeholders:
    • {i}: Counter (required)

Template system:

  • Use {i} as a placeholder for the sequential counter (required)
  • Include path separators to organize plots into directories
  • Specify the file extension to control the output format
  • Use Python format string syntax (e.g., {i:03d} for zero-padding)

Supported Formats:

png, pdf, svg, jpg, jpeg, eps, ps, tif, tiff, webp, pgf, raw, rgba, svgz

⚠️ Counter Resets Warning:

The {i} counter resets to 1 for each script execution. When running multiple scripts with save or both mode, files may be overwritten unless you use different paths or filenames per script.

Examples:

  • 'plot_{i}.png' → plot_1.png, plot_2.png, ...
  • './results/fig_{i}.pdf' → results/fig_1.pdf, results/fig_2.pdf, ...
  • 'analysis_{i:03d}.svg' → analysis_001.svg, analysis_002.svg, ...

Example usage

Example 1: Basic display

Show plots in the CodeGrade UI without saving files:

export MPLBACKEND=cg_plot_capture
python3 student_script.py

Example 2: Basic display and save

This example shows a setup to display and save the plot output using a folder and format of your choice. With this you'd need to use these environment variables in every step you're running. See the next example on how to set it for all steps in your AutoTest configuration.

export MPLBACKEND=cg_plot_capture
export CG_PLOT_MODE="both"
export CG_PLOT_FILENAME="./artifacts/plot_{i}.pdf"
python3 student_script.py

Example 3: One-time configuration using cg_bash_env

Optionally, you can set the configuration one time, so you don't have to set it for every step which makes use of cg-plot-capture. By setting this in the AutoTest Setup or first thing in Test, these are available throughout your configuration.

cat >> ~/.cg_bash_env << 'EOF'
export MPLBACKEND=cg_plot_capture
export CG_PLOT_MODE="both"
export CG_PLOT_FILENAME="./all_plots/plot_{i}.png"
EOF

After this, all scripts in subsequent test steps will use these settings. You can still override CG_PLOT_FILENAME for individual scripts if needed.

Example 4: Running multiple scripts

When running multiple scripts, update the filename template for each to avoid overwrites:

# Script 1
export CG_PLOT_FILENAME="./plots/script1_{i}.png"
python3 script1.py

# Script 2
export CG_PLOT_FILENAME="./plots/script2_{i}.png"
python3 script2.py

Alternatively, use separate directories:

# Script 1
export CG_PLOT_FILENAME="./script1_plots/plot_{i}.png"
python3 script1.py

# Script 2
export CG_PLOT_FILENAME="./script2_plots/plot_{i}.png"
python3 script2.py

Runtime Method

Alternatively, after installing the package, you can invoke it within a Python script using matplotlib.use() before importing pyplot:

import matplotlib
matplotlib.use('module://cg_plot_capture')

import matplotlib.pyplot as plt

plt.plot([1, 2, 3], [4, 5, 6])
plt.show() # Triggers the capture (Stream, Save, or Both)

Limitations and notes

Thread safety: This backend is NOT thread-safe. Multiple threads calling plt.show() or show() simultaneously may produce corrupted output or duplicate filenames. This matches matplotlib's own threading limitations in which figures should only be created and shown from the main thread. Multiprocessing, on the other hand, IS safe.

Multiprocessing is safe and fully supported.

Counter Behavior

The {i} counter:

  • Starts at 1 when each script begins
  • Increments with each plt.show() call
  • Resets to 1 when a new script starts
  • Is local to each Python process (safe for multiprocessing)

Interactive Mode

This backend operates in non-interactive mode. Functions like plt.ion() have no effect. All plots are captured when plt.show() is called.

Compatibility

  • Requires Matplotlib >= 3.6
  • Works with standard Matplotlib plotting
  • Compatible with any library that uses Matplotlib, including:
    • plotnine: ggplot2-style grammar of graphics (install with [plotnine] extra)
    • seaborn: Statistical data visualization (install with [seaborn] extra)
    • pandas plotting: DataFrame.plot() methods work automatically
  • Tested with both pyplot.show() and figure manager show() methods

Troubleshooting

Plots not appearing in CodeGrade UI:

  • Verify MPLBACKEND=cg_plot_capture is set
  • Check that CG_PLOT_MODE is display or both (not save)
  • Ensure you're calling plt.show() to trigger capture

Files not being saved:

  • Verify CG_PLOT_MODE is save or both (not display)
  • Check that CG_PLOT_FILENAME includes a valid path
  • Check file permissions on the output directory

Files being overwritten:

  • See Example 4 for running multiple scripts
  • Each script resets the counter to 1
  • Use different paths or filenames per script

Format not recognized:

  • Check that your extension is in the supported formats list
  • Matplotlib determines format from the file extension in CG_PLOT_FILENAME

Metadata

Release files for cg-plot-capture 1.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cg-plot-capture 1.0.2
File Size Uploaded Provenance Actions
cg_plot_capture-1.0.2.tar.gz 7.4 kB With provenance Details for cg_plot_capture-1.0.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for cg-plot-capture 1.0.2
File Interpreter ABI Platform Actions
cg_plot_capture-1.0.2-py3-none-any.whl Python 3 none any Details for cg_plot_capture-1.0.2-py3-none-any.whl

Total release size: 15.2 kB

Release files / cg_plot_capture-1.0.2.tar.gz

Download URL cg_plot_capture-1.0.2.tar.gz
Size 7.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c6e658c4262b35a0c260e5eb83fc1799a84d01f3d3b63577c50302b93a76da1d
BLAKE2b-256 checksum
How to use checksums
e922a5278e2b279e25467806affadf627c4118c3f21ef6ce1e2c4fc6593d9e58
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 4, 2026.

Transparency log

Release files / cg_plot_capture-1.0.2-py3-none-any.whl

Download URL cg_plot_capture-1.0.2-py3-none-any.whl
Size 7.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d5e3e015c607a43c6a9409faa5bf9b3739276739fa8d3d020d45dc915a3c4125
BLAKE2b-256 checksum
How to use checksums
ed676d78da5b1676b153064b4414c92850f6a445d80bbbae8fa39b749200d6f2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 4, 2026.

Transparency log

Security for cg-plot-capture 1.0.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for cg_plot_capture-1.0.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 4, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page