・Pythonのwidget機能を使った測定用プログラムの作成について
最近新たに追加されたpythonの拡張機能'widget'を使用して、DMM6500における測定値読みと、Delay Stageを動かすプログラムを作成した。目標は時間分解測定を自動化することだが、pythonは基本テキストベースのプログラムを走らせるため、ユーザーにとって直感的にわかるようなシステムにならないのが難点だった。最近、測定開始ボタンなどのUIをpython上で利用できるwidgetという機能が追加され、直感的に測定を実行できるプログラムが作成可能となった。誰でも無料で使えるのも、pythonの利点。
インストールをおこなう: pip install ipywidgets
jupyter notebook あるいはannacondaを最新バージョンにしておかないとエラーが出る。 (annaconda prompt で conda update conda)
Delay stage: module/motor_ui.py
# ==== Jupyter motor control panel (ipywidgets) ====
import threading
from ipywidgets import Button, HBox, VBox, IntText, Label, Output, ToggleButtons
from IPython.display import display
import module.motorMove as motorMove #motorMove.pyは備忘録/pythonを使った外部機器制御/のページにある。
# ---- UI parts ----
step = IntText(value=60, description="相対step:", layout={'width':'220px'})
abspos = IntText(value=-12000, description="絶対pos:", layout={'width':'220px'})
mode = ToggleButtons(options=[("REL", "rel"), ("ABS", "abs")], value="rel",
description="モード:")
btn_minus = Button(description="◀︎ 負方向", tooltip="相対: -step 移動")
btn_plus = Button(description="正方向 ▶︎", tooltip="相対: +step 移動")
btn_go = Button(description="指定位置に移動", button_style='info')
btn_home = Button(description="原点(例:0)へ", button_style='warning')
btn_stop = Button(description="停止(実装あれば)", button_style='danger', disabled=True) # stop関数があれば有効化
log = Output(layout={'border':'1px solid #ccc'})
display(VBox([
HBox([mode]),
HBox([step, btn_minus, btn_plus]),
HBox([abspos, btn_go, btn_home]),
log
]))
# ---- helpers ----
def run_in_thread(func, *args, **kwargs):
t = threading.Thread(target=func, args=args, kwargs=kwargs, daemon=True)
t.start()
def log_print(*a):
with log:
print(*a)
def do_move(delta):
try:
resp = motorMove.move(delta)
log_print(f"[REL {delta}] -> {resp}")
except Exception as e:
log_print(f"[ERR REL {delta}] {e}")
def do_back(pos):
try:
resp = motorMove.back(pos)
log_print(f"[ABS {pos}] -> {resp}")
except Exception as e:
log_print(f"[ERR ABS {pos}] {e}")
# ---- callbacks ----
def on_minus(_):
if mode.value == "rel":
run_in_thread(do_move, -abs(step.value))
else:
run_in_thread(do_back, abspos.value - abs(step.value))
def on_plus(_):
if mode.value == "rel":
run_in_thread(do_move, abs(step.value))
else:
run_in_thread(do_back, abspos.value + abs(step.value))
def on_go(_):
run_in_thread(do_back, abspos.value)
def on_home(_):
run_in_thread(do_back, 0)
btn_minus.on_click(on_minus)
btn_plus.on_click(on_plus)
btn_go.on_click(on_go)
btn_home.on_click(on_home)
log_print("パネル準備完了。ボタンを押すと実行します。")