Я создал интерактивный сюжет, используя matplotlib
и следующий этот ответ.На графике используются ползунки, чтобы пользователь мог управлять вертикальными (ось Y) точками и подгонять к ним сплайн по мере их изменения.Код для достижения этой цели находится здесь:
import matplotlib.animation as animation
from matplotlib.widgets import Slider
import matplotlib as mpl
from matplotlib import pyplot as plt
import scipy.interpolate as inter
import numpy as np
func = lambda x: 0.1*x**2
#get a list of points to fit a spline to as well
N = 10
xmin = 0
xmax = 10
x = np.linspace(xmin,xmax,N)
#spline fit
yvals = func(x)
spline = inter.InterpolatedUnivariateSpline (x, yvals)
#figure.subplot.right
mpl.rcParams['figure.subplot.right'] = 0.8
#set up a plot
fig,axes = plt.subplots(1,1,figsize=(9.0,8.0),sharex=True)
ax1 = axes
interval = 100 # ms, time between animation frames
loop_len = 5.0 # seconds per loop
scale = interval / 1000 / loop_len
def update(val):
# update curve
for i in np.arange(N):
yvals[i] = sliders[i].val
l.set_ydata(yvals)
spline = inter.InterpolatedUnivariateSpline (x, yvals)
m.set_ydata(spline(X))
# redraw canvas while idle
fig.canvas.draw_idle()
X = np.arange(0,xmax+1,0.1)
ax1.plot (X, func(X), 'k--', label='original')
l, = ax1.plot (x,yvals,color='k',linestyle='none',marker='o',markersize=8)
m, = ax1.plot (X, spline(X), 'r-', label='spline')
ax1.set_yscale('linear')
ax1.set_xlim(0, xmax)
ax1.set_ylim(0,xmax)
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.grid(True)
ax1.yaxis.grid(True,which='minor',linestyle='--')
ax1.legend(loc=2,prop={'size':22})
sliders = []
for i in np.arange(N):
axamp = plt.axes([0.84, 0.8-(i*0.05), 0.12, 0.02])
# Slider
s = Slider(axamp, 'p{0}'.format(i), 0, 10, valinit=yvals[i])
sliders.append(s)
for i in np.arange(N):
#samp.on_changed(update_slider)
sliders[i].on_changed(update)
plt.show()
Я думаю, что пользовательский интерфейс был бы лучше, если бы можно было непосредственно нажимать на точки и перетаскивать их вертикально вверх или вниз.Какие функции интерактивного кода matplotlib
будут наиболее полезны для этого?Я просмотрел различные примеры виджетов , но не нашел ничего, что мне было бы легко увидеть как непосредственно полезное для этого.Наиболее близким кажется прямоугольник селектора , но я не уверен, как его адаптировать, чтобы получить то, что мне нужно.
РЕДАКТИРОВАТЬ:
Этот ответ , вероятно, может быть адаптирован, чтобы делать то, что мне нужно.Разница между этим и именно тем, что мне нужно, заключается в том, что пример выбирает точку (на основе щелчка мыши и перетаскивания) вдоль существующей линии и выделяет ее.Мне нужно щелкнуть и выбрать, какая существующая точка находится в пределах небольшого диапазона (если нет, то перетаскивание не должно ничего делать).Затем код должен изменить эту точку при ее перетаскивании и установить сплайн во время этого действия перетаскивания.Возможно, я смогу сделать это с помощью приведенного выше примера, потому что он позволил мне лучше понять, как использовать mpl_connect
для различных действий (и дал несколько примеров действий.
В конечном коде следует только перетаскивать точки по вертикали,но я думаю, что это ограничение будет легко встроить (т.е. использовать только y-координату щелчка мышью / отпускания).
EDIT 2:
Пример Poly Editor кажется, очень близко к тому, что мне нужно, я могу развиться из этого.