The mouse-over behavior to add a string to the message line
can quickly become too expensive to compute the hit list
in the time between mouse move events (particularly in the nbagg
and qt5agg backends) when the number of artists gets large.
This adds:
- a flag on the Axes objects to control if the hitlist should
be computed - an rcparam to control it
@blink1073
importmatplotlib.backend_basesasmbbfig,ax=plt.subplots()forjinrange(150):ax.plot(j+np.sin(np.arange(0,5000)))# fake mouse eventev=mbb.MouseEvent('motion_notify_event',fig.canvas,150,150)ev.inaxes=axax.mouseover=True%prunax.figure.canvas.manager.toolbar.mouse_move(ev)
17104 function calls (16654 primitive calls) in 0.038 seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 166 0.017 0.000 0.018 0.000 lines.py:36(segment_hits) 198 0.003 0.000 0.033 0.000 lines.py:384(contains) 229 0.002 0.000 0.002 0.000 {built-in method affine_transform} 198 0.002 0.000 0.003 0.000 path.py:212(_update_values) 323/171 0.001 0.000 0.003 0.000 transforms.py:2352(get_affine) 261/1 0.001 0.000 0.037 0.037 artist.py:333(hitlist) 202 0.001 0.000 0.001 0.000 {method 'reduce' of 'numpy.ufunc' objects} 408 0.001 0.000 0.001 0.000 weakref.py:101(__init__) 396 0.001 0.000 0.002 0.000 numeric.py:2428(seterr) 396 0.001 0.000 0.001 0.000 numeric.py:2524(geterr) 327 0.001 0.000 0.001 0.000 {built-in method array} 198 0.001 0.000 0.004 0.000 path.py:103(__init__) 337 0.000 0.000 0.000 0.000 {built-in method dot} 408 0.000 0.000 0.001 0.000 transforms.py:86(__init__) 198 0.000 0.000 0.007 0.000 transforms.py:1660(transform_path_affine) 353 0.000 0.000 0.002 0.000 transforms.py:1768(__init__) 412 0.000 0.000 0.000 0.000 __init__.py:879(__getitem__) 170 0.000 0.000 0.000 0.000 {built-in method concatenate} 371 0.000 0.000 0.001 0.000 transforms.py:1622(__init__) 364 0.000 0.000 0.000 0.000 {method 'nonzero' of 'numpy.ndarray' objects} 1 0.000 0.000 0.000 0.000 {built-in method showMessage} 219 0.000 0.000 0.002 0.000 transforms.py:1723(transform_affine) 524 0.000 0.000 0.000 0.000 {built-in method isinstance} 408 0.000 0.000 0.000 0.000 weakref.py:255(update) 396 0.000 0.000 0.000 0.000 {built-in method seterrobj} 248 0.000 0.000 0.001 0.000 numeric.py:394(asarray) 198 0.000 0.000 0.000 0.000 transforms.py:2662(_revalidate) 198 0.000 0.000 0.003 0.000 transforms.py:2687(get_transformed_path_and_affine) 1246 0.000 0.000 0.000 0.000 {built-in method len} 23 0.000 0.000 0.002 0.000 text.py:917(get_window_extent) 39 0.000 0.000 0.002 0.000 text.py:251(contains) 16 0.000 0.000 0.000 0.000 transforms.py:692(translated) 332 0.000 0.000 0.000 0.000 {method 'ravel' of 'numpy.ndarray' objects} 198 0.000 0.000 0.003 0.000 transforms.py:2703(get_affine) 792 0.000 0.000 0.000 0.000 {built-in method geterrobj} 437 0.000 0.000 0.000 0.000 transforms.py:1813(get_matrix) 167 0.000 0.000 0.000 0.000 transforms.py:2527(get_matrix) 400 0.000 0.000 0.000 0.000 path.py:221(vertices) 202 0.000 0.000 0.001 0.000 {method 'all' of 'numpy.ndarray' objects} 202 0.000 0.000 0.001 0.000 _methods.py:40(_all) 186/170 0.000 0.000 0.000 0.000 transforms.py:2313(_get_is_affine) 25 0.000 0.000 0.000 0.000 transforms.py:401(_get_bounds) 198 0.000 0.000 0.007 0.000 transforms.py:1656(transform_path) 25 0.000 0.000 0.000 0.000 transforms.py:779(__init__) 162 0.000 0.000 0.000 0.000 transforms.py:2209(get_matrix) 16 0.000 0.000 0.000 0.000 font_manager.py:786(get_size_in_points) 198 0.000 0.000 0.000 0.000 core.py:5776(isMaskedArray) 198 0.000 0.000 0.000 0.000 lines.py:663(_get_transformed_path) 4 0.000 0.000 0.000 0.000 linalg.py:455(inv) 39 0.000 0.000 0.000 0.000 text.py:880(get_position) 21 0.000 0.000 0.001 0.000 transforms.py:1292(transform) 42 0.000 0.000 0.000 0.000 weakref.py:149(__setitem__) 2 0.000 0.000 0.000 0.000 patches.py:653(_update_patch_transform) 16 0.000 0.000 0.000 0.000 font_manager.py:701(__hash__) 16 0.000 0.000 0.000 0.000 text.py:886(get_prop_tup) 49 0.000 0.000 0.000 0.000 {method 'copy' of 'numpy.ndarray' objects} 16 0.000 0.000 0.000 0.000 text.py:327(_get_layout) 242 0.000 0.000 0.000 0.000 artist.py:351(get_children) 202 0.000 0.000 0.000 0.000 path.py:235(codes) 198 0.000 0.000 0.000 0.000 cbook.py:753(is_numlike) 21 0.000 0.000 0.001 0.000 transforms.py:1388(transform_point) 214 0.000 0.000 0.000 0.000 figure.py:399(_get_dpi) 22 0.000 0.000 0.000 0.000 transforms.py:162(set_children) 21 0.000 0.000 0.000 0.000 transforms.py:2328(transform_affine) 4 0.000 0.000 0.000 0.000 {built-in method point_in_path} 2 0.000 0.000 0.001 0.000 patches.py:673(contains)
vs
ax.mouseover = False%prun ax.figure.canvas.manager.toolbar.mouse_move(ev) 13 function calls in 0.000 seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.000 0.000 {method 'emit' of 'PyQt5.QtCore.pyqtBoundSignal' objects} 1 0.000 0.000 0.000 0.000 {built-in method exec} 1 0.000 0.000 0.000 0.000 {built-in method statusBar} 1 0.000 0.000 0.000 0.000 backend_bases.py:2805(mouse_move) 1 0.000 0.000 0.000 0.000 <string>:1(<module>) 1 0.000 0.000 0.000 0.000 backend_qt5.py:494(_show_message) 1 0.000 0.000 0.000 0.000 backend_bases.py:2789(_set_cursor) 1 0.000 0.000 0.000 0.000 backend_qt5.py:664(set_message) 1 0.000 0.000 0.000 0.000 {built-in method showMessage} 1 0.000 0.000 0.000 0.000 _base.py:3070(format_coord) 1 0.000 0.000 0.000 0.000 _base.py:3110(get_navigate) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 1 0.000 0.000 0.000 0.000 {built-in method len}
These are on a newish i7 desktop, I was getting a ms/Line2D object on a 1.5 year old mobile i5 with power saving turned up to 11.
The mouse-over behavior to add a string to the message line
can quickly become too expensive to compute the hit list
in the time between mouse move events (particularly in the nbagg
and qt5agg backends) when the number of artists gets large.
This adds:
be computed
@blink1073
vs
These are on a newish i7 desktop, I was getting a ms/Line2D object on a 1.5 year old mobile i5 with power saving turned up to 11.