def post(Jpapbp, cls, roundup, fname): adjust = globals()["adjust_" + cls] Jpapbp = adjust(Jpapbp, roundup) save_ctab(transform(Jpapbp, inverse=True), fname + ext) print(" Rounded up to {}; saved to \"{}\"".format(roundup, fname + ext)) Jpapbp = symmetrize(Jpapbp, bitonic=True, diffuse=False) save_ctab(transform(Jpapbp, inverse=True), fname + "s" + ext) print(" Symmetrized; saved to \"{}\"".format(fname + "s" + ext))
def ehtrainbow( N=Nq, Jp=73.16384, # maximizing minimal Cp for all hue Cp=None, hp0=32.1526953043875, # offset the hue so that value==0 is red eps=1024 * np.finfo(np.float).eps, **kwargs): """Create a perceptually uniform rainbow colormap""" name = kwargs.pop('name', "new eht colormap") hp = np.linspace(np.pi / 180 * (hp0), np.pi / 180 * (hp0 + 360), Nq + 1) Jp = np.full(len(hp), Jp) if Cp is not None: if Cp == 'minmax': Cp = min(max_chroma(Jp, hp)) ap = Cp * np.cos(hp) bp = Cp * np.sin(hp) Jpapbp = np.array([np.full(len(hp), Jp), ap, bp]).T sRGB = transform(Jpapbp[:-1, :], inverse=True) return ListedColormap(sRGB, name=name) Cp = max_chroma(Jp, hp) ap = Cp * np.cos(hp) bp = Cp * np.sin(hp) dE = np.sqrt((Jp[1:] - Jp[:-1])**2 + (ap[1:] - ap[:-1])**2 + (bp[1:] - bp[:-1])**2) cE = np.concatenate(([0], np.cumsum(dE))) for i in range(256): cE_new = np.linspace(0, max(cE), len(cE)) hp_new = np.interp(cE_new, cE, hp) Cp_new = max_chroma(Jp, hp_new) if np.max(abs(Cp - Cp_new)) < eps: break Cp = Cp_new hp = hp_new ap = Cp * np.cos(hp) bp = Cp * np.sin(hp) dE = np.sqrt((Jp[1:] - Jp[:-1])**2 + (ap[1:] - ap[:-1])**2 + (bp[1:] - bp[:-1])**2) cE = np.concatenate(([0], np.cumsum(dE))) else: print("WARNING: ehtuniform() has not fully converged") Jpapbp = np.array([Jp, ap, bp]).T sRGB = transform(Jpapbp[:-1, :], inverse=True) return ListedColormap(np.clip(sRGB, 0, 1), name=name)
def _JChp(ax1, cmap): """Plot J', C', and h' of a colormap as function of the mapped value Args: ax1 (matplotlib.axes.Axes): The matplotlib Axes to be plot on. cmap (string or matplotlib.colors.Colormap): The colormap to be plotted. """ ctab = get_ctab(cmap) # get the colormap as a color table in sRGB Jpapbp = transform(ctab) # transform color table into CAM02-UCS colorspace Jp = Jpapbp[:, 0] ap = Jpapbp[:, 1] bp = Jpapbp[:, 2] Cp = np.sqrt(ap * ap + bp * bp) hp = np.arctan2(bp, ap) * 180 / np.pi v = np.linspace(0.0, 1.0, len(Jp)) ax1.set_title(cmap if isinstance(cmap, basestring) else cmap.name) ax1.set_xlabel("Value") ax2 = ax1.twinx() ax1.set_ylim(0, 100) ax1.set_ylabel("J' & C' (0-100)") ax2.set_ylim(-180, 180) ax2.set_ylabel("h' (degrees)") ax1.scatter(v, Jp, color=ctab) ax1.plot(v, Cp, c='k', linestyle='--') ax2.scatter(v[::15], hp[::15], s=12, c='k')
def ehtcmap(N=Nq, Jpmin=15.0, Jpmax=95.0, Cpmin=0.0, Cpmax=64.0, hpmin=None, hpmax=90.0, hp=None, **kwargs): name = kwargs.pop('name', "new eht colormap") Jp = np.linspace(Jpmin, Jpmax, num=N) if hp is None: if hpmin is None: hpmin = hpmax - 60.0 q = 0.25 * (hpmax - hpmin) hp = np.clip(np.linspace(hpmin - 3 * q, hpmax + q, num=N), hpmin, hpmax) elif callable(hp): hp = hp(np.linspace(0.0, 1.0, num=N)) hp *= np.pi / 180.0 Cp = max_chroma(Jp, hp, Cpmin=Cpmin, Cpmax=Cpmax) Jpapbp = np.stack([Jp, Cp * np.cos(hp), Cp * np.sin(hp)], axis=-1) Jpapbp = symmetrize(Jpapbp, **kwargs) sRGB = transform(Jpapbp, inverse=True) return ListedColormap(np.clip(sRGB, 0, 1), name=name)
def mergecmap(cmplist, **kwargs): """Merge color maps An inelegant function to merge a list of existing colormaps into one. TODO: design a more elegant interface. """ name = kwargs.pop('name', "new eht colormap") matchC = kwargs.pop('matchC', False) ctabs = [] for cmp in cmplist: ctab = get_ctab(cmp['name']) if cmp.get('revert'): ctab = ctab[::-1] ctabs += [ctab] if matchC: n = len(ctabs[0]) mCp = getCp(ctabs[0]) for ctab in ctabs[1:]: if len(ctab) != n: raise ValueError("Fail to match chroma; " + "colormap seguments have different lengths") mCp = np.minimum(mCp, getCp(ctab)) for i in range(len(ctabs)): Jpapbp = transform(ctabs[i]) Cp = np.sqrt(Jpapbp[:, 1] * Jpapbp[:, 1] + Jpapbp[:, 2] * Jpapbp[:, 2]) f = mCp / (Cp + 1.0e-32) Jpapbp[:, 1] *= f Jpapbp[:, 2] *= f ctabs[i] = transform(Jpapbp, inverse=True) ctab = [crow for ctab in ctabs for crow in ctab] # flattern list of list return ListedColormap(np.clip(ctab, 0, 1), name=name)
def gethue(color): """Get the hue of a color""" if isinstance(color, float): return color if is_color_like(color): RGB = to_rgba(color)[:3] else: raise ValueError("color is not color like") Jp, ap, bp = transform(np.array([RGB]))[0] hp = np.arctan2(bp, ap) * 180 / np.pi print("Decode color \"{}\"; h' = {}".format(color, hp)) return hp
def visualize_colors(ax, Jp=73.16384, L=50): N = 2 * (8*L) + 1 aP = np.linspace(-L,L,N) bP = np.linspace(-L,L,N) ap, bp = np.meshgrid(aP, bP) Jpapbp = np.array([np.full(N*N, Jp), ap.flatten(), bp.flatten()]).T sRGB = transform(Jpapbp, inverse=True) sRGB[invalid(sRGB),:] = 0 ax.imshow(sRGB.reshape(N,N,3), origin='lower', extent=[-L,L,-L,L]) ax.set_xlabel("a'") ax.set_ylabel("b'")
def pre(cname): return transform(get_ctab(get_cmap(cname)))
def getCp(ctab): Jpapbp = transform(ctab) return np.sqrt(Jpapbp[:, 1] * Jpapbp[:, 1] + Jpapbp[:, 2] * Jpapbp[:, 2])
def ehtuniform( N=Nq, JpL=6.25, JpR=93.75, # consistent with 17 quantize levels CpL=0.0, CpR=64.0, hpL='coral', hpR='gold', hpD=None, eps=1024 * np.finfo(np.float).eps, **kwargs): """Create a perceptually uniform colormap""" name = kwargs.pop('name', "new eht colormap") hpL = gethue(hpL) * np.pi / 180.0 hpR = gethue(hpR) * np.pi / 180.0 if hpD is None: dhp = hpR - hpL while dhp < 0: dhp += 2 * np.pi while dhp > 2 * np.pi: dhp -= 2 * np.pi hpD = +1 if dhp < np.pi else -1 if (hpR - hpL) * hpD < 0.0: hpR += hpD * 2.0 * np.pi Jp = np.linspace(JpL, JpR, N) hp = np.linspace(hpL, hpR, N - 2) Cp = max_chroma(Jp[1:-1], hp) Cp = np.concatenate(([CpL], Cp, [CpR])) hp = np.concatenate(([hpL], hp, [hpR])) ap = Cp * np.cos(hp) bp = Cp * np.sin(hp) dE = np.sqrt((Jp[1:] - Jp[:-1])**2 + (ap[1:] - ap[:-1])**2 + (bp[1:] - bp[:-1])**2) cE = np.concatenate(([0], np.cumsum(dE))) for i in range(256): cE_new = np.linspace(0, max(cE), len(cE)) hp_new = np.interp(cE_new, cE, hp) Cp_new = np.interp(cE_new, cE, Cp) if hpD > 0: edgeL = hp_new <= hpL edge = np.logical_and(hpL < hp_new, hp_new < hpR) edgeR = hpR <= hp_new else: edgeL = hp_new >= hpL edge = np.logical_and(hpL > hp_new, hp_new > hpR) edgeR = hpR >= hp_new Cp_tmp = max_chroma(Jp[edge], hp_new[edge]) Cp_new[edgeL] *= Cp_tmp[0] / Cp_new[edge][0] Cp_new[edgeR] *= Cp_tmp[-1] / Cp_new[edge][-1] Cp_new[edge] = Cp_tmp if np.max(abs(Cp - Cp_new)) < eps: break Cp = Cp_new hp = hp_new ap = Cp * np.cos(hp) bp = Cp * np.sin(hp) dE = np.sqrt((Jp[1:] - Jp[:-1])**2 + (ap[1:] - ap[:-1])**2 + (bp[1:] - bp[:-1])**2) cE = np.concatenate(([0], np.cumsum(dE))) else: print("WARNING: ehtuniform() has not fully converged") Jpapbp = np.array([Jp, ap, bp]).T sRGB = transform(Jpapbp, inverse=True) return ListedColormap(np.clip(sRGB, 0, 1), name=name)