Проблема с блокировкой сюжета для интерактивного сюжета с использованием matplotlib.widgets - PullRequest
0 голосов
/ 14 июля 2020

Я пишу код, который строит необработанные данные эксперимента, и я пытаюсь управлять регрессией на этом графике, используя matplotlib.widget с виджетом Slider. Виджет изменяет подгоночный параметр регрессии и автоматически пересчитывает регрессию при изменении параметра. После того, как я нашел идеальный параметр (путем визуального осмотра регрессии), я хочу принять этот параметр и продолжить свой код. Проблема, с которой я столкнулся, заключается в том, что весь код запускается независимо от того, нажимаю ли я кнопку accept . Мне кажется, что это проблема с блокировкой, и попытка ответить на очень похожий вопрос не увенчалась успехом:

Продолжить код после закрытия matplotlib figure

Я прочитал, что это может быть проблема с графическим сервером, но я пробовал все в раскрывающемся списке своей IDE (Spyder 4.1.3 работает Python 3.7.6):

  • Inline
  • Automati c
  • Qt5
  • Qt4
  • Tkinter

Я не знаю, проблема ли это в графическом сервере (I ' м работает Qt5 в настоящее время) или ошибка в моем коде. Очень возможно, что это ошибка в коде, так как это мой первый go на python, но я не получаю никаких ошибок, и даже простой псевдокод вроде следующего не делает того, что ожидалось:

from matplotlib.pyplot import plot,show
plot([1,2,3])
show(block=True)

show()

print ('continue computation after plot closes')

Я также пробовал ответы, или, думаю, наоборот, в этих ссылках безрезультатно:

Неблокирующее построение с помощью Matplotlib

Есть ли способ отсоединить графики matplotlib, чтобы вычисления могли продолжаться?

Есть идеи, как я могу продолжить свой код после закрытия графика?

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

ps Мой реальный код следующий, хотя приведенного выше псевдокода должно быть достаточно (обратите внимание, что 95% доверительный интервал не reset, как хотелось бы, но это битва на другой день):

import numpy as np
import matplotlib.pyplot as plt
import csv
import math

from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, ConstantKernel as C
from matplotlib.widgets import Slider, Button

def kernreg(xx,yy,zz,aa):
    #Define the kernel regression function.
    #xx=Input x-data
    #yy=Input y-data
    #zz=Predicted x-values
    #aa=Passed value of alpha
    #Function outputs is the predicted y-values and mean squared error

    #Instantiate Gaussian Process model with a product-kernel consisting of a
    #radial-basis function kernel and a constant kernel
    kernel=C(1.0, (1e-3, 1e3))*RBF(10, (1e-2, 1e2))
    gp=GaussianProcessRegressor(kernel=kernel,alpha=aa,
                                optimizer='fmin_l_bfgs_b',
                                n_restarts_optimizer=25)
    #Fit to data using Maximum Likelihood Estimation of the parameters
    gp.fit(xx,yy)
    #Make the prediction on the meshed x-axis (ask for MSE as well)
    y_pred,sig=gp.predict(zz,return_std=True)
    return y_pred,sig


in2ft=1/12 #Convert inches to ft
fps2mph=1/1.4667 #Convert feet per second to miles per hour
fpsps2g=1/32.174049 #Convert feet per second squared to g
z_conf_int=1.96 #Z-score for a 95% confidence interval

#Import raw data; x [in], y[in], z[in]
with open('XYZ_data_20fps.csv','r') as datafile:
    readCSV=csv.reader(datafile, delimiter=',')
    
    x=[]
    y=[]
    z=[]
    
    for row in readCSV:
        x_i=float(row[0])
        y_i=float(row[1])
        z_i=float(row[2])
        
        x.append(x_i)
        y.append(y_i)
        z.append(z_i)

#Calculate the raw distance travelled
d=[] #Distance travelled [ft]
for i in range(len(x)-1):
    d_i=math.sqrt((x[i+1]-x[i])**2+(y[i+1]-y[i])**2+(z[i+1]-z[i])**2)*in2ft
    d.append(d_i)

#Sample frame queries 
frm_pred=np.atleast_2d(np.arange(1,len(x)+0.25,0.25)).T

#Frames analyzed (1=first frame)
frm=np.arange(1,len(x)+1)
frm_data=np.atleast_2d(frm[1:]).T


#Calling the kernel regression function for the initial guess
alpha_0=0.5
d_pred_0,sigma_0=kernreg(frm_data,d,frm_pred,alpha_0)

fig=plt.figure()
ax=fig.add_subplot(111)
fig.subplots_adjust(bottom=0.25)

#Draw the initial plot
plt.plot(frm_data,d,'o',color='black',label='Data')
[line]=plt.plot(frm_pred,np.array(kernreg(frm_data,d,frm_pred,alpha_0)  [0:1]).T,'b-',label='Prediction')
plt.xlabel("Frame")
plt.ylabel("Distance Travelled [ft]")
plt.legend(loc='best')

#Define an axes area and draw a slider in it
axis_color = 'lightgoldenrodyellow'
alph_slider_ax  = fig.add_axes([0.175, 0.1, 0.65, 0.03], facecolor=axis_color)
alph_slider = Slider(alph_slider_ax, chr(945), 0.01, 1.0, valinit=alpha_0)

#Define an action for modifying the line when any slider's value changes
def sliders_on_changed(val):
    line.set_ydata(kernreg(frm_data,d,frm_pred,alph_slider.val)[0:1])
    fig.canvas.draw_idle()
alph_slider.on_changed(sliders_on_changed)

#Add a button for resetting the parameters
reset_button_ax = fig.add_axes([0.175, 0.05, 0.1, 0.04])
reset_button = Button(reset_button_ax, 'Reset',color=axis_color,hovercolor='0.975')
def reset_button_on_clicked(mouse_event):
    alph_slider.reset()
reset_button.on_clicked(reset_button_on_clicked)

#Add a button for calculating the 95% confidence interval
conf_button_ax=fig.add_axes([0.175, 0.005, 0.35, 0.04])
conf_button=Button(conf_button_ax, 'Calculate Confidence Interval', color=axis_color,hovercolor='0.975')
def conf_button_on_click(mouse_event):
    ax.fill(np.concatenate([frm_pred,frm_pred[::-1]]),
         np.concatenate(
             [np.array(kernreg(frm_data,d,frm_pred,alph_slider.val)[0:1]).T-       z_conf_int*np.array(kernreg(frm_data,d,frm_pred,alph_slider.val)[1:2]).T,
                        (np.array(kernreg(frm_data,d,frm_pred,alph_slider.val)[0:1]).T+z_conf_int*np.array(kernreg(frm_data,d,frm_pred,alph_slider.val)[1:2]).T)[::-1]]),
         alpha=.5, fc='b', ec='None', label='95% Confidence Interval')
    ax.legend(loc='best') #Plot new legend with the confidence interval
conf_button.on_clicked(conf_button_on_click)

#Add a button to accept the chosen value of alpha
accept_button_ax=fig.add_axes([0.28, 0.05, 0.15, 0.04])
accept_button=Button(accept_button_ax,'Accept Value',color=axis_color,hovercolor='0.975')
mutable_object={}
def accept_button_on_click(mouse_event):
    alpha=alph_slider.val
    mutable_object['mouse_event']=alpha
    alpha=mutable_object['mouse_event']
    print(alpha)
    plt.close()
accept_button.on_clicked(accept_button_on_click)

print('THIS SHOULD RUN ONLY AFTER I PRESS ACCEPT')
print('REST OF COMPUTATIONS')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...