Skip to content

Instantly share code, notes, and snippets.

@mwaskom
Created February 18, 2015 17:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mwaskom/842d1497b6892d081bfb to your computer and use it in GitHub Desktop.
Save mwaskom/842d1497b6892d081bfb to your computer and use it in GitHub Desktop.
A simple IPython widget to interactively design an Hcl colormap
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Interactive H$_{CL}$ Colormap Designer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook is based off a proposed system for designing the new default matplotlib colormap proposed [here](http://nbviewer.ipython.org/gist/mwaskom/6a43a3b94eca4a9e2e8b). It generalizes the approach into an interactive IPython widget, so that one can play with the ramps for the three paramters and see in real time what the resulting colormap will look like.\n",
"\n",
"Originally written by Michael Waskom, February 18, 2015. Placed in public domain."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
":0: FutureWarning: IPython widgets are experimental and may change in the future.\n"
]
}
],
"source": [
"import numpy as np\n",
"import matplotlib as mpl\n",
"import matplotlib.pyplot as plt\n",
"from IPython.html.widgets import interact, IntRangeSlider, IntSlider"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from colormath.color_objects import sRGBColor, LCHabColor, LabColor\n",
"from colormath.color_conversions import convert_color"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def in_gamut(rgb_color):\n",
" rgb_vals = np.array(rgb_color.get_value_tuple())\n",
" return ((0 < rgb_vals) & (rgb_vals < 1)).all()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def make_colormap(L_ramp, c_ramp, h_ramp):\n",
" rgb_colors = []\n",
" gamut_status = []\n",
" for L, c, h in zip(L_ramp, c_ramp, h_ramp):\n",
" Lch = LCHabColor(L, c, h)\n",
" rgb = convert_color(Lch, sRGBColor)\n",
" rgb_colors.append((rgb.clamped_rgb_r, rgb.clamped_rgb_g, rgb.clamped_rgb_b))\n",
" gamut_status.append(in_gamut(rgb))\n",
" cmap = mpl.colors.LinearSegmentedColormap.from_list(\"hcl_colormap\", rgb_colors)\n",
" return cmap, gamut_status"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def plot_colormap(cmap, gamut_status):\n",
" f, (ax_cmap, ax_gamut) = plt.subplots(2, figsize=(10, 1), sharex=True,\n",
" gridspec_kw={\"height_ratios\": (3, 1)})\n",
" x = np.linspace(0, 1, 256)\n",
" ax_cmap.pcolormesh(np.array([x]), cmap=cmap)\n",
" ax_cmap.set_axis_off()\n",
"\n",
" ax_gamut.pcolormesh(np.array(gamut_status)[np.newaxis, :], cmap=\"Greys_r\", vmin=-.5)\n",
" ax_gamut.set_axis_off()\n",
" ax_gamut.set(xlim=(0, 256))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's the widget itself. If you downloaded this notebook, run the cell and you'll see the interactive part. It shows the colormap and then below the colormap it shows where we have strayed out of gamut (assuming I did the calculations right)."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": [
"iVBORw0KGgoAAAANSUhEUgAAAk8AAABZCAYAAAAn18DBAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n",
"AAALEgAACxIB0t1+/AAAAwhJREFUeJzt3dtt2zAAhlHRdtfoHN2kM2iKjuFx2Yf4IlGUrD9NY9g4\n",
"5yWQeREdpMoHo0BKrXUAAGCfw7MPAADwSsQTAEBAPAEABMQTAEBAPAEABMQTAEBAPAEABMQTAEBA\n",
"PAEABMQTAEBAPAEABE7fdaPy6/fHH9ErZZh9vfbb7bpMFjWvPbruvhbM/cz+l+tyuT5dv5b7mvtr\n",
"H9fHy/XxMuc42f/QjN2v5+OH6Zpm7iGZ+2CP3j5lc/+9ayb7376HzZwyn1s27zN079N7j4v7NGv3\n",
"7Ds9/31sPud2n2Z8+l7asXbNbG4z1vwLmv6UduaUldfX38fienP/dk1drHm4/+w9t2O1O3frTGtr\n",
"9sxpx/fM6Z6/1GZus2Zy/rWxaM3G+dtHbxnaR3KdL96cu9x/eHCWofd9au655yztPmt7dO/5D2t6\n",
"518da36Ae9+n5a+o5XtezL39ENb++Mb+i7W75n5m/96aBw+tydy69lBp5tbp/s0//ttY50FRFw+K\n",
"65rlg/rHzz/Tu8z45AkAICCeAAAC4gkAICCeAAAC4gkAICCeAAAC4gkAICCeAAAC4gkAICCeAAAC\n",
"4gkAICCeAAAC4gkAICCeAAAC4gkAICCeAAAC4gkAICCeAAAC4gkAICCeAAAC4gkAICCeAAAC4gkA\n",
"ICCeAAAC4gkAICCeAAAC4gkAICCeAAAC4gkAICCeAAAC4gkAICCeAAAC4gkAICCeAAAC4gkAICCe\n",
"AAAC4gkAIFBqrc8+AwDAy/DJEwBAQDwBAATEEwBAQDwBAARO33WjcRzf+n+mn8/nZx8BgDc0juOz\n",
"j/BfvMDvzbI24JMnAICAeAIACIgnAICAeAIACIgnAICAeAIACIgnAICAeAIACIgnAICAeAIACIgn\n",
"AICAeAIACJRa3/rv9QIAfCmfPAEABMQTAEBAPAEABMQTAEBAPAEABMQTAEBAPAEABMQTAEBAPAEA\n",
"BMQTAEBAPAEABMQTAEBAPAEABMQTAEBAPAEABMQTAEBAPAEABMQTAEBAPAEABMQTAEDgLxWJOKtZ\n",
"v31RAAAAAElFTkSuQmCC\n"
],
"text/plain": [
"<matplotlib.figure.Figure at 0x1044b5510>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"@interact\n",
"def choose_colormap(\n",
" L=IntRangeSlider(min=0, max=100, value=(20, 90), width=450),\n",
" c=IntRangeSlider(min=0, max=100, value=(30, 50), width=450),\n",
" h_start=IntSlider(min=0, max=360, value=240, width=450),\n",
" h_rot=IntSlider(min=-360, max=360, value=210, width=450)\n",
" ):\n",
" \n",
" L_ramp = np.linspace(*L, num=256)\n",
" c_ramp = np.linspace(*c, num=256)\n",
" h_ramp = np.linspace(h_start, h_start + h_rot, 256) % 360\n",
" cmap, gamut_status = make_colormap(L_ramp, c_ramp, h_ramp)\n",
" plot_colormap(cmap, gamut_status)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.9"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment