matplotlib 多个地物的单击事件

6za6bjd0  于 2023-11-22  发布在  其他
关注(0)|答案(2)|浏览(247)

我想通过点击图中的值来提取图中的值,同时在此时添加标记/删除旧标记。我只对一个图执行此操作,但在我的实践案例中,我有多个图。
当我有多个图时,点击事件只对最近的图有效。点击其他图将打印出最后一个图的值/在最后一个图中添加标记。

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. %matplotlib qt
  4. # Function to get the closest actual value
  5. def find_nearest(array,value):
  6. idx = (np.abs(array-value)).argmin()
  7. return array[idx]
  8. # Function to ectract the value from the graph by clicking
  9. def onclick(event,x,y,fig):
  10. if event.inaxes is not None:
  11. ix = find_nearest(x,event.xdata )
  12. iy = y[np.where(x==ix)[0][0]]
  13. text = (f'x = {ix}, y = {iy}\n')
  14. ax1 = fig.get_axes()[0]
  15. # Update the plots
  16. if len(ax1.get_lines()) > 1:
  17. delete = ax1.get_lines()[-1]
  18. delete.remove()
  19. ax1.plot([ix],[iy],marker="x",color="b")
  20. fig.canvas.draw_idle()
  21. print(text)
  22. # test case
  23. x = np.arange(0,10,1)
  24. y1 = x
  25. y2 = x**2
  26. y3 = x**3
  27. f1 = [x,y1]
  28. f2 = [x,y2]
  29. f3 = [x,y3]
  30. functions = [f1,f2,f3]
  31. for f in functions:
  32. fig, ax1 = plt.subplots(1)
  33. ax1.plot(f[0],f[1])
  34. #plt.show()
  35. cid = fig.canvas.mpl_connect('button_press_event', lambda event: onclick(event,f[0],f[1],fig))

字符串
如果有人知道热修复它,这将是高度赞赏。
我已经试过把fig,ax 1和cid放入字典中,并调整函数参数,但这并没有改变任何东西。
有趣的是,如果我在没有循环的情况下绘制和调用函数,但是单独地进行3次,至少函数的坐标部分的检索工作。只有添加/删除标记不工作。
我在这里发现了一个类似的问题,但我不太明白答案。

6l7fqoea

6l7fqoea1#

我试着写一个代码多个情节,但我不认为这是可能的。所以,我想出了一个主意-当你运行代码,所有的情节显示:
x1c 0d1x的数据
然后你可以点击其中一个。例如,如果你点击第二个图,它会像这样打开,



您可以点击这个图,它将显示标记并在终端中输出坐标。如果您想访问其他图,只需关闭此窗口。3个图将出现。然后您可以选择例如,第三个。然后如果您想终止代码,只需关闭原始窗口(具有所有3个子图的窗口)
下面是我的代码:

  1. # Import modules
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. from matplotlib.animation import FuncAnimation
  5. # ------------------------------------------------------------------------------------------------------------------------------------------- #
  6. # Test data
  7. x = np.arange(0.0, 10.0, 1.0)
  8. y1 = x
  9. y2 = x**2
  10. y3 = x**3
  11. #
  12. x_data = [x, x, x]
  13. y_data = [y1, y2, y3]
  14. #
  15. colors = ["red", "blue", "green"] # color to identify which data is viewed
  16. # ------------------------------------------------------------------------------------------------------------------------------------------- #
  17. while True:
  18. # Define the figure and axes of each subplot
  19. # Documentation https://matplotlib.org/stable/gallery/subplots_axes_and_figures/subplots_demo.html
  20. fig, axs = plt.subplots(1, len(x_data), figsize=(16,16))
  21. # Axis added when viewing one subplot
  22. ax_added = None
  23. # Plot the data in each plot
  24. for i in range(len(x_data)):
  25. axs[i].plot(x_data[i], y_data[i], color=colors[i])
  26. # ------------------------------------------------------------------------------------------------------------------------------------------- #
  27. # Variable that stores which subplot is selected
  28. ax_selected_index = None
  29. ax_selected_index_copy = None
  30. # Boolean that keeps track if only one plot is displayed
  31. selected = False
  32. # Function to retrieve which subplot has been clicked
  33. def onClick1(event):
  34. global axs, ax_selected_index, ax_selected_index_copy
  35. # Iterate through each plot
  36. for i in range(len(axs)):
  37. # Check which plot has been clicked
  38. # Answer from https://stackoverflow.com/questions/25047846/determine-button-clicked-subplot
  39. if (event.inaxes == axs[i]):
  40. ax_selected_index = i
  41. ax_selected_index_copy = i
  42. return
  43. # ----- #
  44. # Define the coordinates of the mouse when clicked
  45. mouse_pos_click = [None, None]
  46. # Function to get mouse coordinates
  47. def onClick2(event):
  48. global mouse_pos_click
  49. # Saves x and y coordinates of mouse
  50. mouse_pos_click = [event.xdata, event.ydata]
  51. # ----- #
  52. def on_close(event):
  53. global selected
  54. # Close on first window
  55. if not selected:
  56. exit()
  57. # ----- #
  58. def animate(i):
  59. global axs, ax_selected_index, selected, mouse_pos_click, ax_selected_index_copy, ax_added
  60. # Exit if the user close the first window
  61. fig.canvas.mpl_connect('close_event', on_close)
  62. # Retrieve the clicked mouse coordinates
  63. # If mouse is click --> run onClick1 event
  64. plt.connect('button_press_event', onClick1)
  65. # Check whether user has clicked a subplot
  66. if ax_selected_index != None:
  67. for ax in axs:
  68. # Hide X and Y axes label marks
  69. ax.xaxis.set_tick_params(labelbottom=False)
  70. ax.yaxis.set_tick_params(labelleft=False)
  71. # Hide X and Y axes tick marks
  72. ax.set_xticks([])
  73. ax.set_yticks([])
  74. # Add another plot "on top" of axs
  75. ax_added = fig.add_subplot()
  76. # Plot the required graph
  77. ax_added.plot(x_data[ax_selected_index], y_data[ax_selected_index], color=colors[ax_selected_index])
  78. # Reset the selected index
  79. ax_selected_index = None
  80. # Update the boolean
  81. selected = True
  82. if selected:
  83. # Retrieve the coordinates of the mouse
  84. plt.connect('button_press_event', onClick2)
  85. # Check if user has clicked
  86. if mouse_pos_click[0] != None:
  87. # Find the closest actual value
  88. indx = (np.abs(x_data[ax_selected_index_copy]-mouse_pos_click[0])).argmin()
  89. # Clear the plot
  90. ax_added.clear()
  91. # Plot the line
  92. ax_added.plot(x_data[ax_selected_index_copy], y_data[ax_selected_index_copy], color=colors[ax_selected_index_copy])
  93. # Scatter the point
  94. ax_added.scatter(x_data[ax_selected_index_copy][indx], y_data[ax_selected_index_copy][indx], color="black", s=50)
  95. # Reset the mouse position
  96. mouse_pos_click = [None, None]
  97. # Output the coordinates
  98. print(f"Figure : {ax_selected_index_copy}")
  99. print(f"x = {x_data[ax_selected_index_copy][indx]}, y = {y_data[ax_selected_index_copy][indx]}")
  100. print("\n")
  101. animation = FuncAnimation(fig, animate, interval=50)
  102. # Display the plot
  103. plt.show()
  104. # ------------------------------------------------------------------------------------------------------------------------------------------- #

字符串
我希望这对你有帮助!

展开查看全部
gc0ot86w

gc0ot86w2#

我能够弄清楚它。某种程度上,问题在于循环.我不知道确切的原因,但当我把数字放入字典,然后单独执行点击事件时,它工作了。但是,当我试图通过循环来做这件事时,它不工作。如果有人知道这种奇怪行为的原因,我很乐意得到解释。
然而,我最终解决这个问题的方法是添加一个函数,它执行click事件。通过这样做,我可以再次使用循环。

  1. def access_click_event(figure,x,y):
  2. figure.canvas.mpl_connect('button_press_event', lambda event: onclick(event,x,y,figure))
  3. figures = {}
  4. for n,f in enumerate(functions):
  5. fig, ax1 = plt.subplots(1)
  6. figures[n] = fig
  7. ax1.plot(f[0],f[1])
  8. access_click_event(figures[n],f[0],f[1])

字符串

相关问题