Cyclic Voltammetryのデータをグラフ化前に前処理

二、三週間くらい前に作ったものですが、
研究室で使うポテンショスタットの機械が吐き出すデータをグラフにするまでの操作が面倒だったので、前処理の部分を自動化しました。

pyinstallerでexe化することを前提に作ったので、pandasとかは使わずにインポートするモジュールのライブラリは極力減らしました。

読み込むテキストデータは例えば

0.000, -7.641e-006
0.001, -7.549e-006
0.002, -7.477e-006
~~~~~~~~~~~~~~~~~~
0.498, +2.116e-006
0.499, +2.087e-006
0.500, +1.906e-006
0.499, +1.823e-006
0.498, +1.776e-006
~~~~~~~~~~~~~~~~~~
0.002, -5.564e-006
0.001, -5.524e-006
0.000, -5.341e-006
0.001, -5.261e-006
0.002, -5.216e-006

みたいな感じで一番左の値が行ったり来たりを繰り返しますが
グラフにするのは最後の一周分で、右の値もアンペアからマイクロアンペアに直します

一回の実験で複数のデータを取って重ね書きすることが多いので、それらのデータを並べ、
かつコピペでテーブルに貼れると便利です

f:id:Py2k4:20161203125048p:plain

こんな感じにフォルダとアプリケーションを配置します(なければアプリで勝手に作ります)
f:id:Py2k4:20161203125319p:plain
inputフォルダの中に処理したいデータを入れ
CVcollecter.exeをダブルクリックで起動
一秒くらいで処理が終わってoutputフォルダ内に結果とプロパティーが出ます
f:id:Py2k4:20161203125512p:plain

結果をカレイダグラフやエクセルに全選択、コピペで貼り付けましょう
僕は事前にこのアプリで前処理した後、pandasとseabornでグラフ化してます

ソースコードはこちら

# -*- coding: utf-8 -*-
import os
import traceback

data = {}  # {pathname1:Data1, pathname2:Data2, ……]}
v_set = set()
data_keys = []


class Data:
    """
    cv_reader()の使用を推奨
    cv_readerで読み取ったデータとその詳細を格納する

    self.va: (V, μA)のタプルのリスト、ただし折り返し地点のみ同じデータを二個持つ
    self.potential: dataの持つVの値を集めた集合
    self.v_step: vの刻み値
    self.v_segment: 1segmentあたりの大きさ
    """
    def __init__(self, read):
        self.va = read
        self.potential = set([row[0] for row in self.va])  # row[col]
        self.v_step = self.va[1][0] - self.va[0][0]
        self.segment = int((max(self.potential) - min(self.potential)) / self.v_step)
        self.count = 0

    def get(self, v):
        if v in self.potential and self.count < len(self.va):
            if v != self.va[self.count][0]:
                print(v, end=":")
                print(self.va[self.count][0])
                return ""

            else:
                self.count += 1
                return self.va[self.count - 1][1]
        else:
            return ""


def cv_reader(pathname):
    """
    CVの機械から持ち出したデータを(Potential(V), Current(μA))のリストに変換する
    read[row][col]
    readを図にするとこんな感じ↓
      V |μA
     ---|--
     0  |0.123
     0.1|0.123
    """
    with open("./input/"+pathname, "r") as f:
        lines = []
        for line in f:
            lines.append(line)

    data_mat = [[float(values.strip(" ")) for values in line.split(",")]
                    for line in lines]
    potential = set([row[0] for row in data_mat])  # row[col]
    maxV = max(potential)
    minV = min(potential)
    stepV = data_mat[1][0] - data_mat[0][0]
    segment = int((maxV - minV) / stepV)
    read = [(round(data_mat[i][0], 3), round(data_mat[i][1]*10**6, 3))
                for i in range(len(data_mat) - 2 * segment, len(data_mat))]
    return read


if __name__ == "__main__":
    if not os.path.isdir('input'):
        os.mkdir("input")
    if not os.path.isdir('output'):
        os.mkdir("output")
    path_list = [path for path in os.listdir("./input") if ".txt" in path]

    description = "データの説明 値はμAに変換済み\n1列目 電圧\n"
    description_counter = 2
    for pathname in path_list:  # テキストを読み込んでDataに変換
        try:
            print(pathname)
            value = Data(cv_reader(pathname))
            key = pathname.split(".txt")[0]
            data_keys.append(key)
            data[key] = value
            v_set.update(data[key].potential)

            description += str(description_counter) + "列目 " + key + "\n"
            description_counter += 1
        except:
            print(traceback.format_exc())
            print(pathname+"は対応していない形式です")

    scan_v = (sorted([v for v in v_set]) +
              sorted([v for v in v_set], reverse=True))

    newtext = ""
    description += ("出力範囲: " +
                    str(scan_v[0]) + "~" +
                    str(scan_v[len(v_set) - 1]) + "\n")

    for v in scan_v:
        newtext += str(v)
        for data_key in data_keys:
            newtext += "\t" + str(data[data_key].get(v))
        newtext += "\n"

    with open("./output/result.txt", "w", encoding="shift_jis") as f:
        f.write(newtext)
    with open("./output/property.txt", "w", encoding="shift_jis") as f:
        f.write(description)

追記
exe化はpyinstallerを使ってます
pipでpyinstallerをインストールして

pyinstaller --onefile ファイル名

バイナリ化できます