-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplotseparate.py
185 lines (163 loc) · 7.52 KB
/
plotseparate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import matplotlib.pyplot as plt
import os
import sys
import pandas as pd
from operator import itemgetter
"""
plotraw(filename, labels)
- plots raw voltammogram from text files
- return: labels of concentrations & colors for legend
"""
def plot_raw(filename, labels, colorslst):
if filename[-3:] == 'txt': # if text file
print("plotting file:", filename)
fp = open(filename, 'r') # open file
xs = []
ys = []
idx1 = filename.rfind("cbz")
idx2 = filename[idx1:].find("_")
conc = filename[idx1 + 3:idx1 + idx2] # get concentration
if 'p' in conc: # for '7p5' concentration
pi = conc.find('p')
conctemp = conc[:pi] + '.' + conc[pi + 1:]
conc = conctemp
conc_str = str(float(conc)) + " \u03BCM"
for line in fp: # for each current, voltage line
if line[0].isnumeric():
potential, diff, f, rev = line.split(',')
potential = float(potential)
current = -float(diff) * 1000000
xs.append(potential) # add potential
ys.append(current) # add current
labelkeys = list(labels.keys())
if conc_str in labelkeys:
plt.plot(xs, ys, color=labels[conc_str])
else:
if len(labelkeys) > 0:
plt.legend()
plt.ylabel("current ($\mu$A)", weight='bold', fontsize=12)
plt.title("raw voltammogram", weight='bold', fontsize=15)
plt.xlabel("potential (V)", weight='bold', fontsize=12)
newcolor = colorslst.pop()
plt.plot(xs, ys, color=newcolor, label=conc_str)
labels[conc_str] = newcolor
return labels
"""
def makedicts
- gathers potential, current of choice (raw, log, smoothed, detilted)
- return: dictionary of ([concentration]: (potential, current)
"""
def makedicts(file, ytype, multiple):
df = pd.read_excel(file) # read dataframe.xlsx
dicttype = dict()
concs = set((l[0], l[1]) for l in df.values) # conc, device set
ylabelreturn = ""
ytitlereturn = ""
for c, d in concs: # for conc, device
if (d == multiple[0] and c == multiple[1]) or multiple == "M": # if plotting multiple or if selected device
x = [l[2] for l in df.values if l[0] == c and l[1] == d] # potential
if ytype == "R": # if raw voltammogram
y = [l[3] for l in df.values if l[0] == c and l[1] == d]
ylabelreturn = 'current ($\mu$A)'
ytitlereturn = "raw voltammogram"
elif ytype == "L": # if log-transform voltammogram
y = [l[4] for l in df.values if l[0] == c and l[1] == d]
ylabelreturn = 'log-transform current'
ytitlereturn = "log voltammogram"
elif ytype == "S": # if smoothed voltammogram
y = [l[-2] for l in df.values if l[0] == c and l[1] == d]
ylabelreturn = 'log-transform current'
ytitlereturn = "smoothed voltammogram"
else: # if detilted voltammogram
y = [l[-1] for l in df.values if l[0] == c and l[1] == d]
ylabelreturn = 'normalized current'
ytitlereturn = "detilted voltammogram"
dicttype[(c, d)] = (x, y) # add device, conc's current and potential
return dicttype, ylabelreturn, ytitlereturn
"""
def plotdataframe
- plots the potential, chosen current (raw, log, smoothed, detilted)
"""
def plotdataframe(datadf, sepbyconc):
colors = ['tab:orange', 'tab:blue', 'tab:orange', 'tab:red', 'tab:green', 'black'] # colors to plot different concs
colorconc = dict()
keys = sorted(datadf.keys(), key=itemgetter(0))
for key in keys: # for concentration, device in dataframe
val = datadf[key]
labelname = str(key[0]) + ' \u03BCM'
# if new concentration to plot
if key[0] not in colorconc.keys():
color = colors.pop()
if sepbyconc and colorconc.keys(): # if separating plots by concentration
handles, labels = plt.gca().get_legend_handles_labels()
by_label = dict(zip(labels, handles))
plt.legend(by_label.values(), by_label.keys())
plt.ylabel(ylabel, weight='bold', fontsize=12)
plt.title(ytitle, weight='bold', fontsize=15)
plt.xlabel("potential (V)", weight='bold', fontsize=12)
plt.show()
colorconc[key[0]] = color
else:
color = colorconc[key[0]]
plt.plot(val[0], val[1], label=labelname, color=color) # colors based on concentration
handles, labels = plt.gca().get_legend_handles_labels()
by_label = dict(zip(labels, handles))
plt.legend(by_label.values(), by_label.keys()) # plot only one legend per conc
"""
main
- prompts user to choose plot type
"""
if __name__ == '__main__':
filetype = input("Do you have a Dataframe file (D) or text (T)?: ")
multiple = input("Would you like to plot one (O) or multiple (M) voltammograms?: ")
if multiple != "O" and multiple != "M": # if invalid entry
print("Invalid input, enter (O) or (M)")
sys.exit()
if filetype == "D": # if plotting from dataframe
vgramtype = input(
"Would you like to plot raw (R), log (L), smoothed (S), detilted (D), or all (A) voltammograms?: ")
else: # if plotting from text file
vgramtype = "raw"
fig, ax = plt.subplots()
if vgramtype == "raw": # if plotting from text file
if multiple == "M": # multiple voltammograms
folder = input("Enter the folder path to analyze: ")
os.chdir(folder) # change directory to folder
ls = dict()
colors = ['tab:green', 'tab:blue', 'tab:red', 'tab:purple', 'tab:orange']
for fn in os.listdir():
newls = plot_raw(fn, ls, colors)
ls = newls # labels for legend
else: # one voltammogram
fn = input("Enter the text file's path: ")
ls = dict()
colors = ['tab:green', 'tab:blue', 'tab:red', 'tab:purple', 'tab:orange']
plot_raw(fn, ls, colors)
plt.ylabel("current ($\mu$A)", weight='bold', fontsize=12)
plt.title("raw voltammogram", weight='bold', fontsize=15)
plt.show()
elif filetype == "D": # if plotting from a dataframe
fn = input("Enter the dataframes's path: ")
sepplot = False # do not separate by concentration
if multiple == "O": # if plotting one voltammogram
dev = int(input("Enter the device to plot: "))
conc = float(input("Enter the concentration to plot: "))
multiple = [dev, conc]
else: # if plotting multiple voltammograms
sep = input("Would you like to separate by concentration (Y/N)? ")
if sep == "Y": # separate by concentration
sepplot = True
if vgramtype == "A": # if plotting all types of voltammogram
vgrams = ["R", "L", "S", "D"] # Raw, Log, Smooth, Detilted
else:
vgrams = [vgramtype]
for vgram in vgrams: # for each type of voltammogram
datadict, ylabel, ytitle = makedicts(fn, vgram, multiple)
plotdataframe(datadict, sepplot)
plt.ylabel(ylabel, weight='bold', fontsize=12)
plt.title(ytitle, weight='bold', fontsize=15)
plt.xlabel("potential (V)", weight='bold', fontsize=12)
plt.show()
else:
print("Invalid input, enter (R), (L), (S), (D), or (A)")
sys.exit()