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

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

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

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

639閲覧

マウスホイールを用いて画像を切り替えるプログラムで、違うパソコンだと動作しない。matplotlibを用いています。

dendendenjirou

総合スコア40

Matplotlib

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

1グッド

1クリップ

投稿2022/11/21 18:29

前提

現在、Pythonのmatplotlibを用いて画像表示を行い
マウスホイールを使って画像切り替えを行うプログラムを組みました。(main.py)

あるパソコンでは正常に動作するのですが
違うパソコンでは動作しません。

main.pyのコードはどこも変更しておらず、USBにて移動しただけです。

また、動作しないパソコン上では特に、エラー等は出ていません

該当のソースコード

Python main.py

1class Pixarr: 2 3 def __init__(self, filenames, row, columns): 4 self.filenames = filenames 5 self.row = row 6 self.columns = columns 7 self.arr = np.zeros((len(self.filenames), row, columns), dtype='int16') 8 9 for i in tqdm((range(len(filenames)))): 10 if len(filenames) == 1: 11 dcm = pydicom.dcmread(filenames[i]) 12 self.arr = dcm.pixel_array 13 else: 14 for i in range(len(filenames)): 15 dcm = pydicom.dcmread(filenames[i]) 16 img_no = dcm[0x0020, 0x0013].value 17 self.arr[img_no - 1] = dcm.pixel_array 18 19 if dcm[0x0008, 0x0070].value == "TOSHIBA": 20 wl = dcm[0x0028, 0x1050].value 21 ww = dcm[0x0028, 0x1051].value 22 23 else: 24 wl = dcm[0x0028, 0x1050].value[0] 25 ww = dcm[0x0028, 0x1051].value[0] 26 self.arr = self.arr - 1024 27 28 self.ww_low = wl - ww // 2 29 self.ww_high = wl + ww // 2 30 31 32def wheel_scroll(event): 33 global sl, f0, x, y 34 if event.button == 'down': 35 sl += 1 36 if sl > len(f0.filenames) - 1: 37 sl = 0 38 39 if event.button == 'up': 40 sl -= 1 41 if sl < 0: 42 sl = len(f0.filenames) - 1 43 44 show_img() 45 46def key_press(event): 47 global sl, f0, x, y 48 49 if event.key == 'down': 50 sl += 1 51 if sl > len(f0.filenames) - 1: 52 sl = 0 53 54 if event.key == 'up': 55 sl -= 1 56 if sl < 0: 57 sl = len(f0.filenames) - 1 58 59 show_img() 60 61 62def enter_axes(event): 63 global ent_ax, axs 64 65 axs = {ax1: 'ax1', ax2: 'ax2'} 66 try: 67 ent_ax = axs[event.inaxes] 68 except KeyError: 69 pass 70 71 72def mouse_click(event): 73 global fig, ax1, ax2, ax3, ax4, sl, x, y, ent_ax, axs, pat 74 75 x, y = int(event.xdata), int(event.ydata) 76 77 if event.button == 1 and (ent_ax == "ax1" or ent_ax == "ax2"): 78 pat = '1' 79 80 81 show_img() 82 83 print(event.button) 84 85def show_img(): 86 global fig, ax1, ax2, ax3, ax4, f0, arr_dispersion, sl, pat, x, y, ent_ax, axs 87 88 89 try: 90 ax1.cla(), ax2.cla(), ax3.cla(),ax4.cla() 91 except NameError: 92 ax1.cla(), ax2.cla() 93 94 area =10 95 96 if pat == '1': 97 c1 = patches.Rectangle(xy=(x - area, y - area), width=area * 2, height=area * 2, ec='red', fill=False) 98 ax1.add_patch(c1) 99 c2 = patches.Rectangle(xy=(x - area, y - area), width=area * 2, height=area * 2, ec='red', fill=False) 100 ax2.add_patch(c2) 101 102 ax3 = fig.add_subplot(2, 2, 3) 103 ax3.axes.xaxis.set_visible(False), ax3.axes.yaxis.set_visible(False) 104 ax3 =sns.heatmap(f0.arr[sl,y - area:y + area, x - area:x + area], annot=True, fmt="d", annot_kws={"size": 6}, 105 cmap='bone', cbar=None, vmin=f0.ww_low, vmax=f0.ww_high) 106 107 ax4 = fig.add_subplot(2, 2, 4) 108 ax4.axes.xaxis.set_visible(False), ax4.axes.yaxis.set_visible(False) 109 ax4 =sns.heatmap(arr_dispersion[sl, y - area:y + area, x - area:x + area], annot=True, fmt="d", annot_kws={"size": 6}, 110 cmap='bone', cbar=None, vmin=f0.ww_low * f0.ww_low, vmax=f0.ww_high * f0.ww_high) 111 112 ax1.imshow(f0.arr[sl], cmap='bone', vmin=f0.ww_low, vmax=f0.ww_high) 113 114 115 ax2.imshow(arr_dispersion[sl], cmap="jet", norm=Normalize(vmin=800, vmax=2400)) 116 117 fig.canvas.mpl_connect('scroll_event', wheel_scroll) 118 fig.canvas.mpl_connect('axes_enter_event', enter_axes) 119 fig.canvas.mpl_connect('button_press_event', mouse_click) 120 fig.canvas.mpl_connect("key_press_event", key_press) 121 122 plt.show() 123 124 125def main(): 126 global fig, ax1, ax2, ax3, ax4, f0, arr_dispersion, sl, pat 127 128 filenames = fs.directory() 129 dcm = pydicom.dcmread(filenames[0]) 130 row, columns = dcm.pixel_array.shape[0], dcm.pixel_array.shape[1] 131 f0 = Pixarr(filenames, row, columns) 132 133 stan = 10 134 arr_dispersion = copy.deepcopy(f0.arr) 135 136 sl, pat, x, y = 0, 0, 0 , 0 137 138 fig = plt.figure(figsize=(18, 18)) 139 ax1 = fig.add_subplot(2, 2, 1) 140 ax2 = fig.add_subplot(2, 2, 2) 141 142 fig.set_facecolor('#434343') 143 plt.subplots_adjust(left=0, right=1, bottom=0, top=1, wspace=0.02, hspace=0.005) 144 145 ax1.axes.xaxis.set_visible(False), ax1.axes.yaxis.set_visible(False) 146 ax2.axes.xaxis.set_visible(False), ax2.axes.yaxis.set_visible(False) 147 148 149 show_img() 150 151 152if __name__ == '__main__': 153 sys.setrecursionlimit(5000) 154 main()

試したこと

仮想環境や、Pythonのバージョン等の影響があるのかなと思い
Pythonのバージョンや、その他のライブラリーのバージョンも揃えましたが状況は改善していません。

ただ、違うところとしてはmatplotlibのツールボタンの表示される位置が違っています。
正常に動くPCでは下部に。動かないPCでは上部に表示されています。
また正常に動かないPCでは一度「Zoom/Pan」のボタンを押すことで左右のマウスイベントが動作します。しかし、マウスホイールの動作は動きません。
また、マウスホイールを動かし、左右どちらかのクリックを押すと、画像が切り替わります。

イメージ説明

補足情報(FW/ツールのバージョンなど)

OSは正常に動くPC、動かないPC共にWindows11です。

読みずらいコードで申し訳ございませんが、何卒宜しくお願い致します。

teamikl👍を押しています

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

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

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

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

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

y_waiwai

2022/11/21 22:57

動かない、で終わってしまわないで、せめてホイールのイベント関数が実行されるかどうかをチェックしてみましょう。
dendendenjirou

2022/11/21 23:06

失礼いたしました。 イベントは実行されています。 よろしくお願いいたします。
y_waiwai

2022/11/21 23:15

なら次に、そのイベント関数で、event.buttonってやつがどんな値なのかを見てみては。
teamikl

2022/11/21 23:51

問題が再現する・実行可能なコードを掲載してください。 import 文がありませんが、コード冒頭は省略されてますか? matplotlib はGUIのバックエンドが選択できるのですが、 未選択の場合は、環境(設定ファイル・環境変数)により異なる事があります。
dendendenjirou

2022/11/22 00:09

teammikl様 import文、抜けていました。申し訳ございません。 以下となります。 import fileselect as fs import numpy as np import pydicom import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap, BoundaryNorm import matplotlib.patches as patches from matplotlib.colors import Normalize from tqdm import tqdm import copy import cv2 import seaborn as sns import sys なお、
dendendenjirou

2022/11/22 00:14 編集

y_waiwai様 def wheel_scroll(event): 内に print(event.button) と記載してイベントの値 「down」 「up」 の確認はしており,動作するPC、動作しないPCにおいても同一の値となっております。
teamikl

2022/11/22 00:15

import 文のある冒頭辺りで確認したかった情報は、 matplotlib.use でのバックエンドの選択があるかどうかです。 なさそうなので、バックエンドの違いが濃厚かな。 回答に関連情報を載せたので、まずは どのバックエンドが選択されてるかを調べて見て下さい。 確認方法 >>> import matplotlib >>> matplotlib.get_backend()
teamikl

2022/11/22 00:26

コメント内の情報は確認漏れしてました。 イベントハンドラ自体が呼ばれているのであれば、 私の回答の情報は該当しなさそうですね。 イベント周りの挙動はバックエンドにより異なる場合があるようなので、 確認は取っておいた方が良いと思います。
teamikl

2022/11/22 00:43 編集

コードで気になる点は、イベントループがネストしている点。 (GUI等のイベント駆動型プログラムでは、イベントが正常に伝搬されない原因になります) plt.show() がイベントループで、 イベントハンドラに設定した関数は、その内部で呼ばれるのですが、 イベントハンドラ内で show_img -> plt.show() イベントループを再び呼んでいます。 恐らくその対策に sys.setrecursionlimit で回数を増やしているのでしょうが、 これは正しい対策ではなく、イベントループ自体をネストしないような設計にすべきです 片方のPCで正常に動作しているとしても、誤ったイベントループの使い方で、 長時間操作するとrecursionlimit の制限に到達しエラーになります。 # show_img関数内で呼び出して、スタックが増えるかどうかを確認してみてください。 import inspect depth = len(inspect.stack()) print(f"call stack depth: {depth}") ※ マウスホィールの問題との関連は、現時点では解りません。
guest

回答1

0

ベストアンサー

恐らく該当しそうなバグ報告
https://github.com/matplotlib/matplotlib/issues/22211
https://github.com/matplotlib/matplotlib/issues/17513
https://github.com/wxWidgets/Phoenix/issues/1794

matplotlib のバックエンドが wx 且つ、
特定のバージョン・特定のプラットフォームのwxPython で
マウスホィール・イベントが効かないことが報告されてます。

正しく動く環境のバックエンドを調べ、
matplotlib.use で明示的に選択して見て下さい。

https://matplotlib.org/stable/users/explain/backends.html

投稿2022/11/22 00:05

編集2022/11/22 00:51
teamikl

総合スコア8664

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

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

jbpb0

2022/11/22 00:30

> 違うところとしてはmatplotlibのツールボタンの表示される位置が違っています。 正常に動くPCでは下部に。動かないPCでは上部に表示されています。 からも、バックエンドが違ってる可能性がありますね
dendendenjirou

2022/11/22 00:59

teamikl様、jbpb0様 ありがとうございます。本当にありがとうございます。 解決しました。 動かない方のbackendは Qt5Agg で、動く方は TkAgg でしたので ご指摘通り、 matplotlib.use('TkAgg') の一文で解決することができました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問