def mycmap(darkcolor=(0, 0, 0), brightcolor=(1, 1, 1), nbins=10): colors = [darkcolor, brightcolor] cmap = LinearSegmentedColormap.from_list("", colors, N=nbins) # Convert RGB to LAB x = np.linspace(0, 1, nbins) rgb = cmap(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) lightness = lab[ 0, :, 0] # So far, lightness is increasing but has no constant derivative. # lightness = lightness-np.min(lightness) # lightness /= np.max(lightness) # lightness *= 50 # lightness += 50 lightness_corrected = np.linspace(lightness[0], lightness[-1], len(lightness)) lab[0, :, 0] = lightness_corrected # Now it has. # Convert back to RGB. rgb = cspace_converter("CAM02-UCS", "sRGB1")(lab) rgb = np.clip(rgb, 0, 1) rgb = np.squeeze( rgb, axis=0 ) # Force all values to [0,1] (which might not be the case due to round-off errors) rgblist = list(map(tuple, rgb)) # Create colormap based on corrected RGB values. cmap = LinearSegmentedColormap.from_list("", rgblist, N=nbins) return cmap
def __init__(self, origin_space_name, cvd_type, severity=100, dest_space_name='sRGB1'): self.severity = severity if cvd_type: cvd_spec = dict(name=origin_space_name, cvd_type=cvd_type, severity=severity) self.converter = cspace_converter(cvd_spec, dest_space_name) else: self.converter = cspace_converter(origin_space_name, dest_space_name)
def mycmapdiv(darkcolorleft=(0, 0, 0), brightcolor=(1, 1, 1), darkcolorright=(0, 0, 0), nbins=10): colors = [darkcolorleft, brightcolor, darkcolorright] cmap = LinearSegmentedColormap.from_list("", colors, N=nbins) # Convert RGB to LAB x = np.linspace(0, 1, nbins) rgb = cmap(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) lightness = lab[ 0, :, 0] # So far, lightness is increasing but has no constant derivative. start = (lightness[0] + lightness[-1]) / 2 # both shall have same lightness if len(lightness) % 2 == 0: lightness_corrected_left = np.linspace(start, np.max(lightness), len(lightness) // 2) lightness_corrected_right = np.linspace(np.max(lightness), start, len(lightness) // 2) lightness_corrected = np.hstack( (lightness_corrected_left, lightness_corrected_right)) else: lightness_corrected_left = np.linspace(start, np.max(lightness), len(lightness) // 2 + 1)[:-1] lightness_corrected_right = np.linspace(np.max(lightness), start, len(lightness) // 2 + 1)[1:] lightness_corrected = np.hstack( (lightness_corrected_left, np.max(lightness), lightness_corrected_right)) lab[0, :, 0] = lightness_corrected # Now it has. # Convert back to RGB. rgb = cspace_converter("CAM02-UCS", "sRGB1")(lab) rgb = np.clip(rgb, 0, 1) rgb = np.squeeze( rgb, axis=0 ) # Force all values to [0,1] (which might not be the case due to round-off errors) rgblist = list(map(tuple, rgb)) # Create colormap based on corrected RGB values. cmap = LinearSegmentedColormap.from_list("", rgblist, N=nbins) return cmap
def plot_cmap(ax, x, y, cmap, vmax, reverse=False): cmap_category = '' for key, value in cmaps.items(): if cmap in value: cmap_category = key dc = _DC.get(cmap_category, 1.4) # cmaps horizontal spacing # Get RGB values for colormap and convert the colormap in # CAM02-UCS colorspace. lab[0, :, 0] is the lightness. rgb = cm.get_cmap(cmap)(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) # Plot colormap L values. Do separately for each category # so each plot can be pretty. To make scatter markers change # color along plot: # http://stackoverflow.com/questions/8202605/matplotlib-scatterplot-colour-as-a-function-of-a-third-variable if cmap_category == 'Sequential': # These colormaps all start at high lightness but we want them # reversed to look nice in the plot, so reverse the order. if reverse: c_ = y else: c_ = y[::-1] else: if reverse: c_ = y[::-1] else: c_ = y ax.scatter(x, y, c=c_, cmap=plt.get_cmap(cmap), vmin=0, vmax=vmax)
def generate_palette(self, palette_size): # colortable needed here color_table = ColorTable() print(color_table) converter = cspace_converter("CAM02-UCS", "sRGB1") if len(self.palette) < 1: self.palette = [color_table[-1, :]] if palette_size <= len(self.palette): return converter(self.palette[0:palette_size]) number_of_colors = color_table.shape[0] distances = np.ones(shape=(number_of_colors, 1)) * 1000 for i in range(len(self.palette) - 1): distances = self.update_distances(color_table.colors, self.palette[i], distances) while len(self.palette) < palette_size: distances = self.update_distances(color_table.colors, self.palette[-1], distances) self.palette.append(color_table[np.argmax(distances), :]) # validation assert isinstance(self.palette, list) for color in self.palette: assert len(color) == 3 assert isinstance(color, np.ndarray) return converter(self.palette[0:palette_size])
def plot_color_gradients(cmap_category, cmap_list): nrows = len(cmap_list) fig, axes = plt.subplots(nrows=nrows, ncols=2) fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99, wspace=0.05) fig.suptitle(cmap_category + " colormaps", fontsize=14, y=1.0, x=0.6) for ax, name in zip(axes, cmap_list): # Get rgb values for colormap rgb = cm.get_cmap(plt.get_cmap(name))(x)[np.newaxis, :, :3] # Get colormap in CAM02-UCS colorspace. We want the lightness. lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) L = lab[0, :, 0] L = np.float32(np.vstack((L, L, L))) ax[0].imshow(gradient, aspect="auto", cmap=plt.get_cmap(name)) ax[1].imshow(L, aspect="auto", cmap="binary_r", vmin=0.0, vmax=100.0) pos = list(ax[0].get_position().bounds) x_text = pos[0] - 0.01 y_text = pos[1] + pos[3] / 2.0 fig.text(x_text, y_text, name, va="center", ha="right", fontsize=10) # Turn off *all* ticks & spines, not just the ones with colormaps. for ax in axes: ax[0].set_axis_off() ax[1].set_axis_off() plt.show()
def generate_color_table(self): """ Generates a lookup table with all possible RGB colors, encoded in a perceptually uniform CAM02-UCS color space. Table rows correspond to individual RGB colors. Table columns correspond to J', a', and b' components. :return: LUT as Numpy array """ widgets = ["Generating color table: ", Percentage(), " ", Bar(), " ", ETA()] bar = ProgressBar(widgets=widgets, maxval=(MAX_RANGE ** 2)).start() i = 0 colors = np.empty(shape=(MAX_RGB255_COLORS, 3), dtype=float) converter = cspace_converter("sRGB255", "CAM02-UCS") for red in range(MAX_RANGE): for green in range(MAX_RANGE): distance = i * MAX_RANGE for blue in range(MAX_RANGE): colors[distance + blue, :] = (red, green, blue) colors[distance : distance + MAX_RANGE] = converter( colors[distance : distance + MAX_RANGE] ) i += 1 bar.update(i) bar.finish() return colors
def test(cmap, fig=None, ax=None): '''Test colormap by plotting. :param cmap: A colormap instance. Use a named one with cm.get_cmap(colormap) ''' from colorspacious import cspace_converter # indices to step through colormap x = np.linspace(0.0, 1.0, 100) # will plot colormap and lightness rgb = cmap(x)[np.newaxis, :, :3] # rgb = cm.get_cmap(cmap)(x)[np.newaxis,:,:3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) # lab = color.rgb2lab(rgb) if ax is None: fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(x, lab[0, :, 0], c=x, cmap=cmap, s=300, linewidths=0.) ax.set_title(cmap.name) ax.set_ylabel('Lightness') ax.set_xticks([])
def plot_color_gradients(cmap_category, cmap_list): fig, axs = plt.subplots(nrows=len(cmap_list), ncols=2) fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99, wspace=0.05) fig.suptitle(cmap_category + ' colormaps', fontsize=14, y=1.0, x=0.6) for ax, name in zip(axs, cmap_list): # Get RGB values for colormap. rgb = cm.get_cmap(plt.get_cmap(name))(x)[np.newaxis, :, :3] # Get colormap in CAM02-UCS colorspace. We want the lightness. lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) L = lab[0, :, 0] L = np.float32(np.vstack((L, L, L))) ax[0].imshow(gradient, aspect='auto', cmap=plt.get_cmap(name)) ax[1].imshow(L, aspect='auto', cmap='binary_r', vmin=0., vmax=100.) pos = list(ax[0].get_position().bounds) x_text = pos[0] - 0.01 y_text = pos[1] + pos[3] / 2. fig.text(x_text, y_text, name, va='center', ha='right', fontsize=10) # Turn off *all* ticks & spines, not just the ones with colormaps. for ax in axs.flat: ax.set_axis_off() plt.show()
def plot_gallery(saveplot=False): '''Make plot of colormaps and labels, like in the matplotlib gallery. :param saveplot=False: Whether to save the plot or not. ''' from colorspacious import cspace_converter gradient = np.linspace(0, 1, 256) gradient = np.vstack((gradient, gradient)) x = np.linspace(0.0, 1.0, 256) fig, axes = plt.subplots(nrows=int(len(cm.cmap_d) / 2), ncols=1, figsize=(6, 12)) fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99, wspace=0.05) for ax, cmapname in zip(axes, cm.cmapnames): if '_r' in cmapname: # skip reversed versions for plot continue cmap = cm.cmap_d[cmapname] # get the colormap instance rgb = cmap(x)[np.newaxis, :, :3] # Find a good conversion to grayscale jch = cspace_converter("sRGB1", "CAM02-UCS")( rgb) # Not sure why to use JCh instead so using this. L = jch[0, :, 0] L = np.float32(np.vstack((L, L, L))) ax.imshow(gradient, aspect='auto', cmap=cmap) pos1 = ax.get_position() # get the original position pos2 = [pos1.x0, pos1.y0, pos1.width, pos1.height / 3.0] axbw = fig.add_axes(pos2) # colorbar axes axbw.set_axis_off() axbw.imshow(L, aspect='auto', cmap=cm.gray, vmin=0, vmax=100.) pos = list(ax.get_position().bounds) x_text = pos[0] - 0.01 y_text = pos[1] + pos[3] / 2. fig.text(x_text, y_text, cmap.name, va='center', ha='right') # Turn off *all* ticks & spines, not just the ones with colormaps. for ax in axes: ax.set_axis_off() if saveplot: fig.savefig('figures/gallery.pdf', bbox_inches='tight') fig.savefig('figures/gallery.png', bbox_inches='tight') plt.show()
def __init__(self, bezier_model, min_Jp, max_Jp, uniform_space): self.bezier_model = bezier_model self.min_Jp = min_Jp self.max_Jp = max_Jp self.trigger = Trigger() self.uniform_to_sRGB1 = cspace_converter(uniform_space, "sRGB1") self.bezier_model.trigger.add_callback(self.trigger.fire)
def plot_gallery(saveplot=False): '''Make plot of colormaps and labels, like in the matplotlib gallery. :param saveplot=False: Whether to save the plot or not. ''' from colorspacious import cspace_converter gradient = np.linspace(0, 1, 256) gradient = np.vstack((gradient, gradient)) x = np.linspace(0.0, 1.0, 256) fig, axes = plt.subplots(nrows=len(cmaps), ncols=1) fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99, wspace=0.05) fig.suptitle('Oceanography colormaps', fontsize=16, y=1.0, x=0.6) for ax, cmap in zip(axes, cmaps): rgb = cmap(x)[np.newaxis, :, :3] # Find a good conversion to grayscale jch = cspace_converter("sRGB1", "JCh")(rgb) L = jch[0, :, 0] # # Get colormap in CIE LAB. We want the L here. # lab = color.rgb2lab(rgb) # L = lab[0, :, 0] L = np.float32(np.vstack((L, L, L))) ax.imshow(gradient, aspect='auto', cmap=cmap) pos1 = ax.get_position() # get the original position pos2 = [pos1.x0, pos1.y0, pos1.width, pos1.height / 4.0] axbw = fig.add_axes(pos2) # colorbar axes axbw.set_axis_off() axbw.imshow(L, aspect='auto', cmap='binary_r', vmin=0, vmax=100.) # ax[1].imshow(L, aspect='auto', cmap='binary_r', vmin=0., vmax=100.) pos = list(ax.get_position().bounds) x_text = pos[0] - 0.01 y_text = pos[1] + pos[3] / 2. fig.text(x_text, y_text, cmap.name, va='center', ha='right') # Turn off *all* ticks & spines, not just the ones with colormaps. for ax in axes: ax.set_axis_off() if saveplot: fig.savefig('figures/gallery.pdf', bbox_inches='tight') fig.savefig('figures/gallery.png', bbox_inches='tight') plt.show()
def plot_gallery(saveplot=False): """Make plot of colormaps and labels, like in the matplotlib gallery. :param saveplot=False: Whether to save the plot or not. """ from colorspacious import cspace_converter # don't have reverse colormaps built in yet rgb = tools.print_colormaps([cm.gray], returnrgb=True) gcmap = tools.cmap(rgb[::-1, :]) gradient = np.linspace(0, 1, 256) gradient = np.vstack((gradient, gradient)) x = np.linspace(0.0, 1.0, 256) fig, axes = plt.subplots(nrows=len(cmaps), ncols=1, figsize=(6, 12)) fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99, wspace=0.05) # fig.suptitle('Oceanography colormaps', fontsize=16, y=1.0, x=0.6) for ax, cmap in zip(axes, cmaps): rgb = cmap(x)[np.newaxis, :, :3] # Find a good conversion to grayscale jch = cspace_converter("sRGB1", "CAM02-UCS")(rgb) # Not sure why to use JCh instead so using this. # jch = cspace_converter("sRGB1", "JCh")(rgb) L = jch[0, :, 0] # # Get colormap in CIE LAB. We want the L here. # lab = color.rgb2lab(rgb) # L = lab[0, :, 0] L = np.float32(np.vstack((L, L, L))) ax.imshow(gradient, aspect="auto", cmap=cmap) pos1 = ax.get_position() # get the original position pos2 = [pos1.x0, pos1.y0, pos1.width, pos1.height / 3.0] axbw = fig.add_axes(pos2) # colorbar axes axbw.set_axis_off() axbw.imshow(L, aspect="auto", cmap=gcmap, vmin=0, vmax=100.0) pos = list(ax.get_position().bounds) x_text = pos[0] - 0.01 y_text = pos[1] + pos[3] / 2.0 fig.text(x_text, y_text, cmap.name, va="center", ha="right") # Turn off *all* ticks & spines, not just the ones with colormaps. for ax in axes: ax.set_axis_off() if saveplot: fig.savefig("figures/gallery.pdf", bbox_inches="tight") fig.savefig("figures/gallery.png", bbox_inches="tight") plt.show()
def plot_lightness(saveplot=False): '''Plot lightness of colormaps together. ''' from colorspacious import cspace_converter dc = 1. x = np.linspace(0.0, 1.0, 256) locs = [] # locations for text labels fig = plt.figure(figsize=(16, 5)) ax = fig.add_subplot(111) fig.subplots_adjust(left=0.03, right=0.97) ax.set_xlim(-0.1, len(cm.cmap_d) / 2. + 0.1) ax.set_ylim(0, 100) ax.set_xlabel('Lightness for each colormap', fontsize=14) for j, cmapname in enumerate(cm.cmapnames): if '_r' in cmapname: # skip reversed versions for plot continue cmap = cm.cmap_d[cmapname] # get the colormap instance rgb = cmap(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) L = lab[0, :, 0] if L[-1] > L[0]: ax.scatter(x + j * dc, L, c=x, cmap=cmap, s=200, linewidths=0.) else: ax.scatter(x + j * dc, L[::-1], c=x[::-1], cmap=cmap, s=200, linewidths=0.) locs.append(x[-1] + j * dc) # store locations for colormap labels # Set up labels for colormaps ax.xaxis.set_ticks_position('top') ticker = mpl.ticker.FixedLocator(locs) ax.xaxis.set_major_locator(ticker) formatter = mpl.ticker.FixedFormatter( [cmapname for cmapname in cm.cmapnames]) ax.xaxis.set_major_formatter(formatter) labels = ax.get_xticklabels() for label in labels: label.set_rotation(60) if saveplot: fig.savefig('cmocean_lightness.png', bbox_inches='tight') fig.savefig('cmocean_lightness.pdf', bbox_inches='tight') plt.show()
def plot_gallery(saveplot=False): '''Make plot of colormaps and labels, like in the matplotlib gallery. :param saveplot=False: Whether to save the plot or not. ''' from colorspacious import cspace_converter gradient = np.linspace(0, 1, 256) gradient = np.vstack((gradient, gradient)) x = np.linspace(0.0, 1.0, 256) fig, axes = plt.subplots(nrows=len(cm.cmap_d)/2, ncols=1, figsize=(6, 12)) fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99, wspace=0.05) for ax, cmapname in zip(axes, cm.cmapnames): if '_r' in cmapname: # skip reversed versions for plot continue cmap = cm.cmap_d[cmapname] # get the colormap instance rgb = cmap(x)[np.newaxis, :, :3] # Find a good conversion to grayscale jch = cspace_converter("sRGB1", "CAM02-UCS")(rgb) # Not sure why to use JCh instead so using this. L = jch[0, :, 0] L = np.float32(np.vstack((L, L, L))) ax.imshow(gradient, aspect='auto', cmap=cmap) pos1 = ax.get_position() # get the original position pos2 = [pos1.x0, pos1.y0, pos1.width, pos1.height / 3.0] axbw = fig.add_axes(pos2) # colorbar axes axbw.set_axis_off() axbw.imshow(L, aspect='auto', cmap=cm.gray, vmin=0, vmax=100.) pos = list(ax.get_position().bounds) x_text = pos[0] - 0.01 y_text = pos[1] + pos[3]/2. fig.text(x_text, y_text, cmap.name, va='center', ha='right') # Turn off *all* ticks & spines, not just the ones with colormaps. for ax in axes: ax.set_axis_off() if saveplot: fig.savefig('figures/gallery.pdf', bbox_inches='tight') fig.savefig('figures/gallery.png', bbox_inches='tight') plt.show()
def plot_gallery(saveplot=False): '''Make plot of colormaps and labels, like in the matplotlib gallery. :param saveplot=False: Whether to save the plot or not. ''' from colorspacious import cspace_converter gradient = np.linspace(0, 1, 256) gradient = np.vstack((gradient, gradient)) x = np.linspace(0.0, 1.0, 256) fig, axes = plt.subplots(nrows=len(cmaps), ncols=1) fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99, wspace=0.05) fig.suptitle('Oceanography colormaps', fontsize=16, y=1.0, x=0.6) for ax, cmap in zip(axes, cmaps): rgb = cmap(x)[np.newaxis, :, :3] # Find a good conversion to grayscale jch = cspace_converter("sRGB1", "JCh")(rgb) L = jch[0, :, 0] # # Get colormap in CIE LAB. We want the L here. # lab = color.rgb2lab(rgb) # L = lab[0, :, 0] L = np.float32(np.vstack((L, L, L))) ax.imshow(gradient, aspect='auto', cmap=cmap) pos1 = ax.get_position() # get the original position pos2 = [pos1.x0, pos1.y0, pos1.width, pos1.height / 4.0] axbw = fig.add_axes(pos2) # colorbar axes axbw.set_axis_off() axbw.imshow(L, aspect='auto', cmap='binary_r', vmin=0, vmax=100.) # ax[1].imshow(L, aspect='auto', cmap='binary_r', vmin=0., vmax=100.) pos = list(ax.get_position().bounds) x_text = pos[0] - 0.01 y_text = pos[1] + pos[3]/2. fig.text(x_text, y_text, cmap.name, va='center', ha='right') # Turn off *all* ticks & spines, not just the ones with colormaps. for ax in axes: ax.set_axis_off() if saveplot: fig.savefig('figures/gallery.pdf', bbox_inches='tight') fig.savefig('figures/gallery.png', bbox_inches='tight') plt.show()
def __init__(self): cs_converterToCIE = cs.cspace_converter("sRGB255", "CAM02-UCS") d = {} with open("color.txt", 'r') as f: for line in f: if line[0] != "!": l = line.split() d[tuple( np.ndarray.tolist( cs_converterToCIE((int(l[0]), int(l[1]), int( l[2])))))] = self.concatColors(l[3:len(l)]) self.colorDict = d
def plot_colormap(ax, cmap, luminance=True): """ Plot a color map and its luminance. Parameters ---------- ax: matplotlib axes Axes for plotting gradient of the color map. cmap: string or matplotlib color map Color map to be plotted. luminance: bool If True, also plot a gradient of the luminance of the color map. Requires the `colorspacious` package. Examples -------- ``` import matplotlib.pyplot as plt import plottools.colors as c fig, ax = plt.subplots() c.plot_colormap(ax, 'jet', True) ``` ![plotcolormap](figures/colors-plotcolormap.png) """ cmap = get_cmap(cmap) # color map: gradient = np.linspace(0.0, 1.0, 256) gradient = np.vstack((gradient, gradient)) ax.set_title(cmap.name) ax.imshow(gradient, cmap=cmap, aspect='auto', extent=(0.0, 1.0, 1.1, 2.1)) ax.set_ylim(1.1, 2.1) # luminance: if luminance: try: from colorspacious import cspace_converter x = np.linspace(0.0, 1.0, 100) rgb = cmap(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) L = lab[0, :, 0] L = np.float32(np.vstack((L, L, L))) ax.imshow(L, aspect='auto', cmap='binary_r', vmin=0.0, vmax=100.0, extent=(0.0, 1.0, 0.0, 1.0)) ax.set_ylim(0.0, 2.1) except: print('failed to plot luminance gradient') raise ax.set_yticks([])
def plot_lightness(saveplot=False): '''Plot lightness of colormaps together. ''' from colorspacious import cspace_converter dc = 1. x = np.linspace(0.0, 1.0, 256) locs = [] # locations for text labels fig = plt.figure(figsize=(16, 6)) ax = fig.add_subplot(111) ax.set_xlim(-0.1, len(cmaps) + 0.1) ax.set_ylim(0, 100) ax.set_xlabel('Lightness for each colormap') for j, cmap in enumerate(cmaps): rgb = cmap(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) # lab = color.rgb2lab(rgb) L = lab[0, :, 0] # import pdb; pdb.set_trace() # L = lab[0, :, 0] if L[-1] > L[0]: ax.scatter(x + j * dc, L, c=x, cmap=cmap, s=300, linewidths=0.) else: ax.scatter(x + j * dc, L[::-1], c=x[::-1], cmap=cmap, s=300, linewidths=0.) locs.append(x[-1] + j * dc) # store locations for colormap labels # Set up labels for colormaps ax.xaxis.set_ticks_position('top') ticker = mpl.ticker.FixedLocator(locs) ax.xaxis.set_major_locator(ticker) formatter = mpl.ticker.FixedFormatter([cmap.name for cmap in cmaps]) ax.xaxis.set_major_formatter(formatter) labels = ax.get_xticklabels() for label in labels: label.set_rotation(60) if saveplot: fig.savefig('figures/lightness.png', bbox_inches='tight') fig.savefig('figures/lightness.pdf', bbox_inches='tight') plt.show()
def plot_lightness(saveplot=False): '''Plot lightness of colormaps together. ''' from colorspacious import cspace_converter dc = 1. x = np.linspace(0.0, 1.0, 256) locs = [] # locations for text labels fig = plt.figure(figsize=(16, 6)) ax = fig.add_subplot(111) ax.set_xlim(-0.1, len(cm.cmap_d)/2. + 0.1) ax.set_ylim(0, 100) ax.set_xlabel('Lightness for each colormap', fontsize=14) for j, cmapname in enumerate(cm.cmapnames): if '_r' in cmapname: # skip reversed versions for plot continue cmap = cm.cmap_d[cmapname] # get the colormap instance rgb = cmap(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) L = lab[0, :, 0] if L[-1] > L[0]: ax.scatter(x+j*dc, L, c=x, cmap=cmap, s=300, linewidths=0.) else: ax.scatter(x+j*dc, L[::-1], c=x[::-1], cmap=cmap, s=300, linewidths=0.) locs.append(x[-1]+j*dc) # store locations for colormap labels # Set up labels for colormaps ax.xaxis.set_ticks_position('top') ticker = mpl.ticker.FixedLocator(locs) ax.xaxis.set_major_locator(ticker) formatter = mpl.ticker.FixedFormatter([cmapname for cmapname in cm.cmapnames]) ax.xaxis.set_major_formatter(formatter) labels = ax.get_xticklabels() for label in labels: label.set_rotation(60) if saveplot: fig.savefig('figures/lightness.png', bbox_inches='tight') fig.savefig('figures/lightness.pdf', bbox_inches='tight') plt.show()
def plot_cmap(cmap): fig, axs = plt.subplots(1, 2, figsize=(6, 2)) gradient = np.linspace(0, 1, 256) gradient = np.vstack((gradient, gradient)) axs[0].imshow(gradient, cmap=cmap, aspect="auto") axs[0].set_axis_off() x = np.linspace(0.0, 1.0, cmap.N + 1) x = (x[1:] + x[:-1]) / 2 rgb = cmap(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) L = lab[0, :, 0] axs[1].plot(x, lab[0, :, 0], color="k", zorder=+1) axs[1].scatter(x, lab[0, :, 0], c=cmap(x)) dL = 1 / (x[1] - x[0]) * np.abs(np.diff(lab[0, :, 0])) axs[1].plot(x[:-1], dL, c="k", ls="--") axs[1].set_ylabel(r"L (solid) & $\Delta$ L (dashed)")
def plot_lightness(saveplot=False): """Plot lightness of colormaps together. """ from colorspacious import cspace_converter dc = 1.0 x = np.linspace(0.0, 1.0, 256) locs = [] # locations for text labels fig = plt.figure(figsize=(16, 6)) ax = fig.add_subplot(111) ax.set_xlim(-0.1, len(cmaps) + 0.1) ax.set_ylim(0, 100) ax.set_xlabel("Lightness for each colormap") for j, cmap in enumerate(cmaps): rgb = cmap(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) # lab = color.rgb2lab(rgb) L = lab[0, :, 0] # import pdb; pdb.set_trace() # L = lab[0, :, 0] if L[-1] > L[0]: ax.scatter(x + j * dc, L, c=x, cmap=cmap, s=300, linewidths=0.0) else: ax.scatter(x + j * dc, L[::-1], c=x[::-1], cmap=cmap, s=300, linewidths=0.0) locs.append(x[-1] + j * dc) # store locations for colormap labels # Set up labels for colormaps ax.xaxis.set_ticks_position("top") ticker = mpl.ticker.FixedLocator(locs) ax.xaxis.set_major_locator(ticker) formatter = mpl.ticker.FixedFormatter([cmap.name for cmap in cmaps]) ax.xaxis.set_major_formatter(formatter) labels = ax.get_xticklabels() for label in labels: label.set_rotation(60) if saveplot: fig.savefig("figures/lightness.png", bbox_inches="tight") fig.savefig("figures/lightness.pdf", bbox_inches="tight") plt.show()
def plot_all_colormaps(cmaps, grayscale=False): """Plot all of the colormaps defined in this package""" grid = np.linspace(0, 1, 256) cmap_names = [name for name in cmaps if not name.endswith('_r')] nrows = len(cmap_names) fig, axes = plt.subplots(nrows, 1, figsize=(10, 1 * nrows), constrained_layout=True) # Turn off ticks & spines for ax in axes: ax.xaxis.set_visible(False) ax.yaxis.set_ticks([]) for _, sp in ax.spines.items(): sp.set_visible(False) for ax, name in zip(axes, cmap_names): cmap = cmaps[name] rgb = cmap(grid)[:, :3] if grayscale: from colorspacious import cspace_converter LAB = cspace_converter("sRGB1", "CAM02-UCS")(rgb) L = LAB[:, 0] / 1e2 H = np.repeat(L[:, None], 3, axis=1)[None] else: H = rgb[None] ax.imshow(H, aspect=20) ax.set_ylabel(name, ha='right', va='center', rotation=0) return fig, axes
def plot_lightness(cmaps): """Plot all of the colormaps as 1D lightness curves""" from colorspacious import cspace_converter grid = np.linspace(0, 1, 256) cmap_names = [name for name in cmaps if not name.endswith('_r')] nrows = int(np.ceil(len(cmap_names) / 3)) fig, axes = plt.subplots(nrows, 3, figsize=(9, 3 * nrows), sharex=True, sharey=True, constrained_layout=True) for i, (ax, name) in enumerate(zip(axes.flat, cmap_names)): cmap = cmaps[name] rgb = cmap(grid)[:, :3] LAB = cspace_converter("sRGB1", "CAM02-UCS")(rgb) L = LAB[:, 0] / 1e2 ax.plot(L) ax.set_title(name) ax.xaxis.set_ticks([]) ax.set_ylim(0, 1) for j in range(i + 1, len(axes.flat)): ax = axes.flat[j] ax.set_visible(False) for ax in axes[:, 0]: ax.set_ylabel('lightness') return fig, axes
import matplotlib.pyplot as plt import mpl_toolkits.mplot3d from matplotlib.gridspec import GridSpec from matplotlib.widgets import Button, Slider import matplotlib.colors from matplotlib.colors import LinearSegmentedColormap from colorspacious import cspace_converter from .minimvc import Trigger # Our preferred space (mostly here so we can easily tweak it when curious) UNIFORM_SPACE = "CAM02-UCS" GREYSCALE_CONVERSION_SPACE = "JCh" _sRGB1_to_JCh = cspace_converter("sRGB1", GREYSCALE_CONVERSION_SPACE) _JCh_to_sRGB1 = cspace_converter(GREYSCALE_CONVERSION_SPACE, "sRGB1") def to_greyscale(sRGB1): JCh = _sRGB1_to_JCh(sRGB1) JCh[..., 1] = 0 return _JCh_to_sRGB1(JCh) _sRGB1_to_uniform = cspace_converter("sRGB1", UNIFORM_SPACE) _uniform_to_sRGB1 = cspace_converter(UNIFORM_SPACE, "sRGB1") _deuter50_space = {"name": "sRGB1+CVD", "cvd_type": "deuteranomaly", "severity": 50} _deuter50_to_sRGB1 = cspace_converter(_deuter50_space, "sRGB1") _deuter100_space = {"name": "sRGB1+CVD", "cvd_type": "deuteranomaly",
""" at = np.asarray(at) at_flat = at.ravel() N = len(points) curve = np.zeros((at_flat.shape[0], 2)) for ii in range(N): curve += np.outer(Bernstein(N - 1, ii)(at_flat), points[ii]) return curve.reshape(at.shape + (2,)) if __name__ == "__main__": # colormap viridis viridis = { "xp": [ 22.674387857633945, 11.221508276482126, -14.356589454756971, -47.18817758739222, -34.59001004812521, -6.0516291196352654 ], "yp": [ -20.102530541012214, -33.08246073298429, -42.24476439790574, -5.595549738219887, 42.5065445026178, 40.13395157135497 ], "min_Jp": 18.8671875, "max_Jp": 92.5 } bezier = BezierModel(viridis["xp"], viridis["yp"]) # wir wollen (R,G,B) fuer den Wert bei at at = np.linspace(0,1,256) ap,bp = bezier.get_bezier_points_at([at]) Jp = (viridis["max_Jp"] - viridis["min_Jp"]) * at + viridis["min_Jp"] # CAM02-UCS ist ein Farbraum, sRGB ist der RGB Farbraum mit Werten fuer rot, gruen, blau in [0,1] sRGB = cspace_converter("CAM02-UCS", "sRGB1")(np.column_stack((Jp, ap, bp))) print(sRGB)
def ctype(self, new_ctype): self._cache = None self._converter = cspace_converter('sRGB255', new_ctype) self._ctype = new_ctype
nsubplots = int(np.ceil(len(cmap_list) / float(dsub))) # squeeze=False to handle similarly the case of a single subplot fig, axes = plt.subplots(nrows=nsubplots, squeeze=False, figsize=(7, 2.6*nsubplots)) for i, ax in enumerate(axes.flat): locs = [] # locations for text labels for j, cmap in enumerate(cmap_list[i*dsub:(i+1)*dsub]): # Get RGB values for colormap and convert the colormap in # CAM02-UCS colorspace. lab[0, :, 0] is the lightness. rgb = cm.get_cmap(cmap)(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) # Plot colormap L values. Do separately for each category # so each plot can be pretty. To make scatter markers change # color along plot: # http://stackoverflow.com/questions/8202605/matplotlib-scatterplot-colour-as-a-function-of-a-third-variable if cmap_category == 'Sequential': # These colormaps all start at high lightness but we want them # reversed to look nice in the plot, so reverse the order. y_ = lab[0, ::-1, 0] c_ = x[::-1] else: y_ = lab[0, :, 0] c_ = x
def draw(cmap_category, cmap_list): ''' draw ''' # Do subplots so that colormaps have enough space. # Default is 6 colormaps per subplot. dsub = _DSUBS.get(cmap_category, 6) nsubplots = int(np.ceil(len(cmap_list) / dsub)) # squeeze=False to handle similarly the case of a single subplot fig, axs = plt.subplots(nrows=nsubplots, squeeze=False, figsize=(7, 2.6 * nsubplots)) ax = None for i, ax in enumerate(axs.flat): locs = [] # locations for text labels for j, cmap in enumerate(cmap_list[i * dsub:(i + 1) * dsub]): # Get RGB values for colormap and convert the colormap in # CAM02-UCS colorspace. lab[0, :, 0] is the lightness. rgb = cm.get_cmap(cmap)(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) # Plot colormap L values. Do separately for each category # so each plot can be pretty. To make scatter markers change # color along plot: # http://stackoverflow.com/questions/8202605/ if cmap_category == 'Sequential': # These colormaps all start at high lightness but we want them # reversed to look nice in the plot, so reverse the order. y_ = lab[0, ::-1, 0] c_ = x[::-1] else: y_ = lab[0, :, 0] c_ = x dc = _DC.get(cmap_category, 1.4) # cmaps horizontal spacing ax.scatter(x + j * dc, y_, c=c_, cmap=cmap, s=300, linewidths=0.0) # Store locations for colormap labels if cmap_category in ('Perceptually Uniform Sequential', 'Sequential'): locs.append(x[-1] + j * dc) elif cmap_category in ('Diverging', 'Qualitative', 'Cyclic', 'Miscellaneous', 'Sequential (2)'): locs.append(x[int(x.size / 2.)] + j * dc) # Set up the axis limits: # * the 1st subplot is used as a reference for the x-axis limits # * lightness values goes from 0 to 100 (y-axis limits) ax.set_xlim(axs[0, 0].get_xlim()) ax.set_ylim(0.0, 100.0) # Set up labels for colormaps ax.xaxis.set_ticks_position('top') ticker = mpl.ticker.FixedLocator(locs) ax.xaxis.set_major_locator(ticker) formatter = mpl.ticker.FixedFormatter(cmap_list[i * dsub:(i + 1) * dsub]) ax.xaxis.set_major_formatter(formatter) ax.xaxis.set_tick_params(rotation=50) ax.set_ylabel('Lightness $L^*$', fontsize=12) ax.set_xlabel(cmap_category + ' colormaps', fontsize=14) fig.tight_layout(h_pad=0.0, pad=1.5)
# python colormap_uniformize.py tmp_cmap.csv # python colormap_uniformize.py tmp_cmap.csv # python colormap_uniformize.py tmp_cmap.csv # python colormap_uniformize.py tmp_cmap.csv import sys import time import csv import numpy as np from colorspacious import cspace_converter import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec from scipy.optimize import minimize # Function to represent colors in perceptually uniform space sRGB_to_uniform = cspace_converter('sRGB1', 'CAM02-UCS') if len(sys.argv) > 1: c_name = sys.argv[1] else: print("Usage: ", __FILE__, " _COLORMAP.csv_ [N_OUTPUT_POINT]") exit() # Load cmap with open(c_name, 'rb') as f: reader = csv.reader(f) cmap = np.array(list(reader)).astype(np.float) # number of output colors if len(sys.argv) > 2: n_output = int(sys.argv[2])
def _get_cm_type(cmap): """ Checks what the colormap type (sequential; diverging; cyclic; qualitative; misc) of the provided `cmap` is and returns it. Parameters ---------- cmap : str or :obj:`~matplotlib.colors.Colormap` object The registered name of the colormap in *MPL* or its corresponding :obj:`~matplotlib.colors.Colormap` object. Returns ------- cm_type : {'sequential'; 'diverging'; 'cyclic'; 'qualitative'; 'misc'} A string stating which of the defined colormap types the provided `cmap` has. """ # Obtain the colormap cmap = mplcm.get_cmap(cmap) # Get array of all values for which a colormap value is requested x = np.linspace(0, 1, cmap.N) # Get RGB values for colormap rgb = cmap(x)[:, :3] # Get lightness values of colormap lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) L = lab[:, 0] diff_L = np.diff(L) # Obtain central values of lightness N = cmap.N - 1 central_i = [int(np.floor(N / 2)), int(np.ceil(N / 2))] diff_L0 = np.diff(L[:central_i[0] + 1]) diff_L1 = np.diff(L[central_i[1]:]) # Obtain perceptual differences of last two and first two values lab_red = np.concatenate([lab[-2:], lab[:2]], axis=0) deltas = np.sqrt(np.sum(np.diff(lab_red, axis=0)**2, axis=-1)) # Check the statistics of cmap and determine the colormap type # QUALITATIVE # If the colormap has less than 40 values, assume it is qualitative if (cmap.N < 40): return ('qualitative') # MISC 1 # If the colormap has plateaus in lightness, it is misc elif np.any(np.isclose(diff_L, 0)): return ('misc') # SEQUENTIAL # If the lightness values always increase or decrease, it is sequential elif np.isclose(np.abs(np.sum(diff_L)), np.sum(np.abs(diff_L))): return ('sequential') # DIVERGING # If the lightness values have a central extreme and sequential sides # Then it is diverging elif (np.isclose(np.abs(np.sum(diff_L0)), np.sum(np.abs(diff_L0))) and np.isclose(np.abs(np.sum(diff_L1)), np.sum(np.abs(diff_L1)))): # If the perceptual difference between the last and first value is # comparable to the other perceptual differences, it is cyclic if np.all(np.abs(np.diff(deltas)) < deltas[::2]): return ('cyclic') # Otherwise, it is a normal diverging colormap else: return ('diverging') # MISC 2 # If none of the criteria above apply, it is misc else: return ('misc')
def create_cmap_overview(cmaps=None, savefig=None, use_types=True): """ Creates an overview plot containing all colormaps defined in the provided `cmaps`. Optional -------- cmaps : list of {str; :obj:`~matplotlib.colors.Colormap` objects}, dict \ of lists or None. Default: None A list of all colormaps that must be included in the overview plot. If dict of lists, the keys define categories for the colormaps. If *None*, all colormaps defined in *CMasher* are used instead. savefig : str or None. Default: None If not *None*, the path where the overview plot must be saved to. Else, the plot will simply be shown. use_types : bool. Default: True Whether all colormaps in `cmaps` should be categorized into their colormap types (sequential; diverging; cyclic; qualitative; misc). If `cmaps` is a dict, this value is ignored. Note ---- The colormaps in `cmaps` can either be provided as their registered name in *MPL*, or their corresponding :obj:`~matplotlib.colors.Colormap` object. Any provided reversed colormaps (colormaps that end their name with '_r') are ignored. """ # If cmaps is None, use cmap_d.values if cmaps is None: cmaps = cmrcm.cmap_d.values() # Create empty list of cmaps cmaps_list = [] # If cmaps is a dict, it has cm_types defined if isinstance(cmaps, dict): # Define empty dict of colormaps cmaps_dict = odict() # Save provided cmaps as something else input_cmaps = cmaps # Loop over all cm_types for cm_type, cmaps in input_cmaps.items(): # Add empty list of colormaps to cmaps_dict with this cm_type cmaps_dict[cm_type] = [] type_lst = cmaps_dict[cm_type] # Loop over all cmaps and remove reversed versions for cmap in cmaps: if isinstance(cmap, string_types) and not cmap.endswith('_r'): type_lst.append(mplcm.get_cmap(cmap)) elif not cmap.name.endswith('_r'): type_lst.append(cmap) # Sort the colormaps in this cm_type type_lst.sort(key=lambda x: x.name) # Convert entire cmaps_dict into a list again for key, value in cmaps_dict.items(): # If this cm_type has at least 1 colormap, add them if value: cmaps_list.append(key) cmaps_list.extend(value) # Else, it is a list with no cm_types else: # If cm_types are requested if use_types: # Define empty dict with the base cm_types cm_types = [ 'sequential', 'diverging', 'cyclic', 'qualitative', 'misc' ] cmaps_dict = odict([[cm_type, []] for cm_type in cm_types]) # Loop over all cmaps and remove reversed versions for cmap in cmaps: cm_type = _get_cm_type(cmap) if isinstance(cmap, string_types) and not cmap.endswith('_r'): cmaps_dict[cm_type].append(mplcm.get_cmap(cmap)) elif not cmap.name.endswith('_r'): cmaps_dict[cm_type].append(cmap) # Loop over all cm_types and sort their colormaps for cm_type in cm_types: cmaps_dict[cm_type].sort(key=lambda x: x.name) # Convert entire cmaps_dict into a list again for key, value in cmaps_dict.items(): # If this cm_type has at least 1 colormap, add them if value: cmaps_list.append(key) cmaps_list.extend(value) else: # Loop over all cmaps and remove reversed versions for cmap in cmaps: if isinstance(cmap, string_types) and not cmap.endswith('_r'): cmaps_list.append(mplcm.get_cmap(cmap)) elif not cmap.name.endswith('_r'): cmaps_list.append(cmap) cmaps_list.sort(key=lambda x: x.name) # Obtain the colorspace converter for showing cmaps in grey-scale cspace_convert = cspace_converter("sRGB1", "CAM02-UCS") # Create figure instance height = 0.4 * (len(cmaps_list) + 1) fig, axes = plt.subplots(figsize=(6.4, height), nrows=len(cmaps_list), ncols=2) w_pad, h_pad, wspace, hspace = fig.get_constrained_layout_pads() fig.subplots_adjust(top=(1 - 0.24 / height), bottom=0.01, left=0.2, right=0.99, wspace=0.05) fig.suptitle("Colormap Overview", fontsize=16, y=1.0, x=0.595) # If cmaps_list only has a single element, make sure axes is a list if (len(cmaps_list) == 1): axes = [axes] # Loop over all cmaps defined in cmaps list for ax, cmap in zip(axes, cmaps_list): # Turn axes off ax[0].set_axis_off() ax[1].set_axis_off() # If cmap is a string, it defines a cm_type if isinstance(cmap, string_types): # Write the cm_type as text in the correct position fig.text(0.595, ax[0].get_position().bounds[1], cmap, va='bottom', ha='center', fontsize=14) # Else, this is a colormap else: # Get array of all values for which a colormap value is requested x = np.linspace(0, 1, cmap.N) # Get RGB values for colormap rgb = cmap(x)[:, :3] # Get lightness values of colormap lab = cspace_convert(rgb) L = lab[:, 0] # Get corresponding RGB values for lightness values using neutral rgb_L = cmrcm.neutral(L / 99.99871678)[:, :3] # Add subplots ax[0].imshow(rgb[np.newaxis, ...], aspect='auto') ax[1].imshow(rgb_L[np.newaxis, ...], aspect='auto') pos = list(ax[0].get_position().bounds) x_text = pos[0] - 0.01 y_text = pos[1] + pos[3] / 2 fig.text(x_text, y_text, cmap.name, va='center', ha='right', fontsize=10) # If savefig is not None, save the figure if savefig is not None: plt.savefig(savefig, dpi=250) plt.close(fig) # Else, simply show it else: plt.show()
JCh_result = cspace_convert(RGB, "sRGB255", "JCh") # JCH_result[0] is J, JCH_result[1] is C, [JCH_result2] is h J_min = 0.0000000000000001 # Practically zero and avoids divide by zero warning J_max = JCh_result[0] # alter J_max if param. says so: if ARGS.BRIGHTNESS_OVERRIDE: J_max = ARGS.BRIGHTNESS_OVERRIDE if ARGS.DARK_TO_BRIGHT: # if told to reverse gradient (dark -> white), swap min,max: tmp = J_min; J_min = J_max; J_max = tmp C = JCh_result[1] # C h = JCh_result[2] # h JCh2RGB = cspace_converter("JCh", "sRGB255") # returns a function colorsRGB = [] # Thanks to help here: https://stackoverflow.com/a/7267806/1397555 descending_j_values = np.linspace(J_max, J_min, num=GLOBAL_NUMBER_OF_SHADES) for J in descending_j_values: # build JCh array: JCh = np.array([ [J, C, h] ]) # build RGB hex array: RGB = JCh2RGB(JCh) # clamp values to RGB ranges: R = clamp(RGB[0][0], 0, 255); G = clamp(RGB[0][1], 0, 255); B = clamp(RGB[0][2], 0, 255) # converts to two-digit (if needed) padded hex string: "{0:0{1}x}".format(255,2) R = "#" + "{0:0{1}x}".format(R,2); G = "{0:0{1}x}".format(G,2); B = "{0:0{1}x}".format(B,2); hex_string = R + G + B hex_string = hex_string.upper()
ax1d.axis('tight') ax1d.set_title('balance') # Circular colormap: phase ax1e.pcolor(X, cmap=cmocean.cm.phase) ax1e.set_xticks([]) ax1e.set_yticks([]) ax1e.axis('tight') ax1e.set_title('phase') ## row 2: Plot colormap in grayscale ## x = np.linspace(0, 1.0, 256) ax2a.text(-0.25, 0.1, 'b', rotation='horizontal', transform=ax2a.transAxes) # Grayscale # jch = cspace_converter("sRGB1", "JCh")(cmocean.cm.gray(x)[np.newaxis, :, :3]) jch = cspace_converter("sRGB1", "CAM02-UCS")(cmocean.cm.gray(x)[np.newaxis, :, :3]) L = jch[0, :, 0] L = np.float32(np.vstack((L, L, L))) ax2a.imshow(L, aspect='auto', cmap=cmocean.cm.gray, vmin=0, vmax=100.) ax2a.set_xticks([]) ax2a.set_yticks([]) # Jet jch = cspace_converter("sRGB1", "CAM02-UCS")(plt.cm.jet(x)[np.newaxis, :, :3]) L = jch[0, :, 0] L = np.float32(np.vstack((L, L, L))) ax2b.imshow(L, aspect='auto', cmap=cmocean.cm.gray, vmin=0, vmax=100.) ax2b.set_xticks([]) ax2b.set_yticks([]) # haline jch = cspace_converter("sRGB1", "CAM02-UCS")(cmocean.cm.haline(x)[np.newaxis, :, :3]) L = jch[0, :, 0]
def __init__(self, cm, uniform_space="CAM02-UCS", name=None, N=256, N_dots=50, show_gamut=False): if isinstance(cm, str): cm = plt.get_cmap(cm) if name is None: name = cm.name self._sRGB1_to_uniform = cspace_converter("sRGB1", uniform_space) self.fig = plt.figure() self.fig.suptitle("Colormap evaluation: %s" % (name,), fontsize=24) axes = _vis_axes(self.fig) x = np.linspace(0, 1, N) x_dots = np.linspace(0, 1, N_dots) RGB = cm(x)[:, :3] RGB_dots = cm(x_dots)[:, :3] ax = axes["cmap"] _show_cmap(ax, RGB) ax.set_title("The colormap in its glory") ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) def label(ax, s): ax.text(0.95, 0.05, s, horizontalalignment="right", verticalalignment="bottom", transform=ax.transAxes) def title(ax, s): ax.text(0.98, 0.98, s, horizontalalignment="right", verticalalignment="top", transform=ax.transAxes) Jpapbp = self._sRGB1_to_uniform(RGB) def delta_ymax(values): return max(np.max(values) * 1.1, 0) ax = axes["deltas"] local_deltas = N * np.sqrt(np.sum((Jpapbp[:-1, :] - Jpapbp[1:, :]) ** 2, axis=-1)) # print("perceptual delta peak-to-peak: %0.2f" % (np.ptp(local_deltas),)) ax.plot(x[1:], local_deltas) arclength = np.sum(local_deltas) / N rmse = np.std(local_deltas) title(ax, "Perceptual deltas") label(ax, "Length: %0.1f\nRMS deviation from flat: %0.1f (%0.1f%%)" % (arclength, rmse, 100 * rmse / arclength)) ax.set_ylim(-delta_ymax(-local_deltas), delta_ymax(local_deltas)) ax.get_xaxis().set_visible(False) ax = axes["cmap-greyscale"] _show_cmap(ax, to_greyscale(RGB)) ax.set_title("Black-and-white printed") ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) ax = axes["lightness-deltas"] ax.axhline(0, linestyle="--", color="grey") lightness_deltas = N * np.diff(Jpapbp[:, 0]) ax.plot(x[1:], lightness_deltas) title(ax, "Perceptual lightness deltas") lightness_arclength = np.sum(np.abs(lightness_deltas)) / N lightness_rmse = np.std(lightness_deltas) label( ax, "Length: %0.1f\nRMS deviation from flat: %0.1f (%0.1f%%)" % (lightness_arclength, lightness_rmse, 100 * lightness_rmse / np.mean(lightness_deltas)), ) # ax.set_ylim(0, ax.get_ylim()[1]) ax.set_ylim(-delta_ymax(-lightness_deltas), delta_ymax(lightness_deltas)) ax.get_xaxis().set_visible(False) # ax = axes['lightness'] # ax.plot(x, ciecam02.J) # label(ax, "Lightness (J)") # ax.set_ylim(0, 105) # ax = axes['colourfulness'] # ax.plot(x, ciecam02.M) # label(ax, "Colourfulness (M)") # ax = axes['hue'] # ax.plot(x, ciecam02.h) # label(ax, "Hue angle (h)") # ax.set_ylim(0, 360) def anom(ax, converter, name): _show_cmap(ax, np.clip(converter(RGB), 0, 1)) label(ax, name) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) anom(axes["deuteranomaly"], _deuter50_to_sRGB1, "Moderate deuteranomaly") anom(axes["deuteranopia"], _deuter100_to_sRGB1, "Complete deuteranopia") anom(axes["protanomaly"], _prot50_to_sRGB1, "Moderate protanomaly") anom(axes["protanopia"], _prot100_to_sRGB1, "Complete protanopia") ax = axes["gamut"] ax.plot(Jpapbp[:, 1], Jpapbp[:, 2], Jpapbp[:, 0]) Jpapbp_dots = self._sRGB1_to_uniform(RGB_dots) ax.scatter(Jpapbp_dots[:, 1], Jpapbp_dots[:, 2], Jpapbp_dots[:, 0], c=RGB_dots[:, :], s=80) # Draw a wireframe indicating the sRGB gamut self.gamut_patch = sRGB_gamut_patch(uniform_space) # That function returns a patch where each face is colored to match # the represented colors. For present purposes we want something # less... colorful. self.gamut_patch.set_facecolor([0.5, 0.5, 0.5, 0.1]) self.gamut_patch.set_edgecolor([0.2, 0.2, 0.2, 0.1]) ax.add_collection3d(self.gamut_patch) self.gamut_patch.set_visible(show_gamut) ax.view_init(elev=75, azim=-75) self.gamut_patch_toggle = Button(axes["gamut-toggle"], "Toggle gamut") def toggle(*args): self.gamut_patch.set_visible(not self.gamut_patch.get_visible()) plt.draw() self.gamut_patch_toggle.on_clicked(toggle) _setup_Jpapbp_axis(ax) images = [] image_args = [] example_dir = os.path.join(os.path.dirname(__file__), "examples") images.append(np.loadtxt(os.path.join(example_dir, "st-helens_before-modified.txt.gz")).T) image_args.append({}) # Adapted from # http://matplotlib.org/mpl_examples/images_contours_and_fields/pcolormesh_levels.py dx = dy = 0.05 y, x = np.mgrid[-5 : 5 + dy : dy, -5 : 10 + dx : dx] z = np.sin(x) ** 10 + np.cos(10 + y * x) + np.cos(x) + 0.2 * y + 0.1 * x images.append(z) image_args.append({}) # Peter Kovesi's colormap test image at # http://peterkovesi.com/projects/colourmaps/colourmaptest.tif images.append(np.load(os.path.join(example_dir, "colourmaptest.npy"))) image_args.append({}) def _deuter_transform(RGBA): # clipping, alpha handling RGB = RGBA[..., :3] RGB = np.clip(_deuter50_to_sRGB1(RGB), 0, 1) return np.concatenate((RGB, RGBA[..., 3:]), axis=-1) deuter_cm = TransformedCMap(_deuter_transform, cm) for i, (image, args) in enumerate(zip(images, image_args)): ax = axes["image%i" % (i,)] ax.imshow(image, cmap=cm, **args) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) ax_cb = axes["image%i-cb" % (i,)] ax_cb.imshow(image, cmap=deuter_cm, **args) ax_cb.get_xaxis().set_visible(False) ax_cb.get_yaxis().set_visible(False) axes["image0"].set_title("Sample images") axes["image0-cb"].set_title("Moderate deuter.")
from colorspacious import cspace_converter JCh2rgb = cspace_converter('JCh', 'sRGB1') import numpy as np from python2latex import Document, Plot, LinearColorMap, Palette # Create the document filepath = './examples/plot examples/custom colors and line labels example/' filename = 'custom_colors_and_line_labels_example' doc = Document(filename, doc_type='article', filepath=filepath) # Create color map in JCh space, in which each parameter is linear with human perception cmap = LinearColorMap( color_anchors=[(20, 45, 135), (81, 99, 495)], color_model='JCh', color_transform=lambda color: np.clip(JCh2rgb(color), 0, 1)) # Create a dynamical palette which generates as many colors as needed from the cmap. Note that by default, the range of color used expands with the number of colors. palette = Palette(colors=cmap, color_model='rgb') pal = Palette(colors=cmap, n_colors=2) # Create the data X = np.linspace(-1, 1, 50) Y = lambda c: np.exp(X * c) + c # Let us compare the different color palettes generated for different number of line plots for n_colors in [2, 3, 5, 10]: # Create a plot plot = doc.new( Plot(
def __init__(self, *components, **kwargs): ctype = kwargs.pop('ctype', 'sRGB255') self._components = cspace_convert(components, ctype, 'sRGB255') self._ctype = ctype self._converter = cspace_converter('sRGB255', self.ctype) self._cache = None
# squeeze=False to handle similarly the case of a single subplot fig, axs = plt.subplots(nrows=nsubplots, squeeze=False, figsize=(7, 2.6 * nsubplots)) for i, ax in enumerate(axs.flat): locs = [] # locations for text labels for j, cmap in enumerate(cmap_list[i * dsub:(i + 1) * dsub]): # Get RGB values for colormap and convert the colormap in # CAM02-UCS colorspace. lab[0, :, 0] is the lightness. rgb = cm.get_cmap(cmap)(x)[np.newaxis, :, :3] lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) # Plot colormap L values. Do separately for each category # so each plot can be pretty. To make scatter markers change # color along plot: # https://stackoverflow.com/q/8202605/ if cmap_category == 'Sequential': # These colormaps all start at high lightness but we want them # reversed to look nice in the plot, so reverse the order. y_ = lab[0, ::-1, 0] c_ = x[::-1] else: y_ = lab[0, :, 0] c_ = x
def create_cmap_overview(cmaps=None, *, savefig=None, use_types=True, sort='alphabetical', show_grayscale=True, plot_profile=False, dark_mode=False, title="Colormap Overview", wscale=1, hscale=1): """ Creates an overview plot containing all colormaps defined in the provided `cmaps`. Optional -------- cmaps : list of {str; :obj:`~matplotlib.colors.Colormap` objects}, dict \ of lists or None. Default: None A list of all colormaps that must be included in the overview plot. If dict of lists, the keys define categories for the colormaps. If *None*, all colormaps defined in *CMasher* are used instead. savefig : str or None. Default: None If not *None*, the path where the overview plot must be saved to. Else, the plot will simply be shown. use_types : bool. Default: True Whether all colormaps in `cmaps` should be categorized into their colormap types (sequential; diverging; cyclic; qualitative; misc). If `cmaps` is a dict, this value is ignored. sort : {'alphabetical'/'name'; 'lightness'}, function or None. Default: \ 'alphabetical' String or function indicating how the colormaps should be sorted in the overview. If 'alphabetical', the colormaps are sorted alphabetically on their name. If 'lightness', the colormaps are sorted based on their lightness profile. If function, a function definition that takes a :obj:`~matplotlib.colors.Colormap` object and returns the sorted position of that colormap. If *None*, the colormaps retain the order they were given in. show_grayscale : bool. Default: True Whether to show the grayscale versions of the given `cmaps` in the overview. plot_profile : bool or float. Default: False Whether the lightness profiles of all colormaps should be plotted. If not *False*, the lightness profile of a colormap is plotted on top of its gray-scale version and `plot_profile` is used for setting the alpha (opacity) value. If `plot_profile` is *True*, it will be set to `0.25`. If `show_grayscale` is *False*, this value is ignored. dark_mode : bool. Default: False Whether the colormap overview should be created using mostly dark colors. title : str or None. Default: "Colormap Overview" String to be used as the title of the colormap overview. If empty or *None*, no title will be used. wscale, hscale : float. Default: (1, 1) Floats that determine with what factor the colormap subplot dimensions in the overview should be scaled with. The default values uses the default dimensions for the subplots (which are determined by other input arguments). Notes ----- The colormaps in `cmaps` can either be provided as their registered name in :mod:`matplotlib.cm`, or their corresponding :obj:`~matplotlib.colors.Colormap` object. Any provided reversed colormaps (colormaps that end their name with '_r') are ignored if their normal versions were provided as well. If `plot_profile` is not set to *False*, the lightness profiles are plotted on top of the gray-scale colormap versions, where the y-axis ranges from 0% lightness to 100% lightness. The lightness profile transitions between black and white at 50% lightness. """ # Check value of show_grayscale if show_grayscale: # If True, the overview will have two columns ncols = 2 else: # If False, the overview will have one column and no profile plotted ncols = 1 wscale *= 0.5 plot_profile = False # Determine positions wscale = 0.2 + 0.8 * wscale left_pos = 0.2 / wscale spacing = 0.01 / wscale # If plot_profile is True, set it to its default value if plot_profile is True: plot_profile = 0.25 # Check if dark mode is requested if dark_mode: # If so, use dark grey for the background and light grey for the text edge_color = '#24292E' face_color = '#24292E' text_color = '#9DA5B4' else: # If not, use white for the background and black for the text edge_color = '#FFFFFF' face_color = '#FFFFFF' text_color = '#000000' # If cmaps is None, use cmap_d.values if cmaps is None: cmaps = cmrcm.cmap_d.values() # If sort is a string, obtain proper function if isinstance(sort, str): # Convert sort to lowercase sort = sort.lower() # Check what string was provided and obtain sorting function if sort in ('alphabetical', 'name'): def sort(x): return (x.name) elif (sort == 'lightness'): sort = _get_cmap_lightness_rank # Create empty list of cmaps cmaps_list = [] # If cmaps is a dict, it has cm_types defined if isinstance(cmaps, dict): # Set use_types to True use_types = True # Define empty dict of colormaps cmaps_dict = odict() # Save provided cmaps as something else input_cmaps = cmaps # Loop over all cm_types for cm_type, cmaps in input_cmaps.items(): # Add empty list of colormaps to cmaps_dict with this cm_type cmaps_dict[cm_type] = [] # Loop over all cmaps and remove reversed versions for cmap in cmaps: if isinstance(cmap, str): cmaps_dict[cm_type].append(mplcm.get_cmap(cmap)) else: cmaps_dict[cm_type].append(cmap) # Else, it is a list with no cm_types else: # If cm_types are requested if use_types: # Define empty dict with the base cm_types cm_types = [ 'sequential', 'diverging', 'cyclic', 'qualitative', 'misc' ] cmaps_dict = odict([[cm_type, []] for cm_type in cm_types]) # Loop over all cmaps and remove reversed versions for cmap in cmaps: cm_type = get_cmap_type(cmap) if isinstance(cmap, str): cmaps_dict[cm_type].append(mplcm.get_cmap(cmap)) else: cmaps_dict[cm_type].append(cmap) else: # Loop over all cmaps and remove reversed versions for cmap in cmaps: if isinstance(cmap, str): cmaps_list.append(mplcm.get_cmap(cmap)) else: cmaps_list.append(cmap) # If use_types is True, a dict is currently used if use_types: # Convert entire cmaps_dict into a list again for key, value in cmaps_dict.items(): # If this cm_type has at least 1 colormap, sort and add them if value: # Obtain the names of all colormaps names = [x.name for x in value] # Remove all reversed colormaps that also have their original off_dex = len(names) - 1 for i, name in enumerate(reversed(names)): if name.endswith('_r') and name[:-2] in names: value.pop(off_dex - i) # Sort the colormaps if requested if sort is not None: value.sort(key=sort) # Add to list cmaps_list.append((key, False)) cmaps_list.extend(value) # Else, a list is used else: # Obtain the names of all colormaps names = [x.name for x in cmaps_list] # Remove all reversed colormaps that also have their original off_dex = len(names) - 1 for i, name in enumerate(reversed(names)): if name.endswith('_r') and name[:-2] in names: cmaps_list.pop(off_dex - i) # Sort the colormaps if requested if sort is not None: cmaps_list.sort(key=sort) # Add title to cmaps_list if requested if title: cmaps_list.insert(0, (title, True)) # Obtain the colorspace converter for showing cmaps in grey-scale cspace_convert = cspace_converter("sRGB1", "CAM02-UCS") # Create figure instance height = (0.4 * len(cmaps_list) + 0.1) * hscale fig, axs = plt.subplots(figsize=(6.4 * wscale, height), nrows=len(cmaps_list), ncols=ncols, edgecolor=edge_color, facecolor=face_color) # Adjust subplot positioning fig.subplots_adjust(top=(1 - 0.05 / height), bottom=0.05 / height, left=left_pos, right=1.0 - spacing, wspace=0.05) # If cmaps_list only has a single element, make sure axs is a list if (len(cmaps_list) == 1): axs = [axs] # Loop over all cmaps defined in cmaps list for ax, cmap in zip(axs, cmaps_list): # Obtain axes objects and turn them off if show_grayscale: # Obtain Axes objects ax0, ax1 = ax # Turn axes off ax0.set_axis_off() ax1.set_axis_off() else: # Obtain Axes object ax0 = ax # Turn axis off ax0.set_axis_off() # Obtain position bbox of ax0 pos0 = ax0.get_position() # If cmap is a tuple, it defines a title or cm_type if isinstance(cmap, tuple): # Calculate title_pos title_pos = left_pos + (1 - spacing - left_pos) / 2 # If it is a title if cmap[1]: # Write the title as text in the correct position fig.text(title_pos, pos0.y0 + pos0.height / 2, cmap[0], va='center', ha='center', fontsize=18, c=text_color) # If it is a cm_type else: # Write the cm_type as text in the correct position fig.text(title_pos, pos0.y0, cmap[0], va='bottom', ha='center', fontsize=14, c=text_color) # Else, this is a colormap else: # Obtain the colormap type cm_type = get_cmap_type(cmap) # Get array of all values for which a colormap value is requested x = np.arange(cmap.N) # Get RGB values for colormap rgb = cmap(x)[:, :3] # Get lightness values of colormap lab = cspace_convert(rgb) L = lab[:, 0] # Normalize lightness values L /= 99.99871678 # Get corresponding RGB values for lightness values using neutral rgb_L = cmrcm.neutral(L)[:, :3] # Add colormap subplot ax0.imshow(rgb[np.newaxis, ...], aspect='auto') # Check if the lightness profile was requested if plot_profile and (cm_type != 'qualitative'): # Determine the points that need to be plotted plot_L = -(L - 0.5) points = np.stack([x, plot_L], axis=1) # Determine the colors that each point must have # Use black for L >= 0.5 and white for L <= 0.5. colors = np.zeros_like(plot_L, dtype=int) colors[plot_L >= 0] = 1 # Split points up into segments with the same color s_idx = np.nonzero(np.diff(colors))[0] + 1 segments = np.split(points, s_idx) # Loop over all pairs of adjacent segments for i, (seg1, seg2) in enumerate(zip(segments[:-1], segments[1:])): # Determine the point in the center of these segments central_point = (seg1[-1] + seg2[0]) / 2 # Add this point to the ends of these segments # This ensures that the color changes in between segments segments[i] = np.concatenate( [segments[i], [central_point]], axis=0) segments[i + 1] = np.concatenate( [[central_point], segments[i + 1]], axis=0) # Create an MPL LineCollection object with these segments lc = LineCollection(segments, cmap=cmrcm.neutral, alpha=plot_profile) lc.set_linewidth(1) # Determine the colors of each segment s_colors = [colors[0]] s_colors.extend(colors[s_idx]) s_colors = np.array(s_colors) # Set the values of the line-collection to be these colors lc.set_array(s_colors) # Add line-collection to this subplot ax1.add_collection(lc) # Add gray-scale colormap subplot if requested if show_grayscale: ax1.imshow(rgb_L[np.newaxis, ...], aspect='auto') # Plot the name of the colormap as text x_text = pos0.x0 - spacing y_text = pos0.y0 + pos0.height / 2 fig.text(x_text, y_text, cmap.name, va='center', ha='right', fontsize=10, c=text_color) # If savefig is not None, save the figure if savefig is not None: dpi = 100 if (path.splitext(savefig)[1] == '.svg') else 250 plt.savefig(savefig, dpi=dpi, facecolor=face_color, edgecolor=edge_color) plt.close(fig) # Else, simply show it else: plt.show()
import numpy as np from matplotlib.colors import ListedColormap from colorspacious import cspace_converter _JCh_to_sRGB1 = cspace_converter('JCh', 'sRGB1') cm_data = [] for i in range(256): RGBi = np.clip(_JCh_to_sRGB1((50, 100, 360. * i / 255)), 0, 1) cm_data.append(list(RGBi)) test_cm = ListedColormap(cm_data, name=__file__) if __name__ == "__main__": import matplotlib.pyplot as plt try: from viscm import viscm viscm(test_cm) except ImportError: print("viscm not found, falling back on simple display") plt.imshow(np.linspace(0, 100, 256)[None, :], aspect='auto', cmap=test_cm) plt.show()
def _get_cmap_lightness_rank(cmap): """ Returns a tuple of objects used for sorting the provided `cmap` based on its lightness profile. Parameters ---------- cmap : str or :obj:`~matplotlib.colors.Colormap` object The registered name of the colormap in :mod:`matplotlib.cm` or its corresponding :obj:`~matplotlib.colors.Colormap` object. Returns ------- L_type : int The type of lightness profile of `cmap`. This is only used for sequential colormaps. L_start : float The starting lightness value of `cmap`. For diverging colormaps, this is the central lightness value. L_rng : float The lightness range (L_max-L_min) of `cmap`. L_rmse : float The RMSE of the lightness profile of `cmap`. For diverging colormaps, this is the max RMSE of either half. name : str The name of `cmap`. For qualitative and miscellaneous colormaps, this is the only value that is used. """ # Obtain the colormap cmap = mplcm.get_cmap(cmap) # Get RGB values for colormap rgb = cmap(np.arange(cmap.N))[:, :3] # Get lightness values of colormap lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) L = lab[:, 0] # Determine the deltas of the lightness profile deltas = np.diff(L) derivs = (cmap.N - 1) * deltas # Set lightness profile type to 0 L_type = 0 # Determine the RMSE of the lightness profile of a sequential colormap if (get_cmap_type(cmap) == 'sequential'): # Take RMSE of entire lightness profile L_rmse = np.around(np.std(derivs), 1) # Calculate starting lightness value L_start = np.around(L[0], 1) # Determine type of lightness profile L_type += ~(np.sum(rgb[0]) == 0) * 2 L_type += ((np.sum(rgb[0]) == 0) == (np.sum(rgb[-1]) == 3)) # Diverging/cyclic colormaps elif get_cmap_type(cmap) in ('diverging', 'cyclic'): # Calculate RMSE of both halves central_i = [int(np.floor(cmap.N / 2)), int(np.ceil(cmap.N / 2))] L_rmse = np.max([ np.around(np.std(derivs[:central_i[0]]), 1), np.around(np.std(derivs[central_i[1]:]), 1) ]) # Calculate central lightness value L_start = np.around(np.average(L[central_i]), 1) # Determine lightness range for sequential/diverging/cyclic colormaps if get_cmap_type(cmap) in ('sequential', 'diverging', 'cyclic'): L_min = np.around(np.min(L), 1) L_max = np.around(np.max(L), 1) L_rng = np.around(np.abs(L_max - L_min), 1) # For qualitative/misc colormaps, set all lightness values to zero else: L_type = L_start = L_rng = L_rmse = 0 # Return lightness contributions to the rank return (L_type, L_start, L_rng, L_rmse, cmap.name)