-
Notifications
You must be signed in to change notification settings - Fork 0
/
make_color_spectrum.py
99 lines (77 loc) · 3.63 KB
/
make_color_spectrum.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
# These functions written by Ryan Anderson ([email protected]), March 10, 2021.
# Adapted from SuperCam-specific scripts to be more generic.
from skimage import io
import numpy as np
import scipy.interpolate as interp
import matplotlib.pyplot as plot
def get_color_lookup(input_wvls, use_spectrum_on_gray = False):
#load the image
if use_spectrum_on_gray:
spect_img_path = "Rendered_Spectrum.png"
spect_img = io.imread(spect_img_path)
# take a slice of the image, containing just the colors (no margins, etc)
spect_colors = spect_img[45, 33:1589, 0:3] / 255
# create an array with values corresponding to the wavelength scale on the image
wvl_range = (740.0 - 360.0)
spect_wvls = np.array(list(range(spect_colors.shape[0]))) / spect_colors.shape[0] * wvl_range + 360
fillval = 0.58823529
else:
spect_img_path = "Linear_visible_spectrum.png"
spect_img = io.imread(spect_img_path)
#take a slice of the image, containing just the colors (no margins, etc)
spect_colors = spect_img[200,7:1909,0:3]/255
#create an array with values corresponding to the wavelength scale on the image
wvl_range = (750.0-380.0)
spect_wvls = np.array(list(range(spect_colors.shape[0])))/spect_colors.shape[0]*wvl_range+380
fillval = 0
#for each color (R,G,B) interpolate the values from the spectrum image onto the input wavelengths
#(for values outside the spectrum image range, use black)
f_red = interp.interp1d(spect_wvls, spect_colors[:, 0], bounds_error=False, fill_value=fillval)
f_green = interp.interp1d(spect_wvls, spect_colors[:, 1], bounds_error=False, fill_value=fillval)
f_blue = interp.interp1d(spect_wvls, spect_colors[:, 2], bounds_error=False, fill_value=fillval)
input_red = f_red(input_wvls)
input_green = f_green(input_wvls)
input_blue = f_blue(input_wvls)
#return the rgb values for each input wvl
return np.vstack((input_red, input_green, input_blue)).T
def color_lineplot(ax, x,y,colors):
# plot the spectrum segment by segment, using the specified colors
# (This assumes that the segments are small compared to the change in color over the spectrum.
# Could look weird for low spectral resolution.)
for i in range(len(x)):
try:
ax.plot(x[i:i+2],y[i:i+2], color = colors[i], linewidth = 2, solid_capstyle= 'round')
except:
pass
########## Example #########
#make a fake wvl array and matching fake data (substitute real data here)
wvls = np.arange(200,900,0.1)
fake_spect = np.sin(wvls/np.pi)
#look up rgb colors matching each wvl
color_values = get_color_lookup(wvls, use_spectrum_on_gray=False)
#get indices for three spectral ranges
range1_ind = np.all((wvls > 240, wvls < 340), axis=0)
range2_ind = np.all((wvls > 379, wvls < 465), axis=0)
range3_ind = np.all((wvls > 535, wvls < 855), axis=0)
fig, (ax1, ax2, ax3) = plot.subplots(1, 3, figsize=(10,4))
# plot color coded lines
color_lineplot(ax1, wvls[range1_ind], fake_spect[range1_ind], color_values[range1_ind])
color_lineplot(ax2, wvls[range2_ind], fake_spect[range2_ind], color_values[range2_ind])
color_lineplot(ax3, wvls[range3_ind], fake_spect[range3_ind], color_values[range3_ind])
# narrow plot spacing
plot.subplots_adjust(wspace=0.01)
# remove yticks
ax1.set_yticks([])
ax2.set_yticks([])
ax3.set_yticks([])
# labels
ax1.set_ylabel('Y Axis Title')
ax2.set_xlabel('X Axis Title')
# titles
fig.suptitle('Example colorized spectrum')
ax1.set_title('Range 1')
ax2.set_title('Range 2')
ax3.set_title('Range 3')
# plot.show()
dpi = 1000
plot.savefig('example_fig_' + str(dpi) + 'dpi.png', dpi=dpi)