Is there a charting library where I can get the mouse coordinates in plot units? #5526
-
First Check
Example Codedef on_click(event):
if event.xdata is not None and event.ydata is not None:
logger.info(f"Clicked at: ({event.xdata:.2f}, {event.ydata:.2f})")DescriptionI am coming from R, where even the most basic charts can return the mouse position in the chart in user coordinates (i.e. not simple in pixels). Trying this with one of the charting libraries in NiceGUI/python.
Any suggestion for a library to do this easily? Something like: NiceGUI VersionAny Python Version3.13.9 BrowserChrome Operating SystemWindows Additional ContextNo response |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 13 replies
-
|
Looks like Transform.inverted will do the trick: Added later: Sorry for not reading carefully, which had used this method before. |
Beta Was this translation helpful? Give feedback.
-
|
In case someone needs it (the scaling is straightforward, but tedious to get right): from PIL import Image # noqa
from nicegui import ui, events
import matplotlib.pyplot as plt
format = "svg"
format = "png"
img_file = f"mousecoords.{format}"
# For simplicity, we only care for the x-value
left = 0.1
right = 0.9
top = 0.95
bottom = 0.25
width = 1000
height = 200
x_min = 80
x_max = 120
px = 1 / (plt.rcParams["figure.dpi"])
fig, ax = plt.subplots(figsize=(width * px, height * px))
fig.subplots_adjust(bottom=bottom, top=top, left=left, right=right)
ax.set_xlabel("Systolic blood pressure (mmHg)")
ax.set_xlim(x_min, x_max)
ax.set_ylim(-1, 1)
ax.axvline(100)
ax.axhline(0, color="grey", linewidth=0.2)
plt.savefig(img_file) # Use file detour for better testing
# Better hide this in a closure....
def x_scaled(x, x_min=x_min, x_max=x_max, left=left, right=right, img_width=width):
return (x_max - x_min) * (x - left * img_width) / (
(right - left) * img_width
) + x_min
def mouse_handler(e: events.MouseEventArguments):
ui.notify(f"image: {e.image_x:.1f}, user: {round(x_scaled(e.image_x),1))} ")
image = ui.interactive_image(
source=img_file,
on_mouse=mouse_handler,
events=["mousedown"],
)
ui.run() |
Beta Was this translation helpful? Give feedback.
-
|
@dmenne I found the following shorter solution (at least for PNG-based rendering): import io
import matplotlib.pyplot as plt
from PIL import Image
from nicegui import events, ui
fig, ax = plt.subplots()
fig.set_dpi(100)
ax.plot([80, 100, 120], [1, 2, 3], 'o-')
buffer = io.BytesIO()
plt.savefig(buffer)
buffer.seek(0)
img = Image.open(buffer)
def handle_click(e: events.MouseEventArguments):
x_data, y_data = ax.transData.inverted().transform((e.image_x, img.height - e.image_y))
ui.notify(f'image: ({e.image_x:.1f}, {e.image_y:.1f}), data: ({x_data:.1f}, {y_data:.1f})')
ui.interactive_image(img, on_mouse=handle_click)
ui.run() |
Beta Was this translation helpful? Give feedback.

Here is an alternative for SVG: