pyyeti.datacursor.DataCursor¶
- class pyyeti.datacursor.DataCursor(ax=None, figs=None, hover=True, mk_label=<function mk_label>, offsets=(-20, 20), bbox={'alpha': 0.5, 'boxstyle': 'round, pad=0.5', 'fc': 'gray'}, arrowprops={'arrowstyle': '->', 'connectionstyle': 'arc3, rad=0'}, followdot={'alpha': 0.7, 'color': 'green', 's': 130}, permdot={'alpha': 0.4, 'color': 'red', 's': 130})[source]¶
Class to show x, y data points and to allow selection of points for annotations.
- hover¶
If True, an annotated large green, semi-transparent dot is displayed that follows the mouse as long as the mouse is inside the axes. Note: setting this directly is possible; you just have to turn the DataCursor off and back on for the setting to take effect. For example:
from pyyeti.datacursor import DC DC.hover = False DC.off() DC.on()
- Type:
- mk_label¶
Function that returns an annotation label for a data point. Must accept a single SimpleNamespace argument that contains information about the selected data point. mk_label defaults to:
def mk_label(point): def tostr(xyz): if isinstance(xyz, numbers.Number): return f"{xyz:.5g}" return f"{xyz}" if point.ax.name == "polar": deg = np.rad2deg(point.x % (2 * np.pi)) label = ( f"θ: {tostr(point.x)} ({tostr(deg)}°)\n" f"rad: {tostr(point.y)}" ) else: label = f"x: {tostr(point.x)}\ny: {tostr(point.y)}" if point.z is not None: label += f"\nz: {tostr(point.z)}" if point.nlines > 1: label += f"\n{point.handle.get_label()}" return label
The SimpleNamespace
pointcontains the following attributes:attr
Description
ax
Axes handle
handle
Line2D or PathCollection handle for line
index
Index into the data vectors for data point
lines
Total number of lines on axes
n
Line number starting at 0
x,y,z
x, y, z coordinates of data point; z is None for 2D
dot
The
matplotlib.pyplot.scatter()(PathCollection) object handle. Note thatDataCursorignores these added annotation points when moused over; they are identified by the added attribute “_pyyeti_dc_point”.note
The annotation object handle from
matplotlib.pyplot.annotate().xy_note
The (x, y) coordinates for the note.
- Type:
function
- bbox¶
Defines the bbox parameter for
matplotlib.axes.Axes.annotate()- Type:
dict; optional
- arrowprops¶
Defines the arrowprops parameter for
matplotlib.axes.Axes.annotate()- Type:
dict; optional
- followdot¶
Typically defines the s, color, and alpha settings (and possibly others as desired) for
matplotlib.axes.Axes.scatter(). That function is used for drawing the “dot” on the plot that follows the mouse and highlights the currently selected data point.- Type:
dict; optional
- permdot¶
Similar to followdot except this is a “permanent” dot; this gets placed after left clicking.
- Type:
dict; optional
- points¶
Contains list of SimpleNamespace objects. Each “point” is as described above under the mk_label attribute.
- Type:
- xyz¶
If points have been selected and the datacursor has been turned off, the xyz attribute will be filled with the x, y, z data for the selected points for all axes. If there are no 3d plots, only the x and y columns will be present. The order of the rows follows the selection order (same order as points; the source of this data).
- Type:
2d ndarray or None
Notes
Having multiple data-cursors active at the same time is undesirable. Therefore, this module instantiates one DataCursor object called DC during the initial import. It is recommended to always use DC rather than instantiating new DataCursor objects. From within a script:
from datacursor import DC ... DC.getdata() # blocks until DataCursor is turned off via 't' DC.getdata(n) # blocks until user selects `n` points (or # DataCursor is turned off via 't')
From an interactive prompt:
from datacursor import DC DC.on() # doesn't block, but DC is active
Once the DataCursor is turned on, you’ll just mouse over the data to see selected data points. These operations are available (when the mouse is inside the axes):
Action
Description
left-click
Data point will be stored in the member list points.
right-click
Last point is deleted from the plot and from points.
typing ‘t’
Turns off DataCursor. To turn on, use
DC.on. Note that turning on will reset points.typing ‘D’
Deletes last point AND removes the line from the plot via
line_handle.remove(). Any older annotations are not deleted.To get data points from plots from within a script, use
DataCursor.getdata(). Enter the number of points or press ‘t’ to end blocking so the script will continue (seeDataCursor.getdata()).Once the DataCursor is turned off, the annotations become draggable. Note that, at least for some versions of Matplotlib, annotations sometimes become linked (moving one will move another). When that happens, try dragging a different annotation; this sometimes breaks the link.
Interactively, the member functions
DataCursor.on()andDataCursor.off()are used to turn the DataCursor on and off. These functions will update the internal state of the DataCursor to account for deleted or added items.DataCursor.getdata()callsDataCursor.on()internally.The following example plots some random data, calls
DataCursor.getdata()to wait for the user to optionally select data points and then turn the DataCursor off (with keystroke ‘t’). It then prints the selected points:import matplotlib.pyplot as plt import numpy as np from pyyeti.datacursor import DC rng = np.random.default_rng() x = np.arange(500)/250 y = rng.uniform(size=x.shape) fig = plt.figure('demo') fig.clf() ax = fig.add_subplot(1, 1, 1) ax.plot(x, y) DC.getdata() # use DC.pause if you want to drag boxes around before # continuing: DC.pause() print('x, y values of selected points are:') print(np.array([[p.x, p.y] for p in DC.points]))
Settings can be changed after instantiation. Here is an example of defining a new format for the annotation. Only the line label is included in the annotation. The example also changes the permanent dot to a gray pentagon:
import matplotlib.pyplot as plt import numpy as np from pyyeti.datacursor import DC def new_label(point): return (f'{point.handle.get_label()}\n' f'({point.x},{point.y:.2f})') DC.mk_label = new_label DC.permdot = dict(s=130, color='black', alpha=0.4, marker='p') rng = np.random.default_rng() plt.plot(rng.normal(size=50), label='Gaussian') plt.plot(rng.uniform(size=50), label='Uniform') DC.on()
For increased versatility, there are two optional functions the user can define that will be called when a point is added (left-click) and when a point is deleted (right-click). See
DataCursor.addpt_func()andDataCursor.delpt_func()for more information on the call signatures. Here is a simple example that just prints statements to the screen:import matplotlib.pyplot as plt import numpy as np from pyyeti.datacursor import DC def addpt(point): print(f'You selected ({point.x}, {point.y}, {point.z})') def delpt(point): print(f'You deleted ({point.x}, {point.y}, {point.z})') DC.addpt_func(addpt) DC.delpt_func(delpt) fig = plt.figure() ax = fig.add_subplot(projection="3d") rng = np.random.default_rng() coords = rng.normal(size=(6, 3)) dots = ax.scatter(*coords.T) ax.plot(*(coords.T + 0.1), "v") DC.on()
- __init__(ax=None, figs=None, hover=True, mk_label=<function mk_label>, offsets=(-20, 20), bbox={'alpha': 0.5, 'boxstyle': 'round, pad=0.5', 'fc': 'gray'}, arrowprops={'arrowstyle': '->', 'connectionstyle': 'arc3, rad=0'}, followdot={'alpha': 0.7, 'color': 'green', 's': 130}, permdot={'alpha': 0.4, 'color': 'red', 's': 130})[source]¶
Initialize the DataCursor.
- Parameters:
ax (axes object(s) or None; optional) – Axes object or list of axes objects as created by
matplotlib.pyplot.subplot()(for example). If None, all axes on all selected figures will be automatically included. Takes precedence over the figs input.figs (figure object(s) or None; optional) – Alternative to the ax input. If ax is not input, figs specifies a figure object or list of figure objects as created by
matplotlib.pyplot.figure(). If None, all applicable figures will be automatically included.hover (bool; optional) – Sets the hover attribute.
form1 (function; optional) – Sets the form1 attribute.
form2 (function; optional) – Sets the form2 attribute.
offsets (tuple; optional) – Sets the offsets attribute.
bbox (dict; optional) – Sets the bbox attribute.
arrowprops (dict; optional) – Sets the arrowprops attribute.
followdot (dict; optional) – Sets the followdot attribute.
permdot (dict; optional) – Sets the permdot attribute.
Methods
__init__([ax, figs, hover, mk_label, ...])Initialize the DataCursor.
addpt_func(func)Function to call on a left-click.
delpt_func(func)Function to call on a right-click.
getdata([maxpoints, msg])Suspend python while user selects points up to maxpoints.
off([stop_blocking])Turns off the DataCursor and optionally stops it from blocking
on([ax, figs, callbacks, reset])Turns on and (re-)initializes the DataCursor for current figures.
pause([msg])Suspend python so user can interact with plots (such as moving previously added annotations) before continuing.