Last active
April 13, 2023 20:56
-
-
Save ad-1/0a99017a076e491afcafc520359fdce7 to your computer and use it in GitHub Desktop.
Code accompanying a concise article exploring how to drag a 2D vector around a figure while users receive real-time updates through dynamically updating data.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # define 2D vector coordinates | |
| vector_coord_1 = np.random.rand(2) | |
| vector_coord_2 = np.random.rand(2) | |
| # plotting | |
| fig, ax = plt.subplots() | |
| vector_1 = ax.add_patch(mpatches.FancyArrowPatch((0, 0), vector_coord_1, mutation_scale=15)) | |
| vector_2 = ax.add_patch(mpatches.FancyArrowPatch((0, 0), vector_coord_2, mutation_scale=15)) | |
| draggable_vector_1 = DraggableVector(vector=vector_1) | |
| draggable_vector_2 = DraggableVector(vector=vector_2) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import matplotlib.patches | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import matplotlib.patches as mpatches | |
| class DraggableVector: | |
| def __init__(self, vector: matplotlib.patches.Patch): | |
| """ | |
| Initialize a new instance of the DraggableVector class. | |
| Parameters: | |
| vector (matplotlib.patches.Patch): the vector that should be made draggable. | |
| Returns: | |
| None | |
| """ | |
| self.vector = vector | |
| self.press = None | |
| self.cidpress = self.vector.figure.canvas.mpl_connect( | |
| "button_press_event", self.on_press | |
| ) | |
| self.cidmotion = self.vector.figure.canvas.mpl_connect( | |
| "motion_notify_event", self.on_motion | |
| ) | |
| self.cidrelease = self.vector.figure.canvas.mpl_connect( | |
| "button_release_event", self.on_release | |
| ) | |
| def on_press(self, event: matplotlib.backend_bases.MouseEvent): | |
| """ | |
| Detect mouse click, and store the data if it is on the vector. | |
| Parameters: | |
| event (matplotlib.backend_bases.MouseEvent): the mouse event that triggered the callback. | |
| Returns: | |
| None | |
| """ | |
| if event.inaxes != self.vector.axes: | |
| return | |
| contains, attrd = self.vector.contains(event) | |
| if not contains: | |
| return | |
| self.press = (0, 0), (event.xdata, event.ydata) | |
| def on_motion(self, event: matplotlib.backend_bases.MouseEvent): | |
| """ | |
| Update the vector's position when the mouse is moved over the vector. | |
| Parameters: | |
| event (matplotlib.backend_bases.MouseEvent): the mouse event that triggered the callback. | |
| Returns: | |
| None | |
| """ | |
| if self.press is None or event.inaxes != self.vector.axes: | |
| return | |
| self.vector.set_positions((0, 0), (event.xdata, event.ydata)) | |
| self.vector.figure.canvas.draw() | |
| def on_release(self, event: matplotlib.backend_bases.MouseEvent): | |
| """ | |
| Handle the release of the mouse button over the vector. | |
| Parameters: | |
| event (matplotlib.backend_bases.MouseEvent): the mouse event that triggered the callback. | |
| Returns: | |
| None | |
| """ | |
| self.press = None | |
| self.vector.figure.canvas.draw() | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import matplotlib.patches as mpatches |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class DraggableVector: | |
| def __init__(self, vector: matplotlib.patches.Patch): | |
| self.vector = vector | |
| self.press = False | |
| self.cidpress = self.vector.figure.canvas.mpl_connect( | |
| 'button_press_event', self.on_press) | |
| self.cidrelease = self.vector.figure.canvas.mpl_connect( | |
| 'button_release_event', self.on_release) | |
| self.cidmotion = self.vector.figure.canvas.mpl_connect( | |
| 'motion_notify_event', self.on_motion) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def on_motion(self, event: matplotlib.backend_bases.MouseEvent): | |
| if not self.press or event.inaxes != self.vector.axes: | |
| return | |
| self.vector.set_positions((0, 0), (event.xdata, event.ydata)) | |
| self.vector.figure.canvas.draw() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def on_press(self, event: matplotlib.backend_bases.MouseEvent): | |
| if event.inaxes != self.vector.axes: | |
| return | |
| contains, attrd = self.vector.contains(event) | |
| if not contains: | |
| return | |
| self.press = True |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def on_release(self, event: matplotlib.backend_bases.MouseEvent): | |
| self.press = False | |
| self.vector.figure.canvas.draw() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import matplotlib.patches | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import matplotlib.patches as mpatches | |
| class DraggableVector: | |
| def __init__(self, vector: matplotlib.patches.Patch): | |
| """ | |
| Initialize a new instance of the DraggableVector class. | |
| Parameters: | |
| vector (matplotlib.patches.Patch): the vector that should be made draggable. | |
| Returns: | |
| None | |
| """ | |
| self.vector = vector | |
| self.press = None | |
| self.cidpress = self.vector.figure.canvas.mpl_connect( | |
| "button_press_event", self.on_press | |
| ) | |
| self.cidmotion = self.vector.figure.canvas.mpl_connect( | |
| "motion_notify_event", self.on_motion | |
| ) | |
| self.cidrelease = self.vector.figure.canvas.mpl_connect( | |
| "button_release_event", self.on_release | |
| ) | |
| def on_press(self, event: matplotlib.backend_bases.MouseEvent): | |
| """ | |
| Detect mouse click, and store the data if it is on the vector. | |
| Parameters: | |
| event (matplotlib.backend_bases.MouseEvent): the mouse event that triggered the callback. | |
| Returns: | |
| None | |
| """ | |
| if event.inaxes != self.vector.axes: | |
| return | |
| contains, attrd = self.vector.contains(event) | |
| if not contains: | |
| return | |
| self.press = (0, 0), (event.xdata, event.ydata) | |
| def on_motion(self, event: matplotlib.backend_bases.MouseEvent): | |
| """ | |
| Update the vector's position when the mouse is moved over the vector. | |
| Parameters: | |
| event (matplotlib.backend_bases.MouseEvent): the mouse event that triggered the callback. | |
| Returns: | |
| None | |
| """ | |
| if self.press is None or event.inaxes != self.vector.axes: | |
| return | |
| self.vector.set_positions((0, 0), (event.xdata, event.ydata)) | |
| self.vector.figure.canvas.draw() | |
| def on_release(self, event: matplotlib.backend_bases.MouseEvent): | |
| """ | |
| Handle the release of the mouse button over the vector. | |
| Parameters: | |
| event (matplotlib.backend_bases.MouseEvent): the mouse event that triggered the callback. | |
| Returns: | |
| None | |
| """ | |
| self.press = None | |
| self.vector.figure.canvas.draw() | |
| # define 2D vector coordinates | |
| vector_coord_1 = np.random.rand(2) | |
| vector_coord_2 = np.random.rand(2) | |
| # plotting | |
| fig, ax = plt.subplots() | |
| vector_1 = ax.add_patch(mpatches.FancyArrowPatch((0, 0), vector_coord_1, mutation_scale=15)) | |
| vector_2 = ax.add_patch(mpatches.FancyArrowPatch((0, 0), vector_coord_2, mutation_scale=15)) | |
| draggable_vector_1 = DraggableVector(vector=vector_1) | |
| draggable_vector_2 = DraggableVector(vector=vector_2) | |
| ax.set_xlabel("x-axis") | |
| ax.set_ylabel("y-axis") | |
| ax.grid(True) | |
| ax.yaxis.grid(True, which="minor", linestyle="--") | |
| plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment