Вот основная абстракция программы и модуля.Виджеты ползунка Matplotlib должны вызывать пересчет экземпляров Data
, а затем обновлять график.
Каждый раз, когда обновляется ползунок, он должен передавать свое новое значение соответствующему методу, определенному во время создания ползунка.Например, перемещение первого ползунка должно отправить его значение в d1.set_a()
, что вызывает пересчет этих данных, а затем должно вызвать P.offsets()
(см. МОДУЛЬ) для обновления графика.
Вопрос: Как я могу получить эти пользовательские, сгенерированные скриптом ползунки для запуска объектов данных и графика для обновления?Разве экземпляры Slider Widgets предлагают более удобные методы, чем то, как я это делаю здесь?
ОСНОВНАЯ программа:
import numpy as np
from MODULE import Data, Plot
x0 = np.linspace(0, 10., 11)
y1, y2 = [0.5 * (1.0 + f(x0)) for f in (np.cos, np.sin)]
d1, d2 = Data('hey', x0, y1), Data('wow', x0, y2) # data generating objects
p = Plot('hey') # plot object
p.add_slider(d1, 'set_a', d1.a, (0.2, 1.0))
p.add_slider(d1, 'set_p', d1.p, (0.5, 2.0))
p.add_slider(d2, 'set_a', d2.a, (0.2, 1.0))
p.add_slider(d2, 'set_p', d2.p, (0.5, 2.0))
p.plotme((d1, d2))
Текущий результат, ползунки перемещаются, но не запускают пересчет / повторное построение:

МОДУЛЬ:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
class Plot(object):
def __init__(self, name):
self.name = name
self.sliders = []
self.axcolor = 'lightgoldenrodyellow'
self.fig = plt.figure()
def sliderfunc(self, value):
print('sliderfunc') # currently not getting here
for (obj, P) in self.OPs:
P.set_offsets(obj.xy.T)
self.fig.canvas.draw_idle()
def add_slider(self, obj, method, nominal, limits):
ybot = 0.03 * (len(self.sliders) + 1)
name = obj.name + '.' + method
ax_slider = plt.axes([0.25, ybot, 0.50, 0.02], facecolor=self.axcolor)
slider = Slider(ax_slider, name, limits[0], limits[1],
valinit=nominal)
slider.on_changed(getattr(obj, method)) # this may not be right
self.sliders.append(slider)
return slider
def plotme(self, objs):
ybot = 0.03 * (len(self.sliders) + 3)
A = plt.axes([0.15, ybot, 0.65, 0.50])
self.OPs = []
for obj in objs:
P = A.scatter(obj.x, obj.y)
self.OPs.append((obj, P))
plt.show()
class Data(object):
def __init__(self, name, x0, y0):
self.name = name
self.a = 1.0
self.p = 1.0
self.x0, self.y0 = x0, y0
self.setstuff(a=1.0, p=1.0)
def setstuff(self, a=None, p=None):
if a != None:
self.set_a(a)
if p != None:
self.set_p(p)
def set_a(self, a):
self.a = a
self.x = self.a * self.x0
self.y = self.y0**self.p
self.xy = np.vstack((self.x, self.y))
def set_p(self, p):
self.p = p
self.x = self.a * self.x0
self.y = self.y0**self.p
self.xy = np.vstack((self.x, self.y))