質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1822閲覧

matplotlibのグラフ更新に関して

takes.it.easy

総合スコア19

Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/06/30 08:29

matplotlibのキャンバス上をマウスでクリックし、追加された点をスプライン補完するコードです。点を1つ追加あるいは1つ削除した際、表示される線を最新のもののみにしたいのですが、上手くいきません。

Python

1import matplotlib.pyplot as plt 2import numpy as np 3from scipy import interpolate 4 5 6def main(): 7 fig = plt.figure() 8 ClickAddPoints(fig).show() 9 10 11class ClickAddPoints: 12 def __init__(self, fig): 13 self.fig = fig 14 self.ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 15 self.x = [] 16 self.y = [] 17 self.xy = [] 18 self.points = self.ax1.scatter([], [], s=10, color='red', picker=100) 19 self.ax1.figure.canvas.mpl_connect('button_press_event', self.on_click) 20 self.ax1.figure.canvas.mpl_connect('key_press_event', self.on_key) 21 self.counter = 0 22 23 def calc_spline(self, x, y, point, deg): 24 tck, u = interpolate.splprep([x, y], k=deg, s=0) 25 u = np.linspace(0,1, num=point, endpoint=True) 26 spline = interpolate.splev(u, tck) 27 return spline[0], spline[1] 28 29 def remove_points(self): 30 self.xy.pop() 31 32 def update_plot(self): 33 self.ax1.figure.canvas.draw() 34 35 def on_click(self, event): 36 if event.button == 1: 37 # 前の線をクリアする場合は下の行をコメントアウトする。 38 # plt.cla() 39 if event.inaxes is not self.ax1: 40 return 41 42 self.x.append([event.xdata]) 43 self.y.append([event.ydata]) 44 self.xy.append([event.xdata, event.ydata]) 45 self.points.set_offsets(self.xy) 46 self.ax1.draw_artist(self.points) 47 self.ax1.figure.canvas.blit(self.ax1.bbox) 48 49 if 1 < len(self.xy) <= 2: 50 51 #self.xy.sort() 52 self.xx = [t[0] for t in self.xy] 53 self.yy = [t[1] for t in self.xy] 54 x1, y1 = self.calc_spline(self.xx, self.yy, 1000, 1) 55 plt.plot(x1, y1) 56 self.show() 57 self.update_plot() 58 elif 2 < len(self.xy) <= 3: 59 self.xx = [t[0] for t in self.xy] 60 self.yy = [t[1] for t in self.xy] 61 x1, y1 = self.calc_spline(self.xx, self.yy, 1000, 2) 62 plt.plot(x1, y1) 63 self.show() 64 self.update_plot() 65 elif len(self.xy) >= 4: 66 self.xx = [t[0] for t in self.xy] 67 self.yy = [t[1] for t in self.xy] 68 x1, y1 = self.calc_spline(self.xx, self.yy, 1000, 3) 69 plt.plot(x1, y1) 70 self.show() 71 self.update_plot() 72 else: 73 return 74 elif event.button == 3: 75 self.remove_points() 76 self.update_plot() 77 self.counter += 1 78 print('Count:{0}'.format(self.counter)) 79 80 81 82 def show(self): 83 self.ax1.set_xticks(np.linspace(0, 4, 5)) 84 self.ax1.set_yticks(np.linspace(0, 4, 5)) 85 self.ax1.set_aspect('equal') 86 plt.show() 87 88 def on_key(self, event): 89 if event.key == 'q': 90 return 91 92 93main()

plt.cfl()を追加しましたが、グラフがすべて削除されたのち、新しく点を打つことはできませんでした。
plt.cla()を使用した場合は意図しない場所に点が打たさりました。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

self.ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) としているので、
pltではなく、self.ax1に対して描画やcla()を行う必要があります。

このページの冒頭に書いてあるここがわかりやすいかもしれません。

(クリック点の描画をscatterにすると、spline曲線の更新と両立するうまいやり方がわからなかったので、下記コードでは、plot(x, y, 'ro')で代用しています)

lang

1import matplotlib.pyplot as plt 2import numpy as np 3from scipy import interpolate 4 5 6def main(): 7 fig = plt.figure() 8 ClickAddPoints(fig) 9 10 11class ClickAddPoints: 12 def __init__(self, fig): 13 self.fig = fig 14 self.ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 15 self.ax1.figure.canvas.mpl_connect('button_press_event', self.on_click) 16 self.ax1.figure.canvas.mpl_connect('key_press_event', self.on_key) 17 self.x = [] 18 self.y = [] 19 self.update_plot() 20 plt.show() 21 22 def calc_spline(self, x, y, point, deg): 23 tck, u = interpolate.splprep([x, y], k=deg, s=0) 24 u = np.linspace(0, 1, num=point, endpoint=True) 25 spline = interpolate.splev(u, tck) 26 return spline[0], spline[1] 27 28 def update_plot(self): 29 self.ax1.set_xticks(np.linspace(0, 4, 5)) 30 self.ax1.set_yticks(np.linspace(0, 4, 5)) 31 self.ax1.set_aspect('equal') 32 self.ax1.figure.canvas.draw() 33 34 def on_click(self, event): 35 if event.button == 1: 36 # コントロール点を追加 37 if event.inaxes is not self.ax1: 38 return 39 # 過去の座標と同一座標をクリックした場合は抜ける 40 if event.xdata in self.x and event.ydata in self.y: 41 return 42 self.x.append(event.xdata) 43 self.y.append(event.ydata) 44 self.redraw() 45 print('Added no.{} point at [{} {}]'.format( 46 len(self.x), self.x[-1], self.y[-1])) 47 elif event.button == 3: 48 # 直近のコントロール点を削除 49 if len(self.x) > 0: 50 self.x.pop() 51 self.y.pop() 52 self.redraw() 53 print('Removed no.{0} point'.format(len(self.x)+1)) 54 55 def redraw(self): 56 self.ax1.cla() 57 count = len(self.x) 58 if count > 0: 59 # クリック点の描画 60 self.ax1.plot(self.x, self.y, 'ro') 61 if count <= 1: 62 self.update_plot() 63 return 64 if count == 2: 65 deg = 1 66 elif count == 3: 67 deg = 2 68 elif count > 3: 69 deg = 3 70 else: 71 return 72 x1, y1 = self.calc_spline(self.x, self.y, 1000, deg) 73 # 線の描画 74 self.ax1.plot(x1, y1) 75 self.update_plot() 76 77 def on_key(self, event): 78 if event.key == 'q': 79 return 80 81 82main() 83

投稿2020/06/30 14:25

編集2020/06/30 15:18
patapi

総合スコア820

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takes.it.easy

2020/07/01 03:33

度々親切、丁寧な回答ありがとうございます!axesとfigureの関係性やコードの整理の仕方などとても参考になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問