0

亲爱的,

我编写了这段代码来计算图上两次鼠标点击之间的距离。现在,我正在尝试将计算出的偏移量向左或向右移动,以便两个图完全匹配。知道如何实现吗?我尝试正常加减,但没有奏效。

import matplotlib.pyplot as plt
from matplotlib.widgets import Cursor
import mplcursors
from math import sqrt
import numpy as np 
import tkinter as tk
from tkinter import simpledialog

class DistancePlot:
    def __init__(self):
        
        ROOT = tk.Tk()
        ROOT.withdraw()
        ROOT.geometry("500x200")
        #my_frame = Frame(ROOT)
        #my_frame.pack(fill="both", expand=True)

        USER_INP = (simpledialog.askinteger(title="Plot dialig", 
                                  prompt="Enter the number of the plots "))
        
        if USER_INP is not None: 
            def f(x):
                return np.sin(x) + np.random.normal(scale=0.1, size=len(x))
            self.x = np.linspace(1, 10)
            self.fig, self.ax= plt.subplots()
            for i in range(USER_INP):
                plt.plot(self.x, f(self.x))

       
            self.ax.set_xlabel('X-axis')
            self.ax.set_ylabel('Y-axis')

            self.d1 = (0.0, 0.0)
            self.d2 = (0.0, 0.0)

            self.first_click = True

            self.cursor=Cursor(self.ax, horizOn=True, vertOn=True, color='black', linewidth=1.0)

            self.fig.canvas.mpl_connect('button_press_event', self.onclick)

            mplcursors.cursor(hover=True)
            plt.show()
            
        else: 
            def quit(self):
                self.ROOT.destroy()
        
    def onclick(self, event):
        z1, r1 = event.xdata, event.ydata
        print(z1, r1)

        if self.first_click:
            self.first_click = False
            self.d1 = (z1, r1)
        else:
            self.first_click = True
            self.d2 = (z1, r1)
            distance = sqrt((((self.d1[0]) - (self.d2[0])) ** 2) + (((self.d1[1]) - (self.d2[1])) ** 2))
            print("The shift between ", self.d1, "and", self.d2, "is", distance)
    
            
dp = DistancePlot()

评论中的答案很有帮助,但这并不完全是我想要的,我尝试使用相同的逻辑来获得我的解决方案,但它不起作用,我会与你分享。

import matplotlib.pyplot as plt
from matplotlib.widgets import Cursor
import mplcursors
import numpy as np
import tkinter as tk
#from tkinter import simpledialog

class DistancePlot:
    def __init__(self):
        ROOT = tk.Tk()
        ROOT.withdraw()
        ROOT.geometry("500x200")
#        USER_INP = 1
        
        #random sine wave
        x = np.linspace(1, 10)
        def f(x):
            return np.sin(x) + np.random.normal(scale=0.1, size=len(x)) 
        #fixed sine wave 
        time= np.arange(0, 10, 0.1)
        amplitude   = np.sin(time)
        
        self.fig, self.ax = plt.subplots()
        self.ax.plot(x, f(x))
        self.ax.plot(time, amplitude)
        self.ax.set_xlabel('X-axis')
        self.ax.set_ylabel('Y-axis')
        self.d1 = np.zeros(2)
        self.d2 = np.zeros(2)

        self.first_click = True
        self.cursor = Cursor(self.ax, horizOn=True, vertOn=True, color='black', linewidth=1)
        self.fig.canvas.mpl_connect('button_press_event', self.onclick)
        mplcursors.cursor(hover=True)
        plt.show()
            

    def onclick(self, event):
        z1, r1 = event.xdata, event.ydata
        print(z1, r1)
        if self.first_click:
            self.first_click = False
            self.d1 = np.array((z1, r1))
        else:
            self.first_click = True
            self.d2 = np.array((z1, r1))
            #distance = sqrt((((self.d1[0]) - (self.d2[0])) ** 2) + (((self.d1[1]) - (self.d2[1])) ** 2))
            #print("The distance between ", self.d1, "and", self.d2, "is", distance)
            delta = self.d2 - self.d1
            print("The delta between ", self.d1, "and", self.d2, "is", delta)
            if (abs(self.d2[0]) > abs(self.d1[0])).all():
                self.ax.lines[0].set_data(self.ax.lines[0].get_data() - delta.reshape(2,1))
                self.ax.relim()
                self.ax.autoscale_view()
                plt.draw()
                
            else: 
                self.ax.lines[0].set_data(self.ax.lines[0].get_data() + delta.reshape(2,1))
                self.ax.relim()
                self.ax.autoscale_view()
                plt.draw()

dp = DistancePlot()

我想要的是使用参考图并将其与另一个图匹配,如果我添加的图领先我希望它被减去,如果它滞后我希望它向前移动,所以将它添加到增量中。

4

1 回答 1

1

这是一种方法,将第一条曲线移动到给定的距离。Numpy 数组用于简化循环。relim()autoscale_view()重新计算 x 和 y 限制以将所有内容再次放入边距内(如果预期位移很小,则可以跳过此步骤)。

import matplotlib.pyplot as plt
from matplotlib.widgets import Cursor
import mplcursors
from math import sqrt
import numpy as np
import tkinter as tk
from tkinter import simpledialog

class DistancePlot:
    def __init__(self):
        ROOT = tk.Tk()
        ROOT.withdraw()
        ROOT.geometry("500x200")
        USER_INP = 2
        # USER_INP = (simpledialog.askinteger(title="Plot dialig", prompt="Enter the number of the plots "))
        if USER_INP is not None:
            def f(x):
                return np.sin(x) + np.random.normal(scale=0.1, size=len(x))

            self.x = np.linspace(1, 10)
            self.fig, self.ax = plt.subplots()
            for i in range(USER_INP):
                self.ax.plot(self.x, f(self.x))
            self.ax.set_xlabel('X-axis')
            self.ax.set_ylabel('Y-axis')
            self.d1 = np.zeros(2)
            self.d2 = np.zeros(2)

            self.first_click = True
            self.cursor = Cursor(self.ax, horizOn=True, vertOn=True, color='black', linewidth=1)
            self.fig.canvas.mpl_connect('button_press_event', self.onclick)
            mplcursors.cursor(hover=True)
            plt.show()
        else:
            def quit(self):
                self.ROOT.destroy()

    def onclick(self, event):
        z1, r1 = event.xdata, event.ydata
        if self.first_click:
            self.first_click = False
            self.d1 = np.array((z1, r1))
        else:
            self.first_click = True
            self.d2 = np.array((z1, r1))
            distance = sqrt((((self.d1[0]) - (self.d2[0])) ** 2) + (((self.d1[1]) - (self.d2[1])) ** 2))
            delta = self.d2 - self.d1
            self.ax.lines[0].set_data(self.ax.lines[0].get_data() + delta.reshape(2,1))
            self.ax.relim()
            self.ax.autoscale_view()
            plt.draw()

dp = DistancePlot()

如果您只想左右移动,您可以使用set_xdata来仅更改 x 位置。下面的示例代码以给定的位移移动第二条曲线。如果你想向左移动,第二次点击应该在第一次的左边。

    def onclick(self, event):
        z1, r1 = event.xdata, event.ydata
        if self.first_click:
            self.first_click = False
            self.d1 = np.array((z1, r1))
        else:
            self.first_click = True
            self.d2 = np.array((z1, r1))
            delta_x = self.d1[0] - self.d2[0]
            self.ax.lines[1].set_xdata(self.ax.lines[1].get_xdata() + delta_x)
            self.ax.relim()
            self.ax.autoscale_view()
            plt.draw()
于 2021-07-11T14:50:36.897 回答