Pylustrator: edit a matplotlib figure by mouse and get the code back
Visualisations of data are at the core of every publication of scientific research results. They have to be as clear as possible to facilitate the communication of research. As data can have different formats and shapes, the visualisations often have to be adapted to reflect the data as well as possible. We developed Pylustrator, an interface to directly edit python generated matplotlib graphs to finalize them for publication. Therefore, subplots can be resized and dragged around by the mouse, text and annotations can be added. The changes can be saved to the initial plot file as python code.
At a glance
- What is it?
- Pylustrator is a PyQt5 desktop application that lets you drag matplotlib subplots around, add text and annotations, and then saves your changes back as Python source, so a publication figure stays reproducible. The last tagged release is v1.3.0 from 2023, the licence is GPL-3.0-or-later, and the project is built around matplotlib rather than around any other plotting library.
- Who is it for?
- Pylustrator suits a researcher who has working matplotlib code, likes the plot, and needs to move panels and add labels without hand-tuning layout constants, because the result is code rather than a picture and the figure stays reproducible. It does not suit a workflow built around another plotting library, since the whole design assumes matplotlib objects, and it does not suit someone who wants a web-based or collaborative editing tool.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 52 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The point is that you get code back, not a picture
Pylustrator exists because of a specific habit in scientific publishing. A researcher produces a figure with a Python script, then discovers that a panel label is in the wrong place or a subplot needs to be wider, and the easy fix is to open the image in a graphics program and move things by hand. The result is a figure that no longer matches the code that produced it, which breaks the reproducibility that the publication is claiming. Pylustrator's answer is stated in the description: it prepares figures for publication in a reproducible way, so you receive the figure and, alongside it, a generated code file that reproduces the figure exactly as you edited it, without needing to readjust things in external programs. The interactive interface is for finding the best presentation of the data, and the formatting and styling you add are saved by automatically generated code. The deployment in scientific publishing is a real one, and the tool is a direct answer to it.
Panels, text and annotations are what you manipulate
The capabilities divide into two groups. The first is layout: subplots can be resized and dragged around with the mouse, and the tool can compose multiple figures into panels, that is, take different subfigures and put them together into a single figure. That composition feature is what separates it from simply nudging one axes object, because a multi-panel figure in a paper is usually assembled from separately made plots and the assembly is where the labels and the alignment live. The second group is annotation: text and annotations can be added, which covers panel letters, arrows, callouts and axis notes. The description frames the whole project in terms of data shape, noting that data can come in different formats and shapes and so visualisations often have to be adapted to reflect the data as well as possible, which is the reason a tool that works on top of your existing plotting code is useful rather than a separate drawing program with its own data model.
The dependency list tells you what it is built on
The package metadata is short and reveals the design. The project name is pylustrator, the version is 1.3.0, the license field says GPL-3.0-or-later, and the package summary is a single line about adding interactivity to arrange panels in matplotlib. That dependency list is the architecture in one screen. Matplotlib is the thing being edited, and it is the only plotting library present, which is why the tool works on your figure rather than on a screenshot of it. PyQt5 is the desktop interface, and qtpy sits above it, which is the abstraction layer that lets the same code target a different Qt binding if you need to. qtawesome provides the icon set for the toolbar, since this is an application with a lot of small commands, and scikit-image is there for image handling. The optional extras are a test extra pinned to pytest below version 8 and a dev extra with ruff and ty, the latter being a newer type checker, and the build backend is plain setuptools with a wheel, with the packages listed explicitly as pylustrator and pylustrator.components.
Contributing is a fork, a branch and a pull request
The contributing section is the shortest part of the documentation and it is worth reading because it shows the whole workflow. You fork the project, then create a branch for your feature with git checkout -b cool-new-feature, commit your changes with git commit -am 'My new feature', push the branch with git push origin cool-new-feature and submit a pull request. The commit uses the -a flag, so it stages the modifications to already tracked files, which is convenient here because the change you are making is an edit to an existing source file rather than the addition of new ones. The package metadata also shows what the tool is made of:
requires-python = ">=3.9"
dependencies = [
"natsort>=2.0.0",
"numpy>=1.0.3",
"matplotlib>=2.0.2",
"PyQt5>=5.6",
"qtawesome>=0.5.0",
"scikit-image>=0.7.0",
"qtpy>=2.4.3",
]The repository also carries a ruff configuration in the same file that excludes the documentation example file, so the formatting rules are declared next to the package metadata, and there is a uv.lock file, which means the development environment is pinned. The tests directory sits alongside the package and there is a pytest workflow badge on the project, and the type checking setup is visible in a ty.toml file and a matplotlib-stubs directory, which is how the IDE gets correct types for the plotting calls the tool makes.
A journal article, a DOI and a documentation site
Two badges on the project page say something that most repositories do not. One is a DOI pointing to a Journal of Open Source Software article, and the other is a Read the Docs badge for pylustrator.readthedocs.io. A JOSS paper is a peer reviewed description of a research software tool, which is a different kind of validation from unit tests, and the presence of a citation file in the repository root, in both the BibTeX and the CFF format, means you are expected to cite the tool properly rather than mention it in passing. The documentation is a separate site built with Sphinx, and the readthedocs configuration file in the repository root points at it, with a docs dependency group that pulls in nbsphinx for the notebooks, the sphinx-rtd-theme for the theme and sphinxcontrib-bibtex, which is the extension that renders the citation file inside the documentation itself. The developer experience is therefore documented for a scientific audience rather than for developers only, which fits a tool whose users are researchers first.
Where this is the wrong tool
The scope is narrow in a way that is easy to underestimate. Pylustrator edits matplotlib figures, so a figure made with another library, with plotly or with a bespoke graphics tool, is not something it can open. If your publication pipeline produces figures outside matplotlib, the tool does nothing for you. The second limitation is that it is a desktop application. PyQt5 needs a display, which is fine on a workstation and awkward on a headless build server or over a remote shell, and that rules it out of any pipeline where figures are generated automatically without a human present. The third is the usual one for tools in this space: the layout you produce by dragging is a starting point, and the automatic code it writes will not match the style of your existing script, so you will end up tidying the generated code by hand. The tool is a shortcut for the fiddly last hour of figure preparation, not a replacement for understanding how your axes are laid out.
Maintenance state and what it means for a dependency
The version history needs reading carefully. The tagged releases are v1.3.0 from 2023-02-28, v1.2.1 from 2022-10-26 and v1.2 from 2022-10-24, and the package metadata still declares version 1.3.0. The last push to the repository was on 2026-09-01, so work is landing in the repository even though nothing has been tagged since 2023. The distinction matters if you depend on the package, because pip will give you the tagged version, and the code in the repository is ahead of that. The dependencies have clearly moved on in the meantime: the test extra is pinned to pytest below 8, the type checker is the newer ty rather than mypy, and there is a uv lock file, all of which point to a project being modernised rather than frozen. The licence is GPL-3.0-or-later, which for a tool you run on your own machine is not a practical constraint, but it is a real one if you were planning to fold the code into a closed source tool.
Editorial conclusion
Pylustrator suits a researcher who has working matplotlib code, likes the plot, and needs to move panels and add labels without hand-tuning layout constants, because the result is code rather than a picture and the figure stays reproducible. It does not suit a workflow built around another plotting library, since the whole design assumes matplotlib objects, and it does not suit someone who wants a web-based or collaborative editing tool. Before installing it, check that you can run a desktop Qt application on your machine, since the interface is PyQt5, and read the generated code after saving, because the tool writes Python that you will eventually own.
Frequently asked questions
What does Pylustrator do with a matplotlib figure?
It opens it in an interactive PyQt5 interface where you can resize and drag subplots around, add text and annotations, and compose separate subfigures into a single multi-panel figure. The changes are then saved as automatically generated Python code.
How does Pylustrator keep a publication figure reproducible?
Instead of editing the exported image in an external graphics program, you edit it in Pylustrator and save the result as a generated code file that reproduces the figure exactly as you arranged it, so the figure still matches the script that produced it.
What are the dependencies of the pylustrator package?
matplotlib, PyQt5, qtpy, qtawesome, numpy, natsort and scikit-image, with Python 3.9 or newer required. The test extra pulls pytest below version 8, and the dev extra pulls ruff and the ty type checker. The build backend is setuptools with a wheel.
How do I contribute a change to Pylustrator?
Fork the project, create a branch for your feature with git checkout -b, commit the changes with git commit -am, push the branch with git push origin and then open a pull request. Questions and bug reports go to the issue tracker in the repository.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rgerum-pylustrator)Was this useful?