matplotlib: самый эффективный способ обновить набор патчей клина - PullRequest
0 голосов
/ 04 декабря 2018

У меня есть графический интерфейс, который позволяет пользователю создавать наборы точек, используя фигуры (например, круг с центром в X, Y и диаметром D, с N точками, где X, Y, D и N являются входными данными, используя поля ввода).

Из сгенерированного набора точек я строю точки, а также вычисляю двумерный центроид и строю их.Для построения центроида я использую 4 клина для построения 4-квадрантного черно-белого круга.

Данные отображаются нормально (я инициализирую график рассеяния с пустым набором данных, а затем добавляю данные каждый разпользователь генерирует вход).Чтобы построить центроид, хотя я немного растерялся.Я могу рассчитать и построить центроид по заданному набору данных, но я не уверен в наиболее «эффективном» способе обновления.

Должен ли я инициализировать «пустой» символ центроида, а затем обновитьцентр клиньев каким-то образом (не уверен, как это сделать, учитывая мою функцию центроида) аналогично методу, используемому для полного набора данных, или я должен просто удалять и заново создавать центроид каждый раз, когда генерируется больше данных (и как бы ясделать это)?

Отсутствие кода для генерации всех точек данных и простого построения центроида дает:

import tkinter as tk
from tkinter import ttk
import numpy as np

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
from matplotlib.figure import Figure
from matplotlib.patches import Wedge, Circle
matplotlib.use("TkAgg")


class MainGUI(tk.Tk):

    def __init__(self):
        tk.Tk.__init__(self)
        self.title('Title')
        self.geometry('750x500')

        self.nb = ttk.Notebook(self)
        self.nb.grid(row=0, column=0, columnspan=5, rowspan=4, sticky='NESW')
        self.tab2 = ttk.Frame(self.nb)
        self.nb.add(self.tab2, text='Tab2')

        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        tab2_r = 8
        tab2_c = 4
        for i in range(tab2_r):
            self.tab2.rowconfigure(i, weight=1)
        for i in range(tab2_c):
            self.tab2.columnconfigure(i, weight=1)

        self.makeWidgets()
        self.initializePlot()

    def makeWidgets(self):
        self.Labels = []
        self.Entries = []
        self.labText = [('X Location:'), ('Y Location:')]

        self.xGrid = 1
        self.yGrid = int(np.ceil(len(self.labText) / self.xGrid))
        i = 0
        for j in range(0, self.xGrid + 1, 2):
            for k in range(self.yGrid):
                if(i == len(self.labText)):
                    break
                else:
                    self.label = tk.Label(self.tab2, text=self.labText[i])
                    self.label.grid(column=j, row=k + 8, sticky='SW')
                    self.Labels.append(self.label)
                    self.entry = tk.Entry(self.tab2)
                    self.entry.insert(0, '0.0000')
                    self.entry.grid(column=j + 1, row=k + 8, sticky='NS')
                    self.Entries.append(self.entry)
                    i += 1

        self.addBtn = tk.Button(self.tab2, text='Add Entry', command=self.plotstuff)
        self.addBtn.grid(column=self.xGrid + 1, row=self.yGrid + 9, sticky='NSEW')

    def initializePlot(self):
        self.fig = Figure(figsize=(1, 1), dpi=100)
        self.ptrnFig = self.fig.add_subplot(111)
        self.ptrnFig.axis('equal')
        self.ptrnFig.axis([-5, 5, -5, 5])
        self.ptrnFig.spines['left'].set_position('zero')
        self.ptrnFig.spines['bottom'].set_position('zero')
        self.ptrnFig.grid(True)
        self.canvas = FigureCanvasTkAgg(self.fig, self.tab2)
        self.canvas.draw()
        self.canvas.get_tk_widget().grid(column=0, row=0, columnspan=4, rowspan=5, sticky='NSEW')
        self.scat = self.ptrnFig.scatter([], [], c="b", marker="o")     # Used to plot full dataset

    def plotstuff(self):
        # self.scat.set_offsets(dataset) <---- Used to plot full dataset, updated each time data entered
        self.points = np.array([float(self.Entries[0].get()), float(self.Entries[1].get())], ndmin=2)
        self.cog = self.plotCOG((self.points[0, 0], self.points[0, 1]), 0.1, angle=0, ax=self.ptrnFig)
        self.canvas.draw_idle()

    def plotCOG(self, center, radius, angle=0, ax=None, colors=('w', 'k'), **kwargs):
        if ax is None:
            ax = plt.gca()

        # Some code here to delete old COG?

        theta1, theta2, theta3, theta4 = angle, angle + 90, angle + 180, angle + 270
        w1 = Wedge(center, radius, theta1, theta2, fc=colors[0], ec='k', **kwargs)
        w2 = Wedge(center, radius, theta2, theta3, fc=colors[1], ec='k', **kwargs)
        w3 = Wedge(center, radius, theta3, theta4, fc=colors[0], ec='k', **kwargs)
        w4 = Wedge(center, radius, theta4, theta1, fc=colors[1], ec='k', **kwargs)
        for wedge in [w1, w2, w3, w4]:
            ax.add_artist(wedge)


def main():
    MainGUI().mainloop()


if __name__ == '__main__':
    main()

Я пробовал несколько форм ax.remove (), таких как

for wedge in [w1, w2, w3, w4]:
    wedge.remove()

в начале функции plotCOG (после попытки проверить, построены ли клинья), но не может найти ничего, что работает.

Спасибо за помощь.

1 Ответ

0 голосов
/ 04 декабря 2018

Подход, кажется, правильный.Единственная проблема в том, что у вас нет ссылок на старые клинья.Таким образом, вы можете хранить их где-нибудь, чтобы иметь возможность использовать их позже.

def initializePlot(self):
    # ....
    self.wedges = []


def plotCOG(self, center, radius, angle=0, ax=None, colors=('w', 'k'), **kwargs):
    ax = ax  or plt.gca()

    for wedge in self.wedges:
        wedge.remove()

    # ..
    w1 = Wedge(..)
    w2 = Wedge(..)
    w3 = Wedge(..)
    w4 = Wedge(..)

    self.wedges = [w1, w2, w3, w4]
    for wedge in self.wedges:
        ax.add_artist(wedge)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...