интерактивная посадка с python - PullRequest
0 голосов
/ 08 марта 2020

Я хочу дополнить набор точек данных полиномиальной функцией (что я обычно делаю с numpy .polyfit), но я хочу, чтобы пользователь мог интерактивно выбирать степень полинома. Вот пример того, что я пытаюсь сделать:

import sys
import numpy as np
import matplotlib.pyplot as plt
from pylab import *
from sklearn.metrics import mean_squared_error
fig, ax = plt.subplots()
x = np.arange(1,10,0.2)
y = np.sin(x)
ax.plot(x,y,'o',color='orange',markeredgewidth=0.3,markeredgecolor='k')
ax.set_xlim(0,10)
ax.set_ylim(-1.1,1.1)
def press(event):
  #fig.clf()
  fig.canvas.draw_idle()
  sys.stdout.flush()
  deg = int(event.key)
  coeffs = np.polyfit(x,y,deg)
  p = np.poly1d(coeffs)
  rms = sqrt(mean_squared_error(y, p(x)))
  fig.text(0.8,1.02, 'rms='+str(round(rms,4)), rotation=0, color='k',transform=ax.transAxes)
  with open('prova.txt', 'w') as filehandle:
    filehandle.write('#Coefficients for a n= '+str(deg)+' polynomial fit\n\n')
    for listitem in coeffs:
      filehandle.write('%s\n' % listitem)
  ln = plt.plot(x,p(x),'-',color='green',linewidth=0.8,zorder=0)
  fig.canvas.draw()
cid = fig.canvas.mpl_connect('key_press_event', press)
plt.show()
fig.canvas.mpl_disconnect(cid)
f = open('prova.txt','r')
cfs = loadtxt('prova.txt', usecols=(0),comments='#')
print(cfs)

Таким образом, можно эффективно подобрать точки, но графики, следующие за первым, перегружены. Если я опускаю '#' для fig.clf (), код обновляет соответствие, но отменяет точки.

1 Ответ

0 голосов
/ 08 марта 2020

При запуске создайте глобальную переменную с None

  txt = None
  ln = None

А внутри press() вы можете проверить, если вы уже присвоили plot и text и remove() it.

  global txt
  global ln

  if txt:
    txt.remove()
  txt = fig.text(0.8,1.02, 'rms='+str(round(rms,4)), rotation=0, color='k',transform=ax.transAxes)

  if ln:
    ln[0].remove()
  ln = plt.plot(x,p(x),'-',color='green',linewidth=0.8,zorder=0)

  fig.canvas.draw()

Или вы можете установить новые data и text

global txt
global ln

if txt:
    # replace text
    txt.set_text('rms={}'.format(round(rms,4)))
else:
    # create first time
    txt = fig.text(0.8, 1.02, 'rms={}'.format(round(rms,4)), rotation=0, color='k', transform=ax.transAxes)

if ln:
    # replace data
    ln[0].set_data(x, p(x))
else:              
    # create first time
    ln = plt.plot(x, p(x), '-', color='green', linewidth=0.8, zorder=0)

fig.canvas.draw()

Полный код

import sys
import numpy as np
import matplotlib.pyplot as plt
from pylab import *
from sklearn.metrics import mean_squared_error

# --- functions ---

def press(event):
    global txt
    global ln


    #fig.clf()
    fig.canvas.draw_idle()
    sys.stdout.flush()

    deg = int(event.key)

    coeffs = np.polyfit(x, y, deg)
    p = np.poly1d(coeffs)
    rms = sqrt(mean_squared_error(y, p(x)))

    with open('prova.txt', 'w') as filehandle:
        filehandle.write('#Coefficients for a n= {} polynomial fit\n\n'.format(deg))
        for listitem in coeffs:
            filehandle.write('{}\n'.format(listitem))

    if txt:
        txt.remove()
    txt = fig.text(0.8, 1.02, 'rms={}'.format(round(rms,4)), rotation=0, color='k', transform=ax.transAxes)

    if ln:
        ln[0].remove()
    ln = plt.plot(x, p(x), '-', color='green', linewidth=0.8, zorder=0)

    #if txt:
    #    txt.set_text('rms={}'.format(round(rms,4)))
    #else:
    #    txt = fig.text(0.8, 1.02, 'rms={}'.format(round(rms,4)), rotation=0, color='k', transform=ax.transAxes)

    #if ln:
    #    ln[0].set_data(x, p(x))
    #else:              
    #    ln = plt.plot(x, p(x), '-', color='green', linewidth=0.8, zorder=0)

    fig.canvas.draw()

# --- main ---

txt = None
ln = None

fig, ax = plt.subplots()
x = np.arange(1, 10, 0.2)
y = np.sin(x)
ax.plot(x, y, 'o', color='orange', markeredgewidth=0.3, markeredgecolor='k')

ax.set_xlim(0, 10)
ax.set_ylim(-1.1, 1.1)
cid = fig.canvas.mpl_connect('key_press_event', press)
plt.show()

#fig.canvas.mpl_disconnect(cid)
cfs = loadtxt('prova.txt', usecols=0, comments='#')
print(cfs)
...