{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Pick event demo\n\nYou can enable picking by setting the \"picker\" property of an artist\n(for example, a Matplotlib Line2D, Text, Patch, Polygon, AxesImage,\netc.)\n\nThere are a variety of meanings of the picker property:\n\n* *None* - picking is disabled for this artist (default)\n\n* bool - if *True* then picking will be enabled and the artist will fire a pick\n  event if the mouse event is over the artist.\n\n  Setting ``pickradius`` will add an epsilon tolerance in points and the artist\n  will fire off an event if its data is within epsilon of the mouse event.  For\n  some artists like lines and patch collections, the artist may provide\n  additional data to the pick event that is generated, for example, the indices\n  of the data within epsilon of the pick event\n\n* function - if picker is callable, it is a user supplied function which\n  determines whether the artist is hit by the mouse event. ::\n\n     hit, props = picker(artist, mouseevent)\n\n  to determine the hit test.  If the mouse event is over the artist, return\n  hit=True and props is a dictionary of properties you want added to the\n  PickEvent attributes.\n\nAfter you have enabled an artist for picking by setting the \"picker\"\nproperty, you need to connect to the figure canvas pick_event to get\npick callbacks on mouse press events.  For example, ::\n\n  def pick_handler(event):\n      mouseevent = event.mouseevent\n      artist = event.artist\n      # now do something with this...\n\n\nThe pick event (matplotlib.backend_bases.PickEvent) which is passed to\nyour callback is always fired with two attributes:\n\nmouseevent\n  the mouse event that generate the pick event.\n\n  The mouse event in turn has attributes like x and y (the coordinates in\n  display space, such as pixels from left, bottom) and xdata, ydata (the\n  coords in data space).  Additionally, you can get information about\n  which buttons were pressed, which keys were pressed, which Axes\n  the mouse is over, etc.  See matplotlib.backend_bases.MouseEvent\n  for details.\n\nartist\n  the matplotlib.artist that generated the pick event.\n\nAdditionally, certain artists like Line2D and PatchCollection may\nattach additional metadata like the indices into the data that meet\nthe picker criteria (for example, all the points in the line that are within\nthe specified epsilon tolerance)\n\nThe examples below illustrate each of these methods.\n\n<div class=\"alert alert-info\"><h4>Note</h4><p>These examples exercises the interactive capabilities of Matplotlib, and\n    this will not appear in the static documentation. Please run this code on\n    your machine to see the interactivity.\n\n    You can copy and paste individual parts, or download the entire example\n    using the link at the bottom of the page.</p></div>\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\nimport numpy as np\nfrom numpy.random import rand\n\nfrom matplotlib.image import AxesImage\nfrom matplotlib.lines import Line2D\nfrom matplotlib.patches import Rectangle\nfrom matplotlib.text import Text\n\n# Fixing random state for reproducibility\nnp.random.seed(19680801)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Simple picking, lines, rectangles and text\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig, (ax1, ax2) = plt.subplots(2, 1)\nax1.set_title('click on points, rectangles or text', picker=True)\nax1.set_ylabel('ylabel', picker=True, bbox=dict(facecolor='red'))\nline, = ax1.plot(rand(100), 'o', picker=True, pickradius=5)\n\n# Pick the rectangle.\nax2.bar(range(10), rand(10), picker=True)\nfor label in ax2.get_xticklabels():  # Make the xtick labels pickable.\n    label.set_picker(True)\n\n\ndef onpick1(event):\n    if isinstance(event.artist, Line2D):\n        thisline = event.artist\n        xdata = thisline.get_xdata()\n        ydata = thisline.get_ydata()\n        ind = event.ind\n        print('onpick1 line:', np.column_stack([xdata[ind], ydata[ind]]))\n    elif isinstance(event.artist, Rectangle):\n        patch = event.artist\n        print('onpick1 patch:', patch.get_path())\n    elif isinstance(event.artist, Text):\n        text = event.artist\n        print('onpick1 text:', text.get_text())\n\n\nfig.canvas.mpl_connect('pick_event', onpick1)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Picking with a custom hit test function\nYou can define custom pickers by setting picker to a callable function. The\nfunction has the signature::\n\n hit, props = func(artist, mouseevent)\n\nto determine the hit test. If the mouse event is over the artist, return\n``hit=True`` and ``props`` is a dictionary of properties you want added to\nthe `.PickEvent` attributes.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "def line_picker(line, mouseevent):\n    \"\"\"\n    Find the points within a certain distance from the mouseclick in\n    data coords and attach some extra attributes, pickx and picky\n    which are the data points that were picked.\n    \"\"\"\n    if mouseevent.xdata is None:\n        return False, dict()\n    xdata = line.get_xdata()\n    ydata = line.get_ydata()\n    maxd = 0.05\n    d = np.sqrt(\n        (xdata - mouseevent.xdata)**2 + (ydata - mouseevent.ydata)**2)\n\n    ind, = np.nonzero(d <= maxd)\n    if len(ind):\n        pickx = xdata[ind]\n        picky = ydata[ind]\n        props = dict(ind=ind, pickx=pickx, picky=picky)\n        return True, props\n    else:\n        return False, dict()\n\n\ndef onpick2(event):\n    print('onpick2 line:', event.pickx, event.picky)\n\n\nfig, ax = plt.subplots()\nax.set_title('custom picker for line data')\nline, = ax.plot(rand(100), rand(100), 'o', picker=line_picker)\nfig.canvas.mpl_connect('pick_event', onpick2)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Picking on a scatter plot\nA scatter plot is backed by a `~matplotlib.collections.PathCollection`.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "x, y, c, s = rand(4, 100)\n\n\ndef onpick3(event):\n    ind = event.ind\n    print('onpick3 scatter:', ind, x[ind], y[ind])\n\n\nfig, ax = plt.subplots()\nax.scatter(x, y, 100*s, c, picker=True)\nfig.canvas.mpl_connect('pick_event', onpick3)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Picking images\nImages plotted using `.Axes.imshow` are `~matplotlib.image.AxesImage`\nobjects.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig, ax = plt.subplots()\nax.imshow(rand(10, 5), extent=(1, 2, 1, 2), picker=True)\nax.imshow(rand(5, 10), extent=(3, 4, 1, 2), picker=True)\nax.imshow(rand(20, 25), extent=(1, 2, 3, 4), picker=True)\nax.imshow(rand(30, 12), extent=(3, 4, 3, 4), picker=True)\nax.set(xlim=(0, 5), ylim=(0, 5))\n\n\ndef onpick4(event):\n    artist = event.artist\n    if isinstance(artist, AxesImage):\n        im = artist\n        A = im.get_array()\n        print('onpick4 image', A.shape)\n\n\nfig.canvas.mpl_connect('pick_event', onpick4)\n\nplt.show()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.14.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}