Repository navigation
Expand file tree
/
Copy pathDashboard.py
More file actions
155 lines (138 loc) · 5.82 KB
/
Copy pathDashboard.py
File metadata and controls
155 lines (138 loc) · 5.82 KB
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
""" Dashboard function for plotting """
from matplotlib import pyplot as plt
from matplotlib import image as img
from matplotlib import gridspec as grd
#import seaborn as sns
import numpy as np
import colorsys as cs
import cv2
import datetime
def dashboard(mean_RGB, var_RGB, image_array, timestamps, N=100):
'''
#
Display a dashboard containing the following information:
1: time trace of RGB values
2: image of reaction flask
3: position on color intensity bar
4: history of actual color
5: position on color wheel
Parameters:
mean_RGB: array | mean RGB values for all images taken up
var_RGB: array | variances in RGB values for all images taken
image_array: array | latest image of the reaction flask
timestamps: array | Time stamps of data files in directory
N: int | number of points used to construct the color wheel
Notes:
1: N > 200 is not recommended for most laptops.
2: mean_RGB and var_RGB can be properly formatted by appending
#
'''
# construct a 2-dimensional polar space where each point is a color in HSV
# then convert each point to RGB for plotting
radii = np.linspace(0, 1, N)
thetas = np.linspace(0, 2*np.pi, N)
t = []
r = []
c = []
for theta in thetas:
for radius in radii:
t.append(theta)
r.append(radius)
# all HSV inputs must be 0-1
c.append(cs.hsv_to_rgb(theta/(2*np.pi), radius, 1))
# construct a 2-dimensional Cartesian space where x is a color intensity
# then convert to RGB for plotting
x_dim = np.linspace(0, 1, N)
y_dim = np.linspace(0, 1, N)
y = []
x = []
color = []
for x_val in x_dim:
for y_val in y_dim:
x.append(x_val)
y.append(y_val)
# rescale for a light-to-dark gradient
color.append(cs.hsv_to_rgb(0, 0, 1-x_val))
# allow the function to be called repeatedly to update the dashboard
plt.ion()
plt.close('all')
# construct a 3 X 6 grid for plotting
gs = grd.GridSpec(3, 6)
lines = plt.subplot2grid((3, 6), (0, 0), colspan=2, rowspan=2)
beaker = plt.subplot2grid((3, 6), (0, 2), colspan=2, rowspan=2)
colorbar = plt.subplot2grid((3, 6), (2, 4), colspan=2)
squares = plt.subplot2grid((3, 6), (2, 0), colspan=4)
# polar projection for HSV-based color construction
colorwheel = plt.subplot2grid((3, 6), (0, 4), projection='polar', colspan=2, rowspan=2)
# plot color wheel
# alpha = 1 ensures accurate colors
colorwheel.scatter(t, r, c=c, alpha=1.0)
colorwheel.xaxis.set_visible(False)
colorwheel.yaxis.set_visible(False)
colorwheel.set_title('Tracking through Color Space', fontsize=8)
colorwheel.axis('off')
# plot color intensity bar
# alpha = 1 ensures accurate color intensity
colorbar.scatter(x, y, c=color, alpha=1.0)
colorbar.xaxis.set_visible(False)
colorbar.yaxis.set_visible(False)
colorbar.axis('off')
colorbar.set_title('Tracking through Intensity Space', fontsize=8)
# temp = mean_RGB[0]
# mean_RGB[0] = mean_RGB[2]
# mean_RGB[2] = temp
# plot mean RGB values over time with error bars of variances
# DEFAULT: construct array of time stamps relative to first: default
tstamps_delta = [datetime.datetime.strptime(str(ts), "%Y%m%d%H%M%S") for ts in timestamps]
tstamps_delta = np.array([(ts - tstamps_delta[0]).total_seconds() for ts in tstamps_delta])
# # WORKAROUND FOR PREVIOUS DATA FORMAT: construct array of time stamps relative to first
# tstamps_delta = np.array([int(str(ts)[12:]) for ts in timestamps])
# tstamps_delta = tstamps_delta - tstamps_delta[0]
# plot traces
line_colors = ['r', 'g', 'b']
for i, c in enumerate(line_colors):
lines.errorbar(tstamps_delta[:len(mean_RGB)], mean_RGB[:, i], yerr=np.sqrt(var_RGB[:, i]), color=c)
lines.set_ylim(-5, 260) #fix pixel value around maximum range [0, 255]
lines.set_title('History of Mean RGB Values', fontsize=8)
lines.set_xlabel('Elapsed Time in s', fontsize=8)
lines.set_ylabel('RGB Component Value', fontsize=8)
# display latest image of the reaction flask
# interpolation = 'nearest' ensures image is displayed accurately
image_array_edit = cv2.cvtColor(image_array, cv2.COLOR_BGR2RGB)
beaker.imshow(image_array_edit, interpolation='nearest')
beaker.axis('off')
beaker.set_title('Latest Beaker Image', fontsize=8)
# plot path through color and intensity spaces
t_val = []
r_val = []
v_val = []
y_val = np.linspace(0, 1, len(mean_RGB))
for color in mean_RGB:
# all RGB values must be 0-1
r, g , b = color[2]/255, color[0]/255, color[1]/255
hsv = cs.rgb_to_hsv(r, g, b)
hsv = np.array(hsv)
#added to increase the effect of the change in color
hsv *= 0.5
# rescale 0-2*pi for polar plotting
t_val.append(hsv[0]*2*np.pi)
r_val.append(hsv[1])
v_val.append(hsv[2])
colorwheel.plot(t_val, r_val, 'k-')
colorwheel.plot(t_val[-1], r_val[-1], 'ko')
colorbar.plot(1-np.array(v_val), y_val, 'y-')
# plot latest points as circles to show the latest position
colorbar.plot(1-v_val[-1], y_val[-1], 'yo')
# display succession of colors over the course of the experiment
c_squares = mean_RGB/255 # rescale mean_RGB for the following plot
for i in range(1, len(mean_RGB)+1):
squares.plot([i-1+0.49, i-0.49], [0, 0], '-', linewidth=100, c=c_squares[i-1])
squares.axis('off')
squares.set_title('Mean Color in the Beaker over Time', fontsize=8)
# display dashboard
# ensure that plots don't overlap on the dashboard
plt.tight_layout()
plt.savefig('image_intensity_change_{}.png'.format(len(mean_RGB)))
plt.show()
# allows for the master script to run while the dashboard "waits"
plt.pause(0.05)