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
みたいな感じで一番左の値が行ったり来たりを繰り返しますが
グラフにするのは最後の一周分で、右の値もアンペアからマイクロアンペアに直します
一回の実験で複数のデータを取って重ね書きすることが多いので、それらのデータを並べ、
かつコピペでテーブルに貼れると便利です
こんな感じにフォルダとアプリケーションを配置します(なければアプリで勝手に作ります)
inputフォルダの中に処理したいデータを入れ
CVcollecter.exeをダブルクリックで起動
一秒くらいで処理が終わってoutputフォルダ内に結果とプロパティーが出ます
結果をカレイダグラフやエクセルに全選択、コピペで貼り付けましょう
僕は事前にこのアプリで前処理した後、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 ファイル名
でバイナリ化できます