0
2

More than 3 years have passed since last update.

Pythonスクリプトをパラメトリックに計算させるためのドライバースクリプト

Last updated at Posted at 2020-04-16

これはなに

自作のTimerライブラリーの誤差を測定するために作成した、ドライバースクリプトです。
あるpythonスクリプトを、異なる条件で計算させるためのドライバーツールです。どのように表現してよいかわかりませんでしたが、WebDriverをイメージして、ドライバーと表現しました。
Pythonスクリプトをドライブするための、ドライバースクリプトという感じです。

ドライバースクリプト

python
from timer import Timer

def main():
    seconds = 5
    interval_set = [0.01,0.025,0.05,0.1,0.15,0.2,0.25,0.5,0.75,1,2,2.5,3,3.5,4,4.5]

    num = len(interval_set) + 1

    for case in range(1,num):
        interval = interval_set[case-1]
        timer = Timer(seconds, interval)
        timer.test(seconds, interval, case)

if __name__ == '__main__':
    main()

これを、実行するとtimer.pyにあるtestinterval_setに指定された値ごとに実行し結果を記録します。
timer.pyの前半部分は再掲になりますが、以下のとおりです。

python
import time
import csv
import platform

class Timer:
    def __init__(self, seconds, interval):
        self.interval = interval
        self.seconds = seconds
        self.n = int((seconds - (seconds % interval))/interval)

    def timer(self, seconds,interval):
        time_start = time.perf_counter()
        time.sleep(self.interval*self.n)
        time_stop = time.perf_counter()
        self.remain = seconds - (time_stop - time_start)
        if self.remain > 0: # 補正を入れるとするとココかな
            time.sleep(self.remain)
        else:
            pass
        self.real = time.perf_counter() - time_start
        self.error = self.real - seconds
        return False

    def test(self,seconds, interval, case):
        filename = f"./error_data{case}"+"_"+str(platform.system())+".csv" # フォーマット済み文字列リテラル
        with open(filename, 'w') as f: # wは新規作成
            f.write('seconds(sec),interval(sec),real(sec),error(msec)\n')
            f.close()
        for i in range(1000): # 計測回の設定
            while self.timer(seconds, interval):
                pass
            else:
                print('ループ'+str(case)+' '+str(i+1)+'回目 '+'interval=' + str(interval) + 'sec Error:'+str(self.error*1000)+'msec')
                save_data = [self.seconds,self.interval,self.real, self.error*1000]
                with open(filename, 'a', newline='') as f:
                    writer = csv.writer(f, lineterminator='\r\n')
                    writer.writerow(save_data)

この例では16のintervalの値ごと、1000回ほど誤差の測定を行っています。
なかなかの待ち時間なので、一回づつ実行するのは修行に近いですね。

こういう仕事こそコンピューターの出番です。

main.pyを実行することによりerror_data1_Darwin.csvに、結果が記録されます。
Macで実行しているので、Darwinになっています。ラズパイで実行すると、Linuxになります。

$ python main.py

可視化

大量のグラフをいちいち表示していたら心が折れそうになるので、以下のスクリプトでグラフ化しています。

python
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

num_figure = 9    # 描画したいcsvファイルの数

fig = plt.figure(figsize=(10.0, 15.0))


for i in range(1, num_figure+1):
    df = pd.read_csv('./data/error_data{}_Darwin.csv'.format(i))    # csvファイル読み込み
    df_error = df['error(sec)']   # Error列の読み込み
    df_param = df['interval(sec)'] # Interval列の読み込み
    df_sec = df['seconds(sec)'] # Seconds列の読み込み

    ax = fig.add_subplot(5, 2, i)  # 5行2列の配置で順に描画してくれます。
    sns.distplot(df_error, kde=False, rug=False, bins=100) 
#    plt.hist(df_error,bins=100, alpha=0.4, histtype='stepfilled', color='g')
    ax.set_title("Case{}".format(i)+' ('+str(df_sec[1])+'sec Timer, Int.='+str(df_param[1])+'sec)')  # グラフにタイトルをつける
    ax.set_ylim(0,25) # y軸の範囲を設定
    ax.set_xlim(-0.001,0.011) # x軸の範囲を設定

plt.tight_layout() # グラフの間隔を調整
plt.savefig('Error.png')
plt.show()

あっという間に、グラフが描画されます。
グラフの並べ方を変えただけで、再掲になります。

Error.png

「こうしたらもっと良いよ」など、コメントいただけると嬉しく思います。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2