教育用GM管開発を振り返って(9)

放射線教育支援サイト「らでぃ」の実験集に掲載した「Pythonでパルス波形を見る実験」のPythonプログラムについて解説する。Pythonについては全くと言っていい専門外なので、間違って理解しているところがあるかもしれないが、一例として挙げたプログラムの実行は確認している。以下の解説は、むしろPythonをこれから始める人に見ていただきたい。


Pythonの実装など


プログラム開発は、Windows10で行った。64bitの Windows10でPythonを実装し、ライブラリーとして、音声などのアナログ信号を扱うPyAudioと、グラフを表示するMatPlotLibなどをインストールした。インストールの際の注意事項、Pythonの使用方法、パソコンなどへの接続方法、Visial Basic 6ユーザーを念頭にした文法の違いを以下に挙げる。

(1) Pythonをインストールするには、https://www.python.jp/install/windows/install.html にアクセスし、記述に従ってインストールする。
具体的には、https://pythonlinks.python.jp/ にアクセスし、PythonのバージョンとパソコンのOSを選んでインストール・パッケージをダウンロード、実行する。その際、
"Add Python 3.x to PATH"にチェックを入れてからインストールをクリックする。


(2) 必要なライブラリーをインストールする。ライブラリーはpipコマンドでインストールできる。
例えば、OpenCVは、Windows画面の左下にある「ここに入力して検索」をクリックし、cmdと入力してコマンドプロンプトを開き、pip install opencv-python と入力する。(https://qiita.com/fiftystorm36/items/1a285b5fbf99f8ac82eb 参照)
PyAudioの場合は、インストールする前にMicrosoft Visual C++ Build Tool をインストールしておく。具体的には、https://visualstudio.microsoft.com/ja/downloads/ を開き、下の方にある「Visual Studio 2019のツール」から、「Build Tools for Visual Studio 2019」をダウンロードする。さらに、パッケージを開いて、「C++ Build Tools」にチェックを入れ、右側のオプションのチェックは全て外して、「インストール」をクリックする。なお、Cドライブに1.67GByte以上の空き容量が必要なので確保しておくこと。
次に、https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio を開き、Pythonのバージョン3.8とWindows 32ビットを選んでwhlファイルをダウンロードする。ファイルはユーザーのホーム・ディレクトリーに移動し、pip install 「ダウンロードしたファイル名(PyAudio-0.2.11-cp38-cp38-win32.whlなど)」を入力する。
また、Matplotlibもインストールしておく。


(3) Pythonファイルは、ユーザーのホーム・ディレクトリーに置き、「Pythonファイル名.py」をダブルクリックして起動し、終了にはグラフの「閉じる」を利用すればキーボード操作を省ける。


(4) GM計数装置のイヤホン端子とパソコンのマイク入力端子またはタブレットの4極入力端子をシールド・ケーブルで接続する。その際、0.022μF~0.1μF程度のコンデンサを並列接続して使用する。次に、「コントロールパネル」から「オーディオデバイスの管理」を開いて、「録音」→当該「マイク」の「プロパティ」で録音の「レベル」が中位になるようスライダーを調節または確認する。このタブレットはタッチパネルの動作が不安定なので、必要に応じてマウスを利用する。


(5) Pythonの学習について
Pythonは、昔のBasicやFortranなどに慣れた人ならなじみやすいコマンドライン入力方式となっている。GUIやタッチパネルに慣れた人には難しいかもしれない。
パソコンのプログラミング未経験者ならば、Python入門編から勉強する必要があるが、コマンドライン入力に慣れた人の場合は、逆に、似ているが違う使い方に注意する必要がある。Pythonコードの書き方の基本は、PEP8 Style Guide for Python Code というドキュメントにある。(https://pep8-ja.readthedocs.io/ja/latest/


(6) Visual Basic 6との文法の違い

  1. コードが基本的に変数と制御文でできていることは、ほかの言語と変わらない。ただし、Basicなどではサブルーチン、Visual Basicではプロシージャーといったコードの「くくり」はない。敢えて言えば関数(def)がそれに似ている。
  2. ライブラリーの機能を使うにはライブラリーをimportすれば、外部関数として使用できる。ただし、ライブラリーの名称または略称(cv2、plt、npなど)を関数の前に付ける必要がある。
  3. 反復処理をするためのfor文、if文やwhile文などの制御文の末尾には、コロンが必要で、次の行から制御文の範囲の終わりまでは4字の字下げをするだけで、終わりを示すコマンドはない。字下げの字数は同じでないといけない。
  4. 数字はそのままでは文字として扱われるので、変数aの値を数として使用するにはint(a)のようにして整数化する。逆に数字を文字として出力するにはstr()を使う。
  5. 関数の内外で同じ変数を使用する場合は、global宣言をするが、変数をdefの前に初期化しておき、global宣言はdef内で行う。予めglobal宣言をするVisual Basicなどとは違うので注意したい。
  6. 行列にはlist[]とarrey()があって別の機能なので、混在する場合は、お互いに変換する必要がある。
  7. Visual Basicでのdo文はないので、for文を使う。
  8. List内は、[始めの要素:終わりの要素:インクリメント]となっているが、それぞれ省略が可能で、「始めの要素」を省略すると最初から、「終わりの要素」を省略すると最後まで、「インクリメント」を省略すると、インクリメントは1と解釈される。
  9. if文やfor文で、「何もしない」コマンドは、passとcontinueがあって、passは「何もしない」、continueは「次のループに進む」の意味になる。ループの外に出るのは、breakを使う。

Pythonでパルス波形を見る実験」のプログラム例


最初に、計数に必要な検出パルスの最大値やノイズレベルを知り、そもそも検出できているかどうかをモニターするための、パルス波形を見るPythonプログラムを取り上げる。


まず、必要なライブラリーをインポートする。このうち、numpyはPythonのインストールで同時にインストールされるので、ライブラリーとして別途インストールする必要はない。#以下はコメント文である。

import pyaudio #マイク入出力処理
import numpy as np
import matplotlib.pyplot as plt #グラフ処理
import cv2 #カメラ画像処理

次に一連の音声入力をストリーミングとして関数化する。CHUNKは入力単位でここでは、1024個ごとにサンプリングする。サンプリング周波数は変えられるが、デフォルトのままにした。録音時間はパルスの描画を考慮して120msecにした。

def streamandshow(): #入力からグラフ描画まで処理
    CHUNK = 1024 #入出力の長さ
    FORMAT = pyaudio.paInt16 #2Byte整数
    CHANNELS = 2 #ステレオ
    RATE = 44100 #サンプリング周波数(Hz)
    RECORD_SECONDS = 0.12 #録音時間(秒)

ストリーミングをオープンし、CHUNKごとのデータdata-rawをframesというlistに追記していく。

    p = pyaudio.PyAudio()
    stream = p.open(format = FORMAT,
                    channels = CHANNELS,
                    rate = RATE,
                    input = True, #入力のみ
                    frames_per_buffer = CHUNK)
    frames = [] #空のlistを用意
    for i in range(int(RATE* RECORD_SECONDS // CHUNK)): #CHUNK単位で切り捨て
        data_raw = stream.read(CHUNK) 
        frames.append(data_raw) #追記

framesのデータを2進数に数値化する。

    frames_int16 = np.array(frames)

ここでストリームを閉じる。

    stream.stop_stream() #ストリームを閉じる
    stream.close()
    p.terminate()

以下は、パルス波形を描画するための演算で、まず、2進数を10進数に変換し、データは片チャンネルだけでよいので、ステレオのLチャンネルのデータだけを抽出する。さらに、データの最大値を求め、画面に出力する。

data = np.frombuffer(frames_int16, dtype='int16') 
    data_l = data[::2] #ステレオのLチャンネル
    data_max = max(data_l) #最大値を求める
    print(data_max) #最大値を画面に出力

グラフの大きさを決め、パルス波形を描画する。描画は0.3秒間だけ保持して、全体の処理を繰り返す。

    fig = plt.figure(num = 1, figsize = (6, 4)) #グラフの大きさを決める
    plt.plot(data_l[100:]) #最初の100点をスキップ
    plt.pause(0.3) #0.3秒間だけ描画
    plt.clf() #グラフを閉じる

プログラムの停止の停止には、キーボードからQを入力する。

while True: #キー入力を待つ
    if cv2.waitKey(1) & 0xFF == ord('q')#qを入力すると、
        break #処理を終了
    streamandshow() #処理を反復

PythonWindows Power ShellやCMDのコマンドラインで実行されるため、Pythonプログラムの一時中断や再開といった手段がない。waitKeyを使うのはカメラの機能だが、利用させてもらった。ウエブカメラを使用していないのに、OpenCVをインポートしたのはそのためである。Pythonが実装されていれば、PythonファイルをダブルクリックすればPythonプログラムが起動する。バグがあったり、プログラムが終了したりすると、CMDなどの窓が閉じてしまうので、バグフィックスにはCMDでPythonファイルを実行させる方が良い。バグがあれば、エラー原因などが表示されている。また、出力が表示されているので、出力を確認するにはこの方が良い。


パルス波高分布のグラフ描画の例を以下に示す。

f:id:apgmman:20211214143456p:plain

上のパルス波形を見て、計数の閾値を例えば1000と決めることができる。


(※id:TJOid:apgmmanから受領したWord原稿を元に再構成、代理投稿したものです)