def plot_light_spectrum(n_wavelengths=100): lambdas, omegas = generate_wavelengths(n_wavelengths) colors_XYZ = np.zeros((n_wavelengths, 3)) for i, lambd in enumerate(np.linspace(400E-9, 700E-9, n_wavelengths)): print(i) # spectrum = generate_gaussian_spectrum(lambdas=lambdas, mu=lambd, sigma=30E-9) spectrum = generate_mono_spectrum(lambdas=lambdas, color=lambd) colors_XYZ[i, :] = -ct.from_spectrum_to_xyz( lambdas, spectrum, normalize=False) #normalize colors # colors_xyz = colors_XYZ/np.max(np.sum(colors_XYZ, axis=1)) colors_xyz = colors_XYZ / np.max(colors_XYZ[:, 1]) colors_rgb = ct.from_xyz_to_rgb(colors_xyz.reshape((1, n_wavelengths, 3)), normalize=False) colors_rgb /= np.max(colors_rgb, axis=(1, 2))[:, None, None] # plt.figure(figsize=(2*3.45, 2*2.5)) plt.figure(figsize=(3.45, 2.5)) plt.imshow(colors_rgb, extent=(400E-9, 700E-9, 0, 1), aspect=(300E-9) / 7) plt.gca().set_yticks([]) plt.gca().set_xticks(np.linspace(400E-9, 700E-9, 4)) plt.gca().set_xticklabels(np.linspace(400, 700, 4).astype(int)) plt.gca().set_xlabel('Wavelength (nm)') plt.savefig(fig_path + 'spectrum_light.pdf')
def compute_rgb(self, sqrt=False): if self.rgb_colors is None: if self.xyz_colors is None: self.compute_xyz(sqrt) self.rgb_colors = ct.from_xyz_to_rgb(self.xyz_colors) return self.rgb_colors
def color_shift_2_figs(n_wavelengths=100, N=10): rhos = color_shift_cube(wavelengths=np.linspace(400E-9, 700E-9, n_wavelengths), rhos=np.linspace(-1, 1, N), thetas=np.array([0]), return_XYZ=True) thetas = color_shift_cube(wavelengths=np.linspace(400E-9, 700E-9, n_wavelengths), rhos=np.array([1]), thetas=np.linspace(0, np.pi, N), return_XYZ=True) rhos = rhos.reshape((N, n_wavelengths, 3)) thetas = thetas.reshape((N, n_wavelengths, 3)) max_rhos = np.max(rhos[:, :, 1]) rhos /= max_rhos thetas /= max_rhos rhos = ct.from_xyz_to_rgb(rhos, normalize=False) thetas = ct.from_xyz_to_rgb(thetas, normalize=False) f, (ax1, ax2) = plt.subplots(2, figsize=(1.3 * 3.45, 1.3 * 3.45), sharex=True) ax1.imshow(rhos, extent=(400E-9, 700E-9, 0, 1), aspect='auto') ax1.set_yticks(np.linspace(0, 1, 3)) ax1.set_yticklabels(np.linspace(1, -1, 3)) ax1.set_ylabel(r'$\rho$', rotation=0) ax1.set_title(r'(a) Color rendition with respect to $\rho$') ax2.imshow(thetas, extent=(400E-9, 700E-9, 0, 1), aspect='auto') ax2.set_yticks(np.linspace(0, 1, 3)) ax2.set_yticklabels(['$\pi$', '$\pi/2$', '$0$']) ax2.set_ylabel(r'$\theta$', rotation=0) ax2.set_title(r'(b) Color rendition with respect to $\theta$') ax2.set_xticks(np.linspace(400E-9, 700E-9, 4)) plt.gca().set_xticklabels(np.linspace(400, 700, 4).astype(int)) ax2.set_xlabel('Wavelength (nm)') plt.savefig(fig_path + 'color_shift_2_figs.pdf')
def lambdas_to_rgb(lambdas): colors_XYZ = np.zeros((len(lambdas), 3)) for i, lambd in enumerate(lambdas): spectrum = generate_mono_spectrum(lambdas=lambdas, color=lambd) colors_XYZ[i, :] = -ct.from_spectrum_to_xyz( lambdas, spectrum, normalize=False) #normalize colors colors_xyz = colors_XYZ / np.max(colors_XYZ[:, 1]) colors_rgb = ct.from_xyz_to_rgb(colors_xyz.reshape((-1, 1, 3)), normalize=False).reshape((-1, 3)) colors_rgb /= np.max(colors_rgb) return colors_rgb
def show_spectrum(lambdas, spectrum, ax=None, visible=False, true_spectrum=True, vmax=None, show_background=False, lw=1, nolabel=False, short_display=False, label=''): if visible: spectrum = spectrum[(lambdas <= 700E-9) & (lambdas >= 400E-9)] lambdas = lambdas[(lambdas <= 700E-9) & (lambdas >= 400E-9)] lam = lambdas * 1E9 if ax is None: plt.figure() ax = plt.gca() L = len(lam) if true_spectrum: cs = [wavelength_to_rgb(wavelength) for wavelength in lam] # cs = lambdas_to_rgb(lambdas) else: colors = plt.cm.Spectral_r(np.linspace(0, 1, L)) cs = [colors[i] for i in range(L)] # ax.scatter(lam, spectrum, color=cs, s=10) # ax.plot(lam, spectrum, '--k', linewidth=0.5, zorder=-1, alpha=0.5, dashes=(2,2)) fda.plot_gradient_line(lam, spectrum, ax=ax, zorder=-1, lw=lw, cs=cs) ax.set_xlim([np.min(lam), np.max(lam)]) if vmax is None: vmax = 1.1 * np.max(spectrum) ax.set_ylim(0, vmax) ax.set_yticks([]) if not nolabel and not short_display: ax.set_xticks([400, 500, 600, 700]) ax.set_xlabel('Wavelength ($nm$)') if not nolabel and short_display: ax.set_xticks([400, 550, 700]) ax.set_xticklabels([400, '$\lambda$ ($nm$)', 700]) ax.set_xlabel(label) if show_background: col = ct.from_xyz_to_rgb( ct.from_spectrum_to_xyz(lambdas, spectrum).reshape( (1, 1, -1))).flatten() ax.add_patch( patches.Rectangle((lam[0], 0.95 * vmax), lam[-1] - lam[0], 1.05 * vmax, facecolor=col, edgecolor='none', zorder=-10))
def color_shift(n_wavelengths=100, ax=None): lambdas, omegas = generate_wavelengths(500) #3000 depths = generate_depths(max_depth=7E-6) rs = [-1, 0.7 * np.exp(1j * np.deg2rad(-148)), 0.2, 1] r_names = ['$r=-1$', 'Hg', 'Air', '$r=1$'] rs = [0.7 * np.exp(1j * np.deg2rad(148)), 0.2] r_names = ['Hg', 'Air'] colors_XYZ = np.zeros((len(rs) + 1, n_wavelengths, 3)) modulation = np.linspace(1, 0.2, len(lambdas)) # modulation = 0.5+np.random.rand(len(lambdas)) # modulation = generate_gaussian_spectrum(lambdas, mu=450E-9, sigma=300E-9) # modulation = generate_gaussian_spectrum(lambdas, mu=450E-9, sigma=150E-9) # modulation = (np.exp(np.linspace(0,1,len(lambdas)))-1 )/(np.exp(1)-1) for i, lambd in enumerate(np.linspace(400E-9, 700E-9, n_wavelengths)): print(i) # spectrum = generate_gaussian_spectrum(lambdas=lambdas, mu=lambd, sigma=30E-9) spectrum = generate_mono_spectrum(lambdas=lambdas, color=lambd) colors_XYZ[0, i, :] = -ct.from_spectrum_to_xyz( lambdas, spectrum, normalize=False) # spectrum *= modulation for j, r in enumerate(rs): window = erfc(np.linspace(0, 3, len(depths))) lippmann = lippmann_transform(lambdas, spectrum, depths, r=r)[0] * window spectrum_replayed = inverse_lippmann(lippmann, lambdas, depths) colors_XYZ[j + 1, i, :] = -ct.from_spectrum_to_xyz( lambdas, spectrum_replayed, normalize=False) #normalize colors colors_xyz = colors_XYZ / np.max(np.sum(colors_XYZ, axis=2), axis=1)[:, None, None] # colors_xyz = colors_XYZ/np.max(colors_XYZ[:,:,1], axis=1)[:,None, None] colors_rgb = ct.from_xyz_to_rgb(colors_xyz, normalize=False) colors_rgb /= np.max(colors_rgb, axis=(1, 2))[:, None, None] # colors_xyz = colors_XYZ/np.max(colors_XYZ[:,:,1]) # colors_rgb = ct.from_xyz_to_rgb(colors_xyz, normalize=False) # colors_rgb /= np.max(colors_rgb) if ax is None: plt.figure(figsize=(3.45, 2.5)) ax = plt.gca() ax.imshow(colors_rgb, extent=(400E-9, 700E-9, 0, 1), aspect='auto') L = len(rs) + 1 ax.set_yticks(np.linspace(1 / (2 * L), 1 - 1 / (2 * L), L)) ax.set_yticklabels((['Original'] + r_names)[::-1]) ax.set_xticks(np.linspace(400E-9, 700E-9, 4)) plt.gca().set_xticklabels(np.linspace(400, 700, 4).astype(int)) ax.set_xlabel('Wavelength (nm)') plt.savefig(fig_path + 'color_shift_PNAS_erfc3_.pdf')
def plot_color_shift_cube(n_wavelengths=100, N=10): xz = color_shift_cube(wavelengths=np.linspace(400E-9, 700E-9, n_wavelengths), rhos=np.linspace(-1, 1, N), thetas=np.array([0]), return_XYZ=True) xy = color_shift_cube(wavelengths=np.linspace(400E-9, 700E-9, n_wavelengths), rhos=np.array([1]), thetas=np.linspace(0, np.pi, N), return_XYZ=True) yz = color_shift_cube(wavelengths=np.array([700E-9]), rhos=np.linspace(-1, 1, N), thetas=np.linspace(0, np.pi, N), return_XYZ=True) max_XZ = np.max(xz[:, :, :, 1]) xz /= max_XZ xy /= max_XZ yz /= max_XZ xz = ct.from_xyz_to_rgb(xz, normalize=False) xy = ct.from_xyz_to_rgb(xy, normalize=False) yz = ct.from_xyz_to_rgb(yz, normalize=False) canvas = figure(figsize=(3.45, 2.5)) axes = Axes3D(canvas) quads = cube(width=1, height=1, depth=1, width_segments=n_wavelengths, height_segments=N, depth_segments=N) # You can replace the following line by whatever suits you. Here, we compute # each quad colour by averaging its vertices positions. RGB = np.average(quads, axis=-2) RGB[np.average(quads, axis=-2)[:, 0] == 1] = yz.transpose( (2, 1, 0, 3)).reshape((-1, 3)) RGB[np.average(quads, axis=-2)[:, 2] == 1] = xy.transpose( (2, 1, 0, 3)).reshape((-1, 3)) RGB[np.average(quads, axis=-2)[:, 1] == 0] = xz.transpose( (2, 1, 0, 3)).reshape((-1, 3)) # Adding an alpha value to the colour array. RGBA = np.hstack((RGB, np.full((RGB.shape[0], 1), 1))) collection = Poly3DCollection(quads) collection.set_color(RGBA) axes.add_collection3d(collection) plt.gca().set_xticks(np.linspace(0, 1, 4)) plt.gca().set_xticklabels(np.linspace(400, 700, 4)) plt.gca().set_xlabel('Wavelength $\lambda$') plt.gca().set_yticks([0, 0.5, 1]) plt.gca().set_yticklabels(['0', '$\pi/2$', '\pi']) plt.gca().set_ylabel(r'$\theta$') plt.gca().set_zticks([-1, 0, 1]) plt.gca().set_zlabel(r'$\rho$') return xz, xy, yz
def color_shift_cube(wavelengths=np.linspace(400E-9, 700E-9, 100), rhos=np.linspace(-1, 1, 10), thetas=np.linspace(0, np.pi, 10), return_XYZ=False): lambdas, omegas = generate_wavelengths(100) #3000 depths = generate_depths(max_depth=5E-6) colors_XYZ = np.zeros((len(rhos), len(thetas), len(wavelengths), 3)) window = erfc(np.linspace(0, 4, len(depths))) for n, lambd in enumerate(wavelengths): print(n) spectrum = generate_gaussian_spectrum(lambdas=lambdas, mu=lambd, sigma=30E-9) # spectrum = generate_mono_spectrum(lambdas=lambdas, color=lambd) # colors_XYZ[0, 0, n, :] = -ct.from_spectrum_to_xyz(lambdas, spectrum, normalize=False) for i, rho in enumerate(rhos): for j, theta in enumerate(thetas): r = rho * np.exp(-1j * theta) lippmann = lippmann_transform(lambdas, spectrum, depths, r=r)[0] #*window spectrum_replayed = inverse_lippmann(lippmann, lambdas, depths) colors_XYZ[i, j, n, :] = -ct.from_spectrum_to_xyz( lambdas, spectrum_replayed, normalize=False) #normalize colors # colors_xyz = colors_XYZ/np.max(np.sum(colors_XYZ, axis=2),axis=1)[:, None,None] if return_XYZ: return colors_XYZ colors_xyz = colors_XYZ / np.max(colors_XYZ[:, :, :, 1]) colors_rgb = ct.from_xyz_to_rgb(colors_xyz, normalize=False) colors_rgb /= np.max(colors_rgb) if len(rhos) == 1: plt.figure(figsize=(3.45, 2.5)) plt.imshow(colors_rgb[0, :, :, :], extent=(400E-9, 700E-9, 0, 1), aspect=(300E-9) / 2) plt.gca().set_yticks(np.linspace(0, 1, 3)) plt.gca().set_yticklabels(['0', '$\pi/2$', '\pi']) plt.gca().set_ylabel(r'$\theta$') elif len(thetas) == 1: plt.figure(figsize=(3.45, 2.5)) plt.imshow(colors_rgb[:, 0, :, :], extent=(400E-9, 700E-9, 0, 1), aspect=(300E-9) / 2) plt.gca().set_yticks(np.linspace(0, 1, 3)) plt.gca().set_yticklabels(np.linspace(1, -1, 3)) plt.gca().set_ylabel(r'$\rho$') if len(rhos) == 1 or len(thetas) == 1: plt.gca().set_xticks(np.linspace(400E-9, 700E-9, 4)) plt.gca().set_xticklabels(np.linspace(400, 700, 4).astype(int)) plt.gca().set_xlabel('Wavelength $\lambda$ (nm)') return colors_rgb
lippmann_hg, _ = lippmann_transform(lambdas, spectrum, depths, r=-0.7) lippmann_air, _ = lippmann_transform(lambdas, spectrum, depths, r=0.2) # window = (np.cos(np.linspace(0, np.pi, len(depths)))+1)/2 # window = np.linspace(1,0, len(depths)) # window = np.exp(np.linspace(0, -7, len(depths))) window = erfc(np.linspace(0, 4, len(depths))) # window = np.ones(len(depths)) lippmann_hg *= window lippmann_air *= window omegas = 2 * np.pi * c / lambdas spectrum_hg = inverse_lippmann(lippmann_hg, lambdas, depths) spectrum_air = inverse_lippmann(lippmann_air, lambdas, depths) c1 = ct.from_xyz_to_rgb( ct.from_spectrum_to_xyz(lambdas, spectrum).reshape((1, 1, -1))) c2 = ct.from_xyz_to_rgb( ct.from_spectrum_to_xyz(lambdas, spectrum_hg).reshape((1, 1, -1))) c3 = ct.from_xyz_to_rgb( ct.from_spectrum_to_xyz(lambdas, spectrum_air).reshape((1, 1, -1))) # plt.close('all') # plt.figure() # show_spectrum(lambdas, spectrum, ax=plt.gca(), show_background=False) # plt.title('original spectrum') # plt.savefig(fig_path + 'original.pdf') # # plt.figure() # show_lippmann_transform(depths, lippmann_hg, ax=plt.gca()) # plt.title('Lippmann transform Hg')