mpl-pointpicker
Attach directly to your original Matplotlib axes: zoom into the underlying data,
select fine details, and keep x fixed while picking a column. No intermediate
screenshots or cropped image files are needed. PNG/JPG digitization is also
available as a separate workflow. Recover
coordinates as NumPy arrays or dictionaries grouped by a series name or a
transition (i, j), with optional uncertainty in y.
Python 3.11 or newer. MIT licensed. This package was extracted from SCCircuits; it does not depend on SCCircuits, SciPy or SymPy.
Install
Version 0.1.0 is distributed through GitHub while the first PyPI publication is being prepared. Install from the fixed release tag:
python -m pip install "mpl-pointpicker @ git+https://github.com/joanjcaceres/mpl-pointpicker.git@v0.1.0"
For Jupyter Notebook, JupyterLab or VS Code notebooks:
python -m pip install "mpl-pointpicker[notebook] @ git+https://github.com/joanjcaceres/mpl-pointpicker.git@v0.1.0"
The GitHub release also includes a wheel and a source archive, installable with
python -m pip install <downloaded-file>. A plain pip install mpl-pointpicker
will become available after publication to PyPI.
Start with your original Matplotlib data
Pass the same ax used to display your measurement data. Existing image arrays,
pcolormesh heatmaps, curves, contours and overlays stay in the figure. Their
coordinates are already defined, so no calibration is needed.
import numpy as np
import matplotlib.pyplot as plt
from mpl_pointpicker import PointPicker
# Replace this synthetic dataset with your original x, y and measured signal.
x = np.linspace(0, 1, 2001)
y = np.linspace(2, 8, 801)
ridge = 4 + np.cos(2 * np.pi * x)
signal = np.exp(-((y[:, None] - ridge[None, :]) / 0.025) ** 2)
fig, ax = plt.subplots()
ax.pcolormesh(x, y, signal, shading="auto")
ax.set(xlabel="Control parameter", ylabel="Frequency (GHz)")
picker = PointPicker(ax, axis_lock=True)
plt.show()
data = picker.to_transition_data(include_sigma=True)
Use the Matplotlib zoom/pan toolbar to inspect a small region, then deactivate the toolbar tool before selecting points. The picker continues to use the original data coordinates at every zoom level. It does not turn your axes into a screenshot. Resolution is determined by the original data, rather than a previously saved image's screen resolution.
With axis_lock=True, the first point fixes the current column's x coordinate.
Later points use that exact x even after zooming or panning; dragging a point
changes only y. Press n for a new column, or click an existing point in Add
mode to reuse its x. The lock operates in data units and does not require
recalibration when the view changes.
Try the axes and zoom notebook or run
python examples/desktop.py to explore the original synthetic data interactively.
Start with an image file
import matplotlib.pyplot as plt
from mpl_pointpicker import PointPicker
picker = PointPicker.from_image("graph.png")
picker.calibrate() # Omit this line to keep pixel coordinates.
plt.show() # Desktop event loop; interact before closing the window.
data = picker.to_dict()
picker.save_yaml("picked-points.yaml")
Keep the picker variable alive for the duration of the interaction. In desktop
scripts, choose an interactive Matplotlib backend. macOS and standard Windows
Python installations usually provide one. On Linux, install your distribution's
Tk support or a Qt binding such as PySide6, then select TkAgg or QtAgg before
importing matplotlib.pyplot. The noninteractive Agg backend can export data
and run tests but cannot receive mouse clicks.
Linear image calibration
Calibration must happen before adding points. The graph must have straight, horizontal/vertical linear axes; logarithmic axes and rotated photographs are outside this version's scope.
- Call
picker.calibrate(). - Click two positions with known x values, in order X1, X2. Their y positions do not matter.
- Click two positions with known y values, in order Y1, Y2. Their x positions do not matter.
- Enter those four axis values in the form and choose Apply.
Click precisely on tick marks or other known reference locations. Each pair needs distinct positions and values. Descending values are supported. Esc cancels calibration; the Cancel button is also available in the value form. The image and future points now share the calibrated coordinates. Calibration does not estimate uncertainty: sigma is entered separately in the final y units.
Use in Jupyter
Run this before creating figures:
%matplotlib widget
from mpl_pointpicker import PointPicker
picker = PointPicker.from_image("graph.png")
picker.calibrate()
Complete calibration and point selection in the displayed figure. Then run a
separate cell to retrieve picker.to_dict() or save YAML. Notebook code does
not block while waiting for mouse input. %matplotlib inline produces a static
image and is unsuitable for picking. Use the notebook extra above, and restart
the kernel after installing it. use_widgets=False uses Matplotlib forms even
inside a notebook.
For the image-file workflow, try the guided
image calibration notebook, or run
python examples/desktop.py graph.png. Choose the axes workflow above whenever
you have the original measurement arrays or a prepared Matplotlib figure.
Select and edit
Focus the figure before using shortcuts:
| Key | Action |
|---|---|
a / Esc |
Add mode: click to add a point |
m |
Move mode: drag a point |
d |
Delete mode: click a point |
t |
Tag mode: click a point, choose Transition or Series, enter a label and optional sigma |
i |
Inspect mode: click a point to print its label and coordinates |
n |
Start a new x column when axis_lock=True |
Pan and zoom toolbar operations do not add or edit points. In the tag form use Action → Remove tag → Apply to remove a label. Esc closes the form. Typing in a form does not trigger editing shortcuts. Markers are red when unlabeled, orange when labeled, and green when labeled with sigma.
For an existing plot or an image array with coordinates already set:
fig, ax = plt.subplots()
ax.plot([0, 1, 2], [1, 4, 2])
picker = PointPicker(ax, axis_lock=False, pick_radius=6)
plt.show()
axis_lock=True keeps each column's x value fixed, including during dragging.
Press n to choose another column, or click an existing point in Add mode to
reuse its column.
Get results
picker.xy # N × 2 NumPy array, including unlabeled points
x, y = picker.get_coordinates() # Also available as x_coords and y_coords
picker.view_points() # Table with labels and sigma
picker.tag_point(0, (0, 1), 0.02) # Programmatic transition tag
picker.tag_point(1, "series A") # Programmatic text label
picker.to_dict()
# {(0, 1): [(0.25, 5.10, 0.02)], "series A": [(0.50, 3.20, None)]}
picker.to_transition_data()
# {(0, 1): [(0.25, 5.10)]}
to_dict(include_sigma=True, x_scale=1.0) includes text and transition groups.
to_transition_data(include_sigma=False, x_scale=1.0) returns only integer-pair
labels, compatible with SCCircuits TransitionFitter. Both omit unlabeled
points. include_sigma=False returns pairs (x, y); otherwise entries are
(x, y, sigma), where unset sigma is None.
set_current_label(label) and set_current_sigma(sigma) set suggestions for the
tag form; new points remain unlabeled until explicitly tagged. sigma must be
positive and finite when supplied. x_scale must be positive and finite and
multiplies exported x values only. Transition order is preserved; the fitter
can normalize (i, j) if needed.
Save and resume
picker.save_yaml("picked-points.yaml", include_sigma=True, x_scale=1.0)
fig, ax = plt.subplots()
ax.imshow(plt.imread("graph.png"), origin="upper", cmap="gray")
restored = PointPicker.load_yaml(ax, "picked-points.yaml")
plt.show()
Provide the original image separately; it is not embedded in YAML. When an
image is already on the supplied axes, loading restores its saved placement.
Without an image, the points still load onto the supplied axes. Coordinates are
stored in their final units, so calibration and x_scale are not reapplied.
The loader accepts the original SCCircuits YAML format. Format 2.0 preserves
data for transition groups and unlabeled for untagged points, adds series
for text labels, and records image calibration under metadata. A series named
"0,1" remains distinct from transition (0, 1). SCCircuits'
TransitionFitter.load_from_yaml() can read the data section unchanged.
Groups retain point order internally; roundtripping YAML may regroup points by
label, so numeric point indices are session-local.
Call picker.disconnect() to release event handlers and forms without closing
the figure. Closing the window also disconnects automatically. Disconnecting
does not discard points or prevent export.
Development and releases
python -m pip install -e ".[dev,notebook]"
python -m pytest
ruff check src tests examples
python -m build
python -m twine check dist/*
CI tests supported Python environments, builds both distributions and checks
installation outside the source tree on Linux, macOS and Windows. PyPI
publishing is manual and disabled until PYPI_PUBLISH_ENABLED is set to true
after configuring a Trusted Publisher; see RELEASING.md.
Attribution
The original PointPicker was developed by Joan Caceres in SCCircuits. Extraction
started from SCCircuits commit c5e051a4dddc43b93a3cff5a8e3e80c698c00afd.
The original MIT copyright notice is preserved in LICENSE.
Metadata
Release files for mpl-pointpicker 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mpl_pointpicker-0.1.0.tar.gz | 73.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mpl_pointpicker-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 91.7 kB
Release files / mpl_pointpicker-0.1.0.tar.gz
| Download URL | mpl_pointpicker-0.1.0.tar.gz |
|---|---|
| Size | 73.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4f6118e89ed9f272689184b2950e33e8bbb25fb87174ea0028b6cf723dcf8e6e
|
|
BLAKE2b-256 checksum How to use checksums |
51fad63b16d5c4107b43fb66bae5b52ac6a37d1eb9e3fce77ca64f48c5162382
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / mpl_pointpicker-0.1.0-py3-none-any.whl
| Download URL | mpl_pointpicker-0.1.0-py3-none-any.whl |
|---|---|
| Size | 18.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ca6b227599d1d5ed3583a49bb30c4e215a9e7e22db74b7b2be4177f0974f5ebe
|
|
BLAKE2b-256 checksum How to use checksums |
5222d2d0035f3dbf0c9c8434fc76663ef65305a01b8cee82dac135f1707f49e7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|