Created
February 18, 2015 17:30
-
-
Save mwaskom/842d1497b6892d081bfb to your computer and use it in GitHub Desktop.
A simple IPython widget to interactively design an Hcl colormap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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