diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..443c917
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,82 @@
+ Colour Palette Generator script.
+ Copyright (c) 2014 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+Furthermore, the ColorBrewer colour schemes are covered by the following:
+
+ Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and
+ The Pennsylvania State University.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions as source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. The end-user documentation included with the redistribution, if
+ any, must include the following acknowledgment: "This product
+ includes color specifications and designs developed by Cynthia
+ Brewer (http://colorbrewer.org/)." Alternately, this
+ acknowledgment may appear in the software itself, if and
+ wherever such third-party acknowledgments normally appear.
+
+ 4. The name "ColorBrewer" must not be used to endorse or promote
+ products derived from this software without prior written
+ permission. For written permission, please contact Cynthia
+ Brewer at cbrewer@psu.edu.
+
+ 5. Products derived from this software may not be called
+ "ColorBrewer", nor may "ColorBrewer" appear in their name,
+ without prior written permission of Cynthia Brewer.
+
+Furthermore, Solarized colour schemes are covered by the following:
+
+ Copyright (c) 2011 Ethan Schoonover
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to permit
+ persons to whom the Software is furnished to do so, subject to the
+ following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+Apache License, Version 2.0 is available in LICENSE.AL2 file. Original
+license accompanying ColorBrewer colour schemes is available in LICENSE.CB
+file. Original license accompanying Solarized project is available in
+LICENSE.SOL file.
diff --git a/LICENSE.AL2 b/LICENSE.AL2
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE.AL2
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/LICENSE.CB b/LICENSE.CB
new file mode 100644
index 0000000..2ac775d
--- /dev/null
+++ b/LICENSE.CB
@@ -0,0 +1,38 @@
+Apache-Style Software License for ColorBrewer software and ColorBrewer Color
+Schemes
+
+Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania State
+University.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions as source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. The end-user documentation included with the redistribution, if any, must
+include the following acknowledgment: "This product includes color
+specifications and designs developed by Cynthia Brewer
+(http://colorbrewer.org/)." Alternately, this acknowledgment may appear in the
+software itself, if and wherever such third-party acknowledgments normally
+appear.
+
+4. The name "ColorBrewer" must not be used to endorse or promote products
+derived from this software without prior written permission. For written
+permission, please contact Cynthia Brewer at cbrewer@psu.edu.
+
+5. Products derived from this software may not be called "ColorBrewer", nor
+may "ColorBrewer" appear in their name, without prior written permission of
+Cynthia Brewer.
diff --git a/LICENSE.SOL b/LICENSE.SOL
new file mode 100644
index 0000000..ee08d7e
--- /dev/null
+++ b/LICENSE.SOL
@@ -0,0 +1,20 @@
+Copyright (c) 2011 Ethan Schoonover
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/demo.html b/demo.html
new file mode 100644
index 0000000..35f7d34
--- /dev/null
+++ b/demo.html
@@ -0,0 +1,85 @@
+
+
Palette generator demo
+
+
+
+
+
+
+
“cbf” after the palette's name means given palette is
+ “colourblind friendly”. All single hue palettes are colourblind
+ friendly.
+
In RGB gradients the ones denoted “linear” calculate value for
+ the gradient prior to applying gamma function. In theory, that
+ means the gradient should represent perceived increase in
+ luminosity better.
+
Paul Tol's palettes have been designed to be colourblind
+ friendly as well as printer friendly. More information about
+ them can be found at
+ www.sron.nl/~pault.
+
ColorBrewer palettes have been designed by Cynthia Brewer for
+ use in maps. More information about them, including interactive
+ demo, can be found at
+ colorbrewer2.org.
+
Soralized palette have been designed by Ethan Schoonover for
+ use with tirminal and GUI applications. As such, it has not
+ been optimised for use in graphs or maps, but the library
+ includes them nonetheless. More information about Solarized can
+ be found at
+ ethanschoonover.com/solarized.
+
+
+
diff --git a/demo.js b/demo.js
new file mode 100644
index 0000000..d5242f2
--- /dev/null
+++ b/demo.js
@@ -0,0 +1,236 @@
+'use strict';
+
+(function() {
+ var byId = document.getElementById.bind(document);
+
+
+ var transformColors = function(colors, callback) {
+ if (!callback) {
+ return colors;
+ }
+ return colors.map(function(color) {
+ var c = parseInt(color, 16);
+ return callback(c >> 16, (c >> 8) & 255, c & 255).map(function(v) {
+ v = Math.floor(v);
+ v = Number(v > 0 ? (v < 255 ? v : 255) : 0).toString(16);
+ return v.length == 1 ? '0' + v : v;
+ }).join('');
+ });
+ };
+
+ var blindnessFilters = {
+ green: {
+ name: 'Green-blindness (6% of men, 0.4% of women)',
+ func: function(r, g, b) {
+ r = Math.pow(r, 2.2);
+ g = Math.pow(g, 2.2);
+ b = Math.pow(b, 2.2);
+ var R = Math.pow(0.02138 + 0.677 * g + 0.2802 * r, 1 / 2.2);
+ var B = Math.pow(0.02138 * (1 + g - r) + 0.9572 * b, 1 / 2.2);
+ return [R, R, B];
+ }
+ },
+ red: {
+ name: 'Red-blindness (2.5% of men)',
+ func: function(r, g, b) {
+ r = Math.pow(r, 2.2);
+ g = Math.pow(g, 2.2);
+ b = Math.pow(b, 2.2);
+ var R = Math.pow(0.003974 + 0.8806 * g + 0.1115 * r, 1 / 2.2);
+ var B = Math.pow(0.003974 * (1 - g + r) + 0.9921 * b, 1 / 2.2);
+ return [R, R, B];
+ }
+ },
+ gray: {
+ name: 'Grayscale',
+ func: function(r, g, b) {
+ g = 0.2126 * r + 0.7152 * g + 0.0722 * b;
+ return [g, g, g];
+ }
+ }
+ };
+ (function(select) {
+ var keys = [];
+ for (var key in blindnessFilters) {
+ keys.push(key);
+ }
+ keys.sort();
+ for (var i = 0; (key = keys[i]); ++i) {
+ var option = document.createElement('option');
+ option.value = key;
+ option.appendChild(document.createTextNode(blindnessFilters[key].name));
+ select.appendChild(option);
+ }
+ })(byId('blindness'));
+
+
+ var createDom = function(tag, opt_attrs, varargs) {
+ var el = document.createElement(tag);
+ if (opt_attrs) {
+ for (var name in opt_attrs) {
+ el.setAttribute(name, opt_attrs[name]);
+ }
+ }
+ for (var i = 2, child; (child = arguments[i]); ++i) {
+ if (typeof child === 'string') {
+ child = document.createTextNode(child);
+ }
+ el.appendChild(child);
+ }
+ return el;
+ };
+
+
+ var createColorRow = function(colors, title) {
+ var row = createDom('tr', null,
+ createDom('td'),
+ createDom('td', null, title))
+
+ if (colors) {
+ var width = Math.max(Math.round(500 / colors.length), 5);
+ var cell = document.createElement('td');
+ row.firstChild.innerHTML = colors.map(function(color) {
+ return '';
+ }).join('');
+ } else {
+ row.firstChild.innerHTML = 'Too many colours requested.';
+ }
+
+ return row;
+ };
+
+
+ var palettes = byId('palettes');
+ var defaultBackground = palettes.style.backgroundColor;
+ var tooltip = byId('tooltip');
+
+ var mouseMoveHandler = function(e) {
+ var target = e.target, bg;
+ if (tooltip.firstChild) {
+ tooltip.removeChild(tooltip.firstChild);
+ }
+ if (target && target.nodeName == 'SPAN') {
+ bg = target.style.backgroundColor;
+ }
+ bg = bg || defaultBackground;
+ tooltip.appendChild(document.createTextNode(bg));
+ tooltip.style.display = bg ? '' : 'none';
+ palettes.style.backgroundColor = bg;
+ };
+ palettes.addEventListener('mousemove', mouseMoveHandler, false);
+ palettes.addEventListener('mouseover', mouseMoveHandler, false);
+
+ palettes.addEventListener('click', function(e) {
+ var target = e.target;
+ if (target && target.nodeName == 'SPAN') {
+ defaultBackground = target.style.backgroundColor || defaultBackground;
+ }
+ }, false);
+
+ var regenerate = function() {
+ var transform = blindnessFilters[byId('blindness').value];
+ transform = transform ? transform.func : null;
+ var num = parseInt(byId('number').value, 10);
+ num = num > 1 ? num < 100 ? num : 100 : 1;
+
+ while (palettes.firstChild) {
+ palettes.removeChild(palettes.firstChild);
+ }
+
+ var table = document.createElement('table'), tbody;
+ palettes.appendChild(table);
+
+ var addHeading = function(title) {
+ tbody = createDom('tbody', null,
+ createDom('tr', null,
+ createDom('th', { colspan: '2' },
+ title)));
+ table.appendChild(tbody);
+ };
+
+ var add = function(title, name, varargs) {
+ var colors;
+ if (typeof name === typeof add && !name.scheme_name) {
+ colors = palette.generate(name, num);
+ } else {
+ var scheme = name;
+ if (typeof name === 'string') {
+ title = name + ': ' + title;
+ scheme = palette.listSchemes(name)[0];
+ }
+ var args = Array.prototype.slice.call(arguments, 1);
+ args[0] = num;
+ colors = scheme.apply(scheme, args);
+ }
+ if (colors) {
+ colors = transformColors(colors, transform);
+ }
+ tbody.appendChild(createColorRow(colors, title || name))
+ };
+
+ addHeading("Paul Tol's palettes");
+ add("Tol's qualitative palette (cbf)", 'tol');
+ add("Tol's Diverging palette (cbf)", 'tol-dv');
+ add("Tol's Sequential palette (cbf)", 'tol-sq');
+ add("Tol's Rainbow palette (cbf)", 'tol-rainbow');
+
+ ['sequential', 'diverging', 'qualitative'].forEach(function(type) {
+ addHeading('ColorBrewer ' + type + ' palettes');
+ palette.listSchemes('cb-' + type).forEach(function(scheme) {
+ var title = scheme.scheme_name;
+ if (scheme.cbf_max >= scheme.max) {
+ title += ' (cbf)';
+ } else if (scheme.cbf_max) {
+ title += ' (cbf if no more than ' + scheme.cbf_max + ' colours)';
+ }
+ add(title, scheme);
+ });
+ });
+
+ addHeading("HSV rainbows");
+ add('HSV Rainbow (s=1, v=1)', 'rainbow');
+ add('HSV Rainbow (s=.5, v=1)', 'rainbow', 0.5);
+ add('HSV Rainbow (s=1, v=.5)', 'rainbow', 1, 0.5);
+ add('HSV Rainbow (s=.5, v=.5)', 'rainbow', 0.5, 0.5);
+
+ addHeading("RGB gradients");
+ add('Red',
+ function(x) { return palette.rgbColor(x, 0, 0); });
+ add('Red (linear)',
+ function(x) { return palette.linearRgbColor(x, 0, 0); });
+ add('Green',
+ function(x) { return palette.rgbColor(0, x, 0); });
+ add('Green (linear)',
+ function(x) { return palette.linearRgbColor(0, x, 0); });
+ add('Blue',
+ function(x) { return palette.rgbColor(0, 0, x); });
+ add('Blue (linear)',
+ function(x) { return palette.linearRgbColor(0, 0, x); });
+ add('Yellow',
+ function(x) { return palette.rgbColor(x, x, 0); });
+ add('Yellow (linear)',
+ function(x) { return palette.linearRgbColor(x, x, 0); });
+ add('Magenta',
+ function(x) { return palette.rgbColor(x, 0, x); });
+ add('Magenta (linear)',
+ function(x) { return palette.linearRgbColor(x, 0, x); });
+ add('Cyan',
+ function(x) { return palette.rgbColor(0, x, x); });
+ add('Cyan (linear)',
+ function(x) { return palette.linearRgbColor(0, x, x); });
+ add('Grayscale',
+ function(x) { return palette.rgbColor(x, x, x); });
+ add('Grayscale (linear)',
+ function(x) { return palette.linearRgbColor(x, x, x); });
+
+ addHeading('Solarized palettes');
+ add('Solarized base colours', 'sol-base');
+ add('Solarized accent colours', 'sol-accent');
+ };
+
+ var el = document.getElementsByTagName('form')[0];
+ el.addEventListener('input', regenerate, false);
+ el.addEventListener('change', regenerate, false);
+ regenerate();
+})();
diff --git a/palette.js b/palette.js
new file mode 100644
index 0000000..be5069e
--- /dev/null
+++ b/palette.js
@@ -0,0 +1,1260 @@
+/** @license
+ *
+ * Colour Palette Generator script.
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may
+ * obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ * Furthermore, ColorBrewer colour schemes are covered by the following:
+ *
+ * Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and
+ * The Pennsylvania State University.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions as source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. The end-user documentation included with the redistribution, if any,
+ * must include the following acknowledgment: "This product includes color
+ * specifications and designs developed by Cynthia Brewer
+ * (http://colorbrewer.org/)." Alternately, this acknowledgment may appear
+ * in the software itself, if and wherever such third-party
+ * acknowledgments normally appear.
+ *
+ * 4. The name "ColorBrewer" must not be used to endorse or promote
+ * products derived from this software without prior written
+ * permission. For written permission, please contact Cynthia Brewer at
+ * cbrewer@psu.edu.
+ *
+ * 5. Products derived from this software may not be called "ColorBrewer",
+ * nor may "ColorBrewer" appear in their name, without prior written
+ * permission of Cynthia Brewer.
+ *
+ * Furthermore, Solarized colour schemes are covered by the following:
+ *
+ * Copyright (c) 2011 Ethan Schoonover
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+'use strict';
+
+var palette = (function() {
+ var ret = (function(proto) {
+ return {
+ slice: function(arr, opt_begin, opt_end) {
+ return proto.slice.apply(arr, proto.slice.call(arguments, 1));
+ },
+ extend: function(arr, arr2) {
+ proto.push.apply(arr, arr2);
+ }
+ };
+ })(Array.prototype);
+ var slice = ret.slice;
+ var extend = ret.extend;
+ var function_type = typeof function(){};
+
+ var INF = 1000000000; // As far as we're concerned, that's infinity. ;)
+
+
+ /**
+ * Generate a colour palette from given scheme.
+ *
+ * If scheme argument is not a function it is passed to palettes.listSchemes
+ * function (along with the number argument). This may result in an array
+ * of more than one available scheme. If that is the case, scheme at
+ * opt_index position is taken.
+ *
+ * This allows using different palettes for different data without having to
+ * name the schemes specifically, for example:
+ *
+ * palette_for_foo = palette('sequential', 10, 0);
+ * palette_for_bar = palette('sequential', 10, 1);
+ * palette_for_baz = palette('sequential', 10, 2);
+ *
+ * @param {!function(number, ...*)|string|!Array.} scheme
+ * Scheme to generate palette for. Either a function constructed with
+ * palette.Scheme object, or anything that palette.listSchemes accepts
+ * as name argument.
+ * @param {number} number Number of colours to return. If negative,
+ * absolute value is taken and colours will be returned in reverse
+ * order.
+ * @param {number=} opt_index If scheme is a name of a group or an array and
+ * results in more than one scheme, index of the scheme to use. The
+ * index wraps around.
+ * @return {Array.} Array of abs(number) 'RRGGBB' strings or null if
+ * no matching scheme was found.
+ * @return {...*} varargs Additional arguments to pass to palette or colour
+ * generator (if the chosen scheme uses those).
+ */
+ var palette = function(scheme, number, opt_index, varargs) {
+ number |= 0;
+ if (number == 0) {
+ return [];
+ }
+
+ if (typeof scheme !== function_type) {
+ scheme = palette.listSchemes(scheme, number);
+ if (!scheme.length) {
+ return null;
+ }
+ scheme = scheme[(opt_index || 0) % scheme.length];
+ }
+
+ var args = slice(arguments, 2);
+ args[0] = number;
+ return scheme.apply(scheme, args);
+ };
+
+
+ /**
+ * Returns a callable colour scheme object.
+ *
+ * Just after being created, the scheme has no colour palettes and no way of
+ * generating any, thus generate method will return null. To turn scheme
+ * into a useful object, addPalette, addPalettes or setColorFunction methods
+ * need to be used.
+ *
+ * To generate a colour palette with given number colours using function
+ * returned by this method, just call it with desired number of colours.
+ *
+ * Since this function *returns* a callable object, it must *not* be used
+ * with the new operator.
+ *
+ * @param {string} name Name of the scheme.
+ * @param {string|!Array.=} opt_groups A group name or list of
+ * groups the scheme should be categorised under. Three typical groups
+ * to use are 'qualitative', 'sequential' and 'diverging', but any
+ * groups may be created.
+ * @return {function(number, ...*): Array.} A colour palette
+ * generator function, which in addition has methods and properties like
+ * a regular object. Think of it as a callable object.
+ */
+ palette.Scheme = function(name, opt_groups) {
+ /**
+ * A map from a number to a colour palettes with given number of colours.
+ * @type {!Object.>}
+ */
+ var palettes = {};
+
+ /**
+ * The biggest palette in palettes map.
+ * @type {number}
+ */
+ var palettes_max = 0;
+
+ /**
+ * The smallest palette in palettes map.
+ * @type {number}
+ */
+ var palettes_min = INF;
+
+ var makeGenerator = function() {
+ if (arguments.length <= 1) {
+ return self.color_func.bind(self);
+ } else {
+ var args = slice(arguments);
+ return function(x) {
+ args[0] = x;
+ return self.color_func.apply(self, args);
+ };
+ }
+ };
+
+ /**
+ * Generate a colour palette from the scheme.
+ *
+ * If there was a palette added with addPalette (or addPalettes) with
+ * enough colours, that palette will be used. Otherwise, if colour
+ * function has been set using setColorFunction method, that function will
+ * be used to generate the palette. Otherwise null is returned.
+ *
+ * @param {number} number Number of colours to return. If negative,
+ * absolute value is taken and colours will be returned in reverse
+ * order.
+ * @return {...*} varargs Additional arguments to pass to palette or colour
+ * generator (if the chosen scheme uses those).
+ */
+ var self = function(number, varargs) {
+ number |= 0;
+ if (!number) {
+ return [];
+ }
+
+ var _number = number;
+ number = Math.abs(number);
+
+ if (number <= palettes_max) {
+ for (var i = Math.max(number, palettes_min);
+ !(i in palettes);
+ ++i) { /* nop */ }
+ var colors = palettes[i];
+ if (i > number) {
+ return palette.generate(function(x) { return colors[Math.round(x)]; },
+ _number, 0, colors.length - 1);
+ }
+ if (_number < 0) {
+ colors.reverse();
+ }
+ return colors;
+
+ } else if (self.color_func) {
+ return palette.generate(makeGenerator.apply(self, arguments),
+ _number, 0, 1, self.color_func_cyclick);
+
+ } else {
+ return null;
+ }
+ };
+
+ /**
+ * The name of the palette.
+ * @type {string}
+ */
+ self.scheme_name = name;
+
+ /**
+ * A list of groups the palette belongs to.
+ * @type {!Array.}
+ */
+ self.groups = opt_groups ?
+ typeof opt_groups === 'string' ? [opt_groups] : opt_groups : [];
+
+ /**
+ * The biggest palette this scheme can generate.
+ * @type {number}
+ */
+ self.max = 0;
+
+ /**
+ * The biggest palette this scheme can generate that is colour-blind
+ * friendly.
+ * @type {number}
+ */
+ self.cbf_max = INF;
+
+
+ /**
+ * Adds a colour palette to the colour scheme.
+ *
+ * @param {!Array.} An array of 'RRGGBB' strings representing the
+ * palette to add.
+ * @param {boolean=} opt_is_cbf Whether the palette is colourblind friendly.
+ */
+ self.addPalette = function(palette, opt_is_cbf) {
+ var len = palette.length;
+ if (len) {
+ palettes[len] = palette;
+ palettes_min = Math.min(palettes_min, len);
+ palettes_max = Math.max(palettes_max, len);
+ self.max = Math.max(self.max, len);
+ if (!opt_is_cbf && len != 1) {
+ self.cbf_max_ = Math.min(self.cbf_max_, len - 1);
+ }
+ }
+ };
+
+ /**
+ * Adds number of colour palettes to the colour scheme.
+ *
+ * @param {!Object.>|!Array.>|}
+ * palettes A map or an array of colour palettes to add. If map, i.e.
+ * object, is used, properties should use integer property names.
+ * @param {number=} opt_max Size of the biggest palette in palettes set.
+ * If not set, palettes must have a length property which will be used.
+ * @param {number=} opt_cbf_max Size of the biggest palette which is still
+ * colourblind friendly. 1 by default.
+ */
+ self.addPalettes = function(palettes, opt_max, opt_cbf_max) {
+ opt_cbf_max = opt_cbf_max || 1;
+ opt_max = opt_max || palettes.length;
+ for (var i = 0; i < opt_max; ++i) {
+ if (i in palettes) {
+ self.addPalette(palettes[i], i <= opt_cbf_max);
+ }
+ }
+ };
+
+ /**
+ * Sets a colour generation function of the colour scheme.
+ *
+ * The function must accept a singe number argument whose value can be
+ * from 0.0 to 1.0, and return a colour as an 'RRGGBB' string. This
+ * function will be used when generating palettes, i.e. if 11-colour
+ * palette is requested, this function will be called with arguments 0.0,
+ * 0.1, …, 1.0.
+ *
+ * If the palette generated by the function is colourblind friendly,
+ * opt_is_cbf should be set to true.
+ *
+ * In some cases, it is not desirable to reach 1.0 when generating
+ * a palette. This happens for hue-rainbows where the 0–1 range corresponds
+ * to a 0°–360° range in hues, and since hue at 0° is the same as at 360°,
+ * it's desired to stop short the end of the range when generating
+ * a palette. To accomplish this, opt_cyclick should be set to true.
+ *
+ * @param {!function(number): string} func A colour generator function.
+ * @param {boolean=} opt_is_cbf Whether palette generate with the function
+ * is colour-blind friendly.
+ * @param {boolean=} opt_cyclick Whether colour at 0.0 is the same as the
+ * one at 1.0.
+ */
+ self.setColorFunction = function(func, opt_is_cbf, opt_cyclick) {
+ self.color_func = func;
+ self.color_func_cyclick = !!opt_cyclick;
+ self.max = INF;
+ if (!opt_is_cbf && self.cbf_max_ === INF) {
+ self.cbf_max_ = 1;
+ }
+ };
+
+ self.color = function(x, varargs) {
+ if (self.color_func) {
+ return self.color_func.apply(this, arguments);
+ } else {
+ return null;
+ }
+ };
+
+ return self;
+ };
+
+
+ /**
+ * Creates a new palette.Scheme and initialises it by calling addPalettes
+ * method with the rest of the arguments.
+ *
+ * @param {string} name Name of the scheme.
+ * @param {string|!Array.=} opt_groups A group name or list of
+ * @param {!Object.>|!Array.>|}
+ * palettes A map or an array of colour palettes to add. If map, i.e.
+ * object, is used, properties should use integer property names.
+ * @param {number=} opt_max Size of the biggest palette in palettes set.
+ * If not set, palettes must have a length property which will be used.
+ * @param {number=} opt_cbf_max Size of the biggest palette which is still
+ * colourblind friendly. 1 by default.
+ * @return {function(number, ...*): Array.} A colour palette
+ * generator function, which in addition has methods and properties like
+ * a regular object. Think of it as a callable object.
+ */
+ palette.Scheme.fromPalettes = function(name, groups,
+ palettes, opt_max, opt_cbf_max) {
+ var scheme = palette.Scheme(name, groups);
+ scheme.addPalettes.apply(scheme, slice(arguments, 2));
+ return scheme;
+ };
+
+
+ /**
+ * Creates a new palette.Scheme and initialises it by calling
+ * setColorFunction method with the rest of the arguments.
+ *
+ * @param {string} name Name of the scheme.
+ * @param {string|!Array.=} opt_groups A group name or list of
+ * @param {!function(number): string} func A colour generator function.
+ * @param {boolean=} opt_is_cbf Whether palette generate with the function
+ * is colour-blind friendly.
+ * @param {boolean=} opt_cyclick Whether colour at 0.0 is the same as the
+ * one at 1.0.
+ * @return {function(number, ...*): Array.} A colour palette
+ * generator function, which in addition has methods and properties like
+ * a regular object. Think of it as a callable object.
+ */
+ palette.Scheme.withColorFunction = function(name, groups,
+ func, opt_is_cbf, opt_cyclick) {
+ var scheme = palette.Scheme(name, groups);
+ scheme.setColorFunction.apply(scheme, slice(arguments, 2));
+ return scheme;
+ };
+
+
+ /**
+ * A map of registered schemes. Maps a scheme or group name to a list of
+ * scheme objects. Property name is either 'n-' for single scheme
+ * names or 'g-' for scheme group names.
+ *
+ * @type {!Object.>}
+ */
+ var registered_schemes = {};
+
+
+ /**
+ * Registers a new colour scheme.
+ *
+ * @param {!palette.Scheme} scheme The scheme to add.
+ */
+ palette.register = function(scheme) {
+ registered_schemes['n-' + scheme.scheme_name] = [scheme];
+ scheme.groups.forEach(function(g) {
+ (registered_schemes['g-' + g] =
+ registered_schemes['g-' + g] || []).push(scheme);
+ });
+ (registered_schemes['g-all'] =
+ registered_schemes['g-all'] || []).push(scheme);
+ };
+
+
+ /**
+ * List all schemes that match given name and number of colours.
+ *
+ * name argument can be either a string or an array of strings. In the
+ * former case, the function acts as if the argument was an array with name
+ * as a single argument (i.e. “palette.listSchemes('foo')” is exactly the same
+ * as “palette.listSchemes(['foo'])”).
+ *
+ * Each name can be either name of a palette (e.g. 'tol-sq' for Paul Tol's
+ * sequential palette), or a name of a group (e.g. 'sequential' for all
+ * sequential palettes). Name can therefore map to a single scheme or
+ * several schemes.
+ *
+ * Furthermore, name can be suffixed with '-cbf' to indicate that only
+ * schemes that are colourblind friendly should be returned. For example,
+ * 'rainbow' returns a HSV rainbow scheme, but because it is not colourblind
+ * friendly, 'rainbow-cbf' returns no schemes.
+ *
+ * Some schemes may produce colourblind friendly palettes for some number of
+ * colours. For example ColorBrewer's Dark2 scheme is colourblind friendly
+ * if no more than 3 colours are generated. If opt_number is not specified,
+ * 'qualitative-cbf' will include 'cb-Dark2' but if opt_number is given as,
+ * say, 5 it won't.
+ *
+ * Name can also be 'all' which will return all registered schemes.
+ * Naturally, 'all-cbf' will return all colourblind friendly schemes.
+ *
+ * Schemes are added to the library using palette.register. Schemes are
+ * created using palette.Scheme function. By default, the following schemes
+ * are available:
+ *
+ * Name Description
+ * -------------- -----------------------------------------------------
+ * tol Paul Tol's qualitative scheme, cbf, max 12 colours.
+ * tol-dv Paul Tol's diverging scheme, cbf.
+ * tol-seq Paul Tol's sequential scheme, cbf.
+ * tol-rainbow Paul Tol's qualitative scheme, cbf.
+ *
+ * rainbow A rainbow palette.
+ *
+ * cb-YlGn ColorBrewer sequential schemes.
+ * cb-YlGnBu
+ * cb-GnBu
+ * cb-BuGn
+ * cb-PuBuGn
+ * cb-PuBu
+ * cb-BuPu
+ * cb-RdPu
+ * cb-PuRd
+ * cb-OrRd
+ * cb-YlOrRd
+ * cb-YlOrBr
+ * cb-Purples
+ * cb-Blues
+ * cb-Greens
+ * cb-Oranges
+ * cb-Reds
+ * cb-Greys
+ *
+ * cb-PuOr ColorBrewer diverging schemes.
+ * cb-BrBG
+ * cb-PRGn
+ * cb-PiYG
+ * cb-RdBu
+ * cb-RdGy
+ * cb-RdYlBu
+ * cb-Spectral
+ * cb-RdYlGn
+ *
+ * cb-Accent ColorBrewer qualitative schemes.
+ * cb-Dark2
+ * cb-Paired
+ * cb-Pastel1
+ * cb-Pastel2
+ * cb-Set1
+ * cb-Set2
+ * cb-Set3
+ *
+ * sol-base Solarized base colours.
+ * sol-accent Solarized accent colours.
+ *
+ * The following groups are also available by default:
+ *
+ * Name Description
+ * -------------- -----------------------------------------------------
+ * all All registered schemes.
+ * sequential All sequential schemes.
+ * diverging All diverging schemes.
+ * qualitative All qualitative schemes.
+ * cb-sequential All ColorBrewer sequential schemes.
+ * cb-diverging All ColorBrewer diverging schemes.
+ * cb-qualitative All ColorBrewer qualitative schemes.
+ *
+ * You can read more about Paul Tol's palettes at http://www.sron.nl/~pault/.
+ * You can read more about ColorBrewer at http://colorbrewer2.org.
+ *
+ * @param {string|!Array.} name A name of a colour scheme, of
+ * a group of colour schemes, or an array of any of those.
+ * @param {number=} opt_number When requesting only colourblind friendly
+ * schemes, number of colours the scheme must provide generating such
+ * that the palette is still colourblind friendly. 2 by default.
+ * @return {!Array.} An array of colour scheme objects matching the
+ * criteria. Sorted by scheme name.
+ */
+ palette.listSchemes = function(name, opt_number) {
+ if (!opt_number) {
+ opt_number = 2;
+ } else if (opt_number < 0) {
+ opt_number = -opt_number;
+ }
+
+ var ret = [];
+ (typeof name === 'string' ? [name] : name).forEach(function(n) {
+ var cbf = n.substring(n.length - 4) === '-cbf';
+ if (cbf) {
+ n = n.substring(0, n.length - 4);
+ }
+ var schemes =
+ registered_schemes['g-' + n] ||
+ registered_schemes['n-' + n] ||
+ [];
+ for (var i = 0, scheme; (scheme = schemes[i]); ++i) {
+ if ((cbf ? scheme.cbf : scheme.max) >= opt_number) {
+ ret.push(scheme);
+ }
+ }
+ });
+
+ ret.sort(function(a, b) {
+ return a.scheme_name >= b.scheme_name ?
+ a.scheme_name > b.scheme_name ? 1 : 0 : -1;
+ });
+ return ret;
+ };
+
+
+ /**
+ * Generates a palette using given colour generating function.
+ *
+ * The color_func callback must accept a singe number argument whose value
+ * can vary from 0.0 to 1.0 (or in general from opt_start to opt_end), and
+ * return a colour as an 'RRGGBB' string. This function will be used when
+ * generating palettes, i.e. if 11-colour palette is requested, this
+ * function will be called with arguments 0.0, 0.1, …, 1.0.
+ *
+ * In some cases, it is not desirable to reach 1.0 when generating
+ * a palette. This happens for hue-rainbows where the 0–1 range corresponds
+ * to a 0°–360° range in hues, and since hue at 0° is the same as at 360°,
+ * it's desired to stop short the end of the range when generating
+ * a palette. To accomplish this, opt_cyclick should be set to true.
+ *
+ * opt_start and opt_end may be used to change the range the colour
+ * generation function is called with. opt_end may be less than opt_start
+ * which will case to traverse the range in reverse. Another way to reverse
+ * the palette is requesting negative number of colours. The two methods do
+ * not always lead to the same results (especially if opt_cyclick is set).
+ *
+ * @param {function(number): string} color_func A colours generating
+ * callback function.
+ * @param {number} number Number of colours to generate in the palette. If
+ * number is negative, colours in the palette will be reversed. If only
+ * one colour is requested, colour at opt_start will be returned.
+ * @param {number=} opt_start Optional starting point for the palette
+ * generation function. Zero by default.
+ * @param {number=} opt_end Optional ending point for the palette generation
+ * function. One by default.
+ * @param {boolean=} opt_cyclick If true, function will assume colour at
+ * point opt_start is the same as one at opt_end.
+ * @return {!Array.} An array of 'RRGGBB' colours.
+ */
+ palette.generate = function(color_func, number, opt_start, opt_end,
+ opt_cyclick) {
+ if (Math.abs(number) < 1) {
+ return [];
+ }
+
+ opt_start = opt_start === void(0) ? 0 : opt_start;
+ opt_end = opt_end === void(0) ? 1 : opt_end;
+
+ if (Math.abs(number) < 2) {
+ return [color_func(opt_start)];
+ }
+
+ var i = Math.abs(number);
+ var x = opt_start;
+ var ret = [];
+ var step = (opt_end - opt_start) / (opt_cyclick ? i : (i - 1));
+
+ for (; --i >= 0; x += step) {
+ ret.push(color_func(x));
+ }
+ if (number < 0) {
+ ret.reverse();
+ }
+ return ret;
+ };
+
+
+ /**
+ * Clamps value to [0, 1] range.
+ * @param {number} v Number to limit value of.
+ * @return {number} If v is inside of [0, 1] range returns v, otherwise
+ * returns 0 or 1 depending which side of the range v is closer to.
+ */
+ var clamp = function(v) {
+ return v > 0 ? (v < 1 ? v : 1) : 0;
+ };
+
+ /**
+ * Converts r, g, b triple into RRGGBB hex representation.
+ * @param {number} r Red value of the colour in the range [0, 1].
+ * @param {number} g Green value of the colour in the range [0, 1].
+ * @param {number} b Blue value of the colour in the range [0, 1].
+ * @return {string} A lower-case RRGGBB representation of the colour.
+ */
+ palette.rgbColor = function(r, g, b) {
+ return [r, g, b].map(function(v) {
+ v = Number(Math.round(clamp(v) * 255)).toString(16);
+ return v.length == 1 ? '0' + v : v;
+ }).join('');
+ };
+
+ /**
+ * Converts a linear r, g, b triple into RRGGBB hex representation.
+ * @param {number} r Linear red value of the colour in the range [0, 1].
+ * @param {number} g Linear green value of the colour in the range [0, 1].
+ * @param {number} b Linear blue value of the colour in the range [0, 1].
+ * @return {string} A lower-case RRGGBB representation of the colour.
+ */
+ palette.linearRgbColor = function(r, g, b) {
+ // http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html
+ return [r, g, b].map(function(v) {
+ v = clamp(v);
+ if (v <= 0.0031308) {
+ v = 12.92 * v;
+ } else {
+ v = 1.055 * Math.pow(v, 1 / 2.4) - 0.055;
+ }
+ v = Number(Math.round(v * 255)).toString(16);
+ return v.length == 1 ? '0' + v : v;
+ }).join('');
+ };
+
+ /**
+ * Converts an HSV colours to RRGGBB hex representation.
+ * @param {number} h Hue in the range [0, 1].
+ * @param {number=} opt_s Saturation in the range [0, 1]. One by default.
+ * @param {number=} opt_v Value in the range [0, 1]. One by default.
+ * @return {string} An RRGGBB representation of the colour.
+ */
+ palette.hsvColor = function(h, opt_s, opt_v) {
+ h *= 6;
+ var s = opt_s === void(0) ? 1 : clamp(opt_s);
+ var v = opt_v === void(0) ? 1 : clamp(opt_v);
+ var x = v * (1 - s * Math.abs(h % 2 - 1));
+ var m = v * (1 - s);
+ switch (Math.floor(h) % 6) {
+ case 0: return palette.rgbColor(v, x, m);
+ case 1: return palette.rgbColor(x, v, m);
+ case 2: return palette.rgbColor(m, v, x);
+ case 3: return palette.rgbColor(m, x, v);
+ case 4: return palette.rgbColor(x, m, v);
+ case 5: return palette.rgbColor(v, m, x);
+ }
+ };
+
+ palette.register(palette.Scheme.withColorFunction(
+ 'rainbow', 'qualitative', palette.hsvColor, 0, true));
+
+ return palette;
+})();
+
+
+/* Paul Tol's schemes start here. *******************************************/
+/* See http://www.sron.nl/~pault/ */
+
+(function() {
+ var rgb = palette.rgbColor;
+
+ /**
+ * Calculates value of a polynomial at given point.
+ * For example, poly(x, 1, 2, 3) calculates value of “1 + 2*x + 2*X^2”.
+ * @param {number} x Value to calculate polynomial for.
+ * @param {...number} varargs Coefficients of the polynomial specified in
+ * the order of rising powers of x including constant as the first
+ * variable argument.
+ */
+ var poly = function(x, varargs) {
+ var i = arguments.length - 1, n = arguments[i];
+ while (i > 1) {
+ n = n * x + arguments[--i];
+ }
+ return n;
+ };
+
+ /**
+ * Calculate approximate value of error function with maximum error of 0.0005.
+ * See .
+ * @param {number} x Argument of the error function.
+ * @return {number} Value of error function for x.
+ */
+ var erf = function(x) {
+ // https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions
+ // This produces a maximum error of 0.0005 which is more then we need. In
+ // the worst case, that error is multiplied by four and then divided by
+ // two before being multiplied by 255, so in the end, the error is
+ // multiplied by 510 which produces 0.255 which is less than a single
+ // colour step.
+ var y = poly(Math.abs(x), 1, 0.278393, 0.230389, 0.000972, 0.078108);
+ y *= y; // y^2
+ y *= y; // y^4
+ y = 1 - 1/y;
+ return x < 0 ? -y : y;
+ };
+
+ palette.register(palette.Scheme.fromPalettes('tol', 'qualitative', [
+ ['4477aa'],
+ ['4477aa', 'cc6677'],
+ ['4477aa', 'ddcc77', 'cc6677'],
+ ['4477aa', '117733', 'ddcc77', 'cc6677'],
+ ['332288', '88ccee', '117733', 'ddcc77', 'cc6677'],
+ ['332288', '88ccee', '117733', 'ddcc77', 'cc6677', 'aa4499'],
+ ['332288', '88ccee', '44aa99', '117733', 'ddcc77', 'cc6677', 'aa4499'],
+ ['332288', '88ccee', '44aa99', '117733', '999933', 'ddcc77', 'cc6677',
+ 'aa4499'],
+ ['332288', '88ccee', '44aa99', '117733', '999933', 'ddcc77', 'cc6677',
+ '882255', 'aa4499'],
+ ['332288', '88ccee', '44aa99', '117733', '999933', 'ddcc77', '661100',
+ 'cc6677', '882255', 'aa4499'],
+ ['332288', '6699cc', '88ccee', '44aa99', '117733', '999933', 'ddcc77',
+ '661100', 'cc6677', '882255', 'aa4499'],
+ ['332288', '6699cc', '88ccee', '44aa99', '117733', '999933', 'ddcc77',
+ '661100', 'cc6677', 'aa4466', '882255', 'aa4499']
+ ], 12, 12));
+
+ /**
+ * Calculates a colour along Paul Tol's sequential colours axis.
+ * See figure 7 and equation 1.
+ * @param {number} x Position of the colour on the axis in the [0, 1] range.
+ * @return {string} An RRGGBB representation of the colour.
+ */
+ palette.tolSequentialColor = function(x) {
+ return rgb(1 - 0.392 * (1 + erf((x - 0.869) / 0.255)),
+ 1.021 - 0.456 * (1 + erf((x - 0.527) / 0.376)),
+ 1 - 0.493 * (1 + erf((x - 0.272) / 0.309)));
+ };
+
+ palette.register(palette.Scheme.withColorFunction(
+ 'tol-sq', 'sequential', palette.tolSequentialColor, true));
+
+ /**
+ * Calculates a colour along Paul Tol's diverging colours axis.
+ * See figure 8 and equation 2.
+ * @param {number} x Position of the colour on the axis in the [0, 1] range.
+ * @return {string} An RRGGBB representation of the colour.
+ */
+ palette.tolDivergingColor = function(x) {
+ var g = poly(x, 0.572, 1.524, -1.811) / poly(x, 1, -0.291, 0.1574);
+ return rgb(poly(x, 0.235, -2.13, 26.92, -65.5, 63.5, -22.36),
+ g * g,
+ 1 / poly(x, 1.579, -4.03, 12.92, -31.4, 48.6, -23.36))
+ };
+
+ palette.register(palette.Scheme.withColorFunction(
+ 'tol-dv', 'diverging', palette.tolDivergingColor, true));
+
+ /**
+ * Calculates a colour along Paul Tol's rainbow colours axis.
+ * See figure 13 and equation 3.
+ * @param {number} x Position of the colour on the axis in the [0, 1] range.
+ * @return {string} An RRGGBB representation of the colour.
+ */
+ palette.tolRainbowColor = function(x) {
+ return rgb(poly(x, 0.472, -0.567, 4.05) / poly(x, 1, 8.72, -19.17, 14.1),
+ poly(x, 0.108932, -1.22635, 27.284, -98.577, 163.3, -131.395,
+ 40.634),
+ 1 / poly(x, 1.97, 3.54, -68.5, 243, -297,125));
+ };
+
+ palette.register(palette.Scheme.withColorFunction(
+ 'tol-rainbow', 'qualitative', palette.tolRainbowColor, true));
+})();
+
+
+/* Solarized colour schemes start here. *************************************/
+/* See http://ethanschoonover.com/solarized */
+
+(function() {
+ /*
+ * Those are not really designed to be used in graphs, but we're keeping
+ * them here in case someone cares.
+ */
+ palette.register(palette.Scheme.fromPalettes('sol-base', 'sequential', [
+ ['002b36', '073642', '586e75', '657b83', '839496', '93a1a1', 'eee8d5',
+ 'fdf6e3']
+ ], 1, 8));
+ palette.register(palette.Scheme.fromPalettes('sol-accent', 'qualitative', [
+ ['b58900', 'cb4b16', 'dc322f', 'd33682', '6c71c4', '268bd2', '2aa198',
+ '859900']
+ ]));
+})();
+
+
+/* ColorBrewer colour schemes start here. ***********************************/
+/* See http://colorbrewer2.org/ */
+
+(function() {
+ var schemes = {
+ YlGn: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['f7fcb9','addd8e','31a354'],
+ 4: ['ffffcc','c2e699','78c679','238443'],
+ 5: ['ffffcc','c2e699','78c679','31a354','006837'],
+ 6: ['ffffcc','d9f0a3','addd8e','78c679','31a354','006837'],
+ 7: ['ffffcc','d9f0a3','addd8e','78c679','41ab5d','238443','005a32'],
+ 8: ['ffffe5','f7fcb9','d9f0a3','addd8e','78c679','41ab5d','238443','005a32'],
+ 9: ['ffffe5','f7fcb9','d9f0a3','addd8e','78c679','41ab5d','238443','006837','004529']
+ },
+ YlGnBu: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['edf8b1','7fcdbb','2c7fb8'],
+ 4: ['ffffcc','a1dab4','41b6c4','225ea8'],
+ 5: ['ffffcc','a1dab4','41b6c4','2c7fb8','253494'],
+ 6: ['ffffcc','c7e9b4','7fcdbb','41b6c4','2c7fb8','253494'],
+ 7: ['ffffcc','c7e9b4','7fcdbb','41b6c4','1d91c0','225ea8','0c2c84'],
+ 8: ['ffffd9','edf8b1','c7e9b4','7fcdbb','41b6c4','1d91c0','225ea8','0c2c84'],
+ 9: ['ffffd9','edf8b1','c7e9b4','7fcdbb','41b6c4','1d91c0','225ea8','253494','081d58']
+ },
+ GnBu: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['e0f3db','a8ddb5','43a2ca'],
+ 4: ['f0f9e8','bae4bc','7bccc4','2b8cbe'],
+ 5: ['f0f9e8','bae4bc','7bccc4','43a2ca','0868ac'],
+ 6: ['f0f9e8','ccebc5','a8ddb5','7bccc4','43a2ca','0868ac'],
+ 7: ['f0f9e8','ccebc5','a8ddb5','7bccc4','4eb3d3','2b8cbe','08589e'],
+ 8: ['f7fcf0','e0f3db','ccebc5','a8ddb5','7bccc4','4eb3d3','2b8cbe','08589e'],
+ 9: ['f7fcf0','e0f3db','ccebc5','a8ddb5','7bccc4','4eb3d3','2b8cbe','0868ac','084081']
+ },
+ BuGn: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['e5f5f9','99d8c9','2ca25f'],
+ 4: ['edf8fb','b2e2e2','66c2a4','238b45'],
+ 5: ['edf8fb','b2e2e2','66c2a4','2ca25f','006d2c'],
+ 6: ['edf8fb','ccece6','99d8c9','66c2a4','2ca25f','006d2c'],
+ 7: ['edf8fb','ccece6','99d8c9','66c2a4','41ae76','238b45','005824'],
+ 8: ['f7fcfd','e5f5f9','ccece6','99d8c9','66c2a4','41ae76','238b45','005824'],
+ 9: ['f7fcfd','e5f5f9','ccece6','99d8c9','66c2a4','41ae76','238b45','006d2c','00441b']
+ },
+ PuBuGn: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['ece2f0','a6bddb','1c9099'],
+ 4: ['f6eff7','bdc9e1','67a9cf','02818a'],
+ 5: ['f6eff7','bdc9e1','67a9cf','1c9099','016c59'],
+ 6: ['f6eff7','d0d1e6','a6bddb','67a9cf','1c9099','016c59'],
+ 7: ['f6eff7','d0d1e6','a6bddb','67a9cf','3690c0','02818a','016450'],
+ 8: ['fff7fb','ece2f0','d0d1e6','a6bddb','67a9cf','3690c0','02818a','016450'],
+ 9: ['fff7fb','ece2f0','d0d1e6','a6bddb','67a9cf','3690c0','02818a','016c59','014636']
+ },
+ PuBu: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['ece7f2','a6bddb','2b8cbe'],
+ 4: ['f1eef6','bdc9e1','74a9cf','0570b0'],
+ 5: ['f1eef6','bdc9e1','74a9cf','2b8cbe','045a8d'],
+ 6: ['f1eef6','d0d1e6','a6bddb','74a9cf','2b8cbe','045a8d'],
+ 7: ['f1eef6','d0d1e6','a6bddb','74a9cf','3690c0','0570b0','034e7b'],
+ 8: ['fff7fb','ece7f2','d0d1e6','a6bddb','74a9cf','3690c0','0570b0','034e7b'],
+ 9: ['fff7fb','ece7f2','d0d1e6','a6bddb','74a9cf','3690c0','0570b0','045a8d','023858']
+ },
+ BuPu: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['e0ecf4','9ebcda','8856a7'],
+ 4: ['edf8fb','b3cde3','8c96c6','88419d'],
+ 5: ['edf8fb','b3cde3','8c96c6','8856a7','810f7c'],
+ 6: ['edf8fb','bfd3e6','9ebcda','8c96c6','8856a7','810f7c'],
+ 7: ['edf8fb','bfd3e6','9ebcda','8c96c6','8c6bb1','88419d','6e016b'],
+ 8: ['f7fcfd','e0ecf4','bfd3e6','9ebcda','8c96c6','8c6bb1','88419d','6e016b'],
+ 9: ['f7fcfd','e0ecf4','bfd3e6','9ebcda','8c96c6','8c6bb1','88419d','810f7c','4d004b']
+ },
+ RdPu: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['fde0dd','fa9fb5','c51b8a'],
+ 4: ['feebe2','fbb4b9','f768a1','ae017e'],
+ 5: ['feebe2','fbb4b9','f768a1','c51b8a','7a0177'],
+ 6: ['feebe2','fcc5c0','fa9fb5','f768a1','c51b8a','7a0177'],
+ 7: ['feebe2','fcc5c0','fa9fb5','f768a1','dd3497','ae017e','7a0177'],
+ 8: ['fff7f3','fde0dd','fcc5c0','fa9fb5','f768a1','dd3497','ae017e','7a0177'],
+ 9: ['fff7f3','fde0dd','fcc5c0','fa9fb5','f768a1','dd3497','ae017e','7a0177','49006a']
+ },
+ PuRd: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['e7e1ef','c994c7','dd1c77'],
+ 4: ['f1eef6','d7b5d8','df65b0','ce1256'],
+ 5: ['f1eef6','d7b5d8','df65b0','dd1c77','980043'],
+ 6: ['f1eef6','d4b9da','c994c7','df65b0','dd1c77','980043'],
+ 7: ['f1eef6','d4b9da','c994c7','df65b0','e7298a','ce1256','91003f'],
+ 8: ['f7f4f9','e7e1ef','d4b9da','c994c7','df65b0','e7298a','ce1256','91003f'],
+ 9: ['f7f4f9','e7e1ef','d4b9da','c994c7','df65b0','e7298a','ce1256','980043','67001f']
+ },
+ OrRd: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['fee8c8','fdbb84','e34a33'],
+ 4: ['fef0d9','fdcc8a','fc8d59','d7301f'],
+ 5: ['fef0d9','fdcc8a','fc8d59','e34a33','b30000'],
+ 6: ['fef0d9','fdd49e','fdbb84','fc8d59','e34a33','b30000'],
+ 7: ['fef0d9','fdd49e','fdbb84','fc8d59','ef6548','d7301f','990000'],
+ 8: ['fff7ec','fee8c8','fdd49e','fdbb84','fc8d59','ef6548','d7301f','990000'],
+ 9: ['fff7ec','fee8c8','fdd49e','fdbb84','fc8d59','ef6548','d7301f','b30000','7f0000']
+ },
+ YlOrRd: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['ffeda0','feb24c','f03b20'],
+ 4: ['ffffb2','fecc5c','fd8d3c','e31a1c'],
+ 5: ['ffffb2','fecc5c','fd8d3c','f03b20','bd0026'],
+ 6: ['ffffb2','fed976','feb24c','fd8d3c','f03b20','bd0026'],
+ 7: ['ffffb2','fed976','feb24c','fd8d3c','fc4e2a','e31a1c','b10026'],
+ 8: ['ffffcc','ffeda0','fed976','feb24c','fd8d3c','fc4e2a','e31a1c','b10026'],
+ 9: ['ffffcc','ffeda0','fed976','feb24c','fd8d3c','fc4e2a','e31a1c','bd0026','800026']
+ },
+ YlOrBr: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['fff7bc','fec44f','d95f0e'],
+ 4: ['ffffd4','fed98e','fe9929','cc4c02'],
+ 5: ['ffffd4','fed98e','fe9929','d95f0e','993404'],
+ 6: ['ffffd4','fee391','fec44f','fe9929','d95f0e','993404'],
+ 7: ['ffffd4','fee391','fec44f','fe9929','ec7014','cc4c02','8c2d04'],
+ 8: ['ffffe5','fff7bc','fee391','fec44f','fe9929','ec7014','cc4c02','8c2d04'],
+ 9: ['ffffe5','fff7bc','fee391','fec44f','fe9929','ec7014','cc4c02','993404','662506']
+ },
+ Purples: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['efedf5','bcbddc','756bb1'],
+ 4: ['f2f0f7','cbc9e2','9e9ac8','6a51a3'],
+ 5: ['f2f0f7','cbc9e2','9e9ac8','756bb1','54278f'],
+ 6: ['f2f0f7','dadaeb','bcbddc','9e9ac8','756bb1','54278f'],
+ 7: ['f2f0f7','dadaeb','bcbddc','9e9ac8','807dba','6a51a3','4a1486'],
+ 8: ['fcfbfd','efedf5','dadaeb','bcbddc','9e9ac8','807dba','6a51a3','4a1486'],
+ 9: ['fcfbfd','efedf5','dadaeb','bcbddc','9e9ac8','807dba','6a51a3','54278f','3f007d']
+ },
+ Blues: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['deebf7','9ecae1','3182bd'],
+ 4: ['eff3ff','bdd7e7','6baed6','2171b5'],
+ 5: ['eff3ff','bdd7e7','6baed6','3182bd','08519c'],
+ 6: ['eff3ff','c6dbef','9ecae1','6baed6','3182bd','08519c'],
+ 7: ['eff3ff','c6dbef','9ecae1','6baed6','4292c6','2171b5','084594'],
+ 8: ['f7fbff','deebf7','c6dbef','9ecae1','6baed6','4292c6','2171b5','084594'],
+ 9: ['f7fbff','deebf7','c6dbef','9ecae1','6baed6','4292c6','2171b5','08519c','08306b']
+ },
+ Greens: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['e5f5e0','a1d99b','31a354'],
+ 4: ['edf8e9','bae4b3','74c476','238b45'],
+ 5: ['edf8e9','bae4b3','74c476','31a354','006d2c'],
+ 6: ['edf8e9','c7e9c0','a1d99b','74c476','31a354','006d2c'],
+ 7: ['edf8e9','c7e9c0','a1d99b','74c476','41ab5d','238b45','005a32'],
+ 8: ['f7fcf5','e5f5e0','c7e9c0','a1d99b','74c476','41ab5d','238b45','005a32'],
+ 9: ['f7fcf5','e5f5e0','c7e9c0','a1d99b','74c476','41ab5d','238b45','006d2c','00441b']
+ },
+ Oranges: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['fee6ce','fdae6b','e6550d'],
+ 4: ['feedde','fdbe85','fd8d3c','d94701'],
+ 5: ['feedde','fdbe85','fd8d3c','e6550d','a63603'],
+ 6: ['feedde','fdd0a2','fdae6b','fd8d3c','e6550d','a63603'],
+ 7: ['feedde','fdd0a2','fdae6b','fd8d3c','f16913','d94801','8c2d04'],
+ 8: ['fff5eb','fee6ce','fdd0a2','fdae6b','fd8d3c','f16913','d94801','8c2d04'],
+ 9: ['fff5eb','fee6ce','fdd0a2','fdae6b','fd8d3c','f16913','d94801','a63603','7f2704']
+ },
+ Reds: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['fee0d2','fc9272','de2d26'],
+ 4: ['fee5d9','fcae91','fb6a4a','cb181d'],
+ 5: ['fee5d9','fcae91','fb6a4a','de2d26','a50f15'],
+ 6: ['fee5d9','fcbba1','fc9272','fb6a4a','de2d26','a50f15'],
+ 7: ['fee5d9','fcbba1','fc9272','fb6a4a','ef3b2c','cb181d','99000d'],
+ 8: ['fff5f0','fee0d2','fcbba1','fc9272','fb6a4a','ef3b2c','cb181d','99000d'],
+ 9: ['fff5f0','fee0d2','fcbba1','fc9272','fb6a4a','ef3b2c','cb181d','a50f15','67000d']
+ },
+ Greys: {
+ type: 'sequential',
+ cbf: 42,
+ 3: ['f0f0f0','bdbdbd','636363'],
+ 4: ['f7f7f7','cccccc','969696','525252'],
+ 5: ['f7f7f7','cccccc','969696','636363','252525'],
+ 6: ['f7f7f7','d9d9d9','bdbdbd','969696','636363','252525'],
+ 7: ['f7f7f7','d9d9d9','bdbdbd','969696','737373','525252','252525'],
+ 8: ['ffffff','f0f0f0','d9d9d9','bdbdbd','969696','737373','525252','252525'],
+ 9: ['ffffff','f0f0f0','d9d9d9','bdbdbd','969696','737373','525252','252525','000000']
+ },
+ PuOr: {
+ type: 'diverging',
+ cbf: 42,
+ 3: ['f1a340','f7f7f7','998ec3'],
+ 4: ['e66101','fdb863','b2abd2','5e3c99'],
+ 5: ['e66101','fdb863','f7f7f7','b2abd2','5e3c99'],
+ 6: ['b35806','f1a340','fee0b6','d8daeb','998ec3','542788'],
+ 7: ['b35806','f1a340','fee0b6','f7f7f7','d8daeb','998ec3','542788'],
+ 8: ['b35806','e08214','fdb863','fee0b6','d8daeb','b2abd2','8073ac','542788'],
+ 9: ['b35806','e08214','fdb863','fee0b6','f7f7f7','d8daeb','b2abd2','8073ac','542788'],
+ 10: ['7f3b08','b35806','e08214','fdb863','fee0b6','d8daeb','b2abd2','8073ac','542788','2d004b'],
+ 11: ['7f3b08','b35806','e08214','fdb863','fee0b6','f7f7f7','d8daeb','b2abd2','8073ac','542788','2d004b']
+ },
+ BrBG: {
+ type: 'diverging',
+ cbf: 42,
+ 3: ['d8b365','f5f5f5','5ab4ac'],
+ 4: ['a6611a','dfc27d','80cdc1','018571'],
+ 5: ['a6611a','dfc27d','f5f5f5','80cdc1','018571'],
+ 6: ['8c510a','d8b365','f6e8c3','c7eae5','5ab4ac','01665e'],
+ 7: ['8c510a','d8b365','f6e8c3','f5f5f5','c7eae5','5ab4ac','01665e'],
+ 8: ['8c510a','bf812d','dfc27d','f6e8c3','c7eae5','80cdc1','35978f','01665e'],
+ 9: ['8c510a','bf812d','dfc27d','f6e8c3','f5f5f5','c7eae5','80cdc1','35978f','01665e'],
+ 10: ['543005','8c510a','bf812d','dfc27d','f6e8c3','c7eae5','80cdc1','35978f','01665e','003c30'],
+ 11: ['543005','8c510a','bf812d','dfc27d','f6e8c3','f5f5f5','c7eae5','80cdc1','35978f','01665e','003c30']
+ },
+ PRGn: {
+ type: 'diverging',
+ cbf: 42,
+ 3: ['af8dc3','f7f7f7','7fbf7b'],
+ 4: ['7b3294','c2a5cf','a6dba0','008837'],
+ 5: ['7b3294','c2a5cf','f7f7f7','a6dba0','008837'],
+ 6: ['762a83','af8dc3','e7d4e8','d9f0d3','7fbf7b','1b7837'],
+ 7: ['762a83','af8dc3','e7d4e8','f7f7f7','d9f0d3','7fbf7b','1b7837'],
+ 8: ['762a83','9970ab','c2a5cf','e7d4e8','d9f0d3','a6dba0','5aae61','1b7837'],
+ 9: ['762a83','9970ab','c2a5cf','e7d4e8','f7f7f7','d9f0d3','a6dba0','5aae61','1b7837'],
+ 10: ['40004b','762a83','9970ab','c2a5cf','e7d4e8','d9f0d3','a6dba0','5aae61','1b7837','00441b'],
+ 11: ['40004b','762a83','9970ab','c2a5cf','e7d4e8','f7f7f7','d9f0d3','a6dba0','5aae61','1b7837','00441b']
+ },
+ PiYG: {
+ type: 'diverging',
+ cbf: 42,
+ 3: ['e9a3c9','f7f7f7','a1d76a'],
+ 4: ['d01c8b','f1b6da','b8e186','4dac26'],
+ 5: ['d01c8b','f1b6da','f7f7f7','b8e186','4dac26'],
+ 6: ['c51b7d','e9a3c9','fde0ef','e6f5d0','a1d76a','4d9221'],
+ 7: ['c51b7d','e9a3c9','fde0ef','f7f7f7','e6f5d0','a1d76a','4d9221'],
+ 8: ['c51b7d','de77ae','f1b6da','fde0ef','e6f5d0','b8e186','7fbc41','4d9221'],
+ 9: ['c51b7d','de77ae','f1b6da','fde0ef','f7f7f7','e6f5d0','b8e186','7fbc41','4d9221'],
+ 10: ['8e0152','c51b7d','de77ae','f1b6da','fde0ef','e6f5d0','b8e186','7fbc41','4d9221','276419'],
+ 11: ['8e0152','c51b7d','de77ae','f1b6da','fde0ef','f7f7f7','e6f5d0','b8e186','7fbc41','4d9221','276419']
+ },
+ RdBu: {
+ type: 'diverging',
+ cbf: 42,
+ 3: ['ef8a62','f7f7f7','67a9cf'],
+ 4: ['ca0020','f4a582','92c5de','0571b0'],
+ 5: ['ca0020','f4a582','f7f7f7','92c5de','0571b0'],
+ 6: ['b2182b','ef8a62','fddbc7','d1e5f0','67a9cf','2166ac'],
+ 7: ['b2182b','ef8a62','fddbc7','f7f7f7','d1e5f0','67a9cf','2166ac'],
+ 8: ['b2182b','d6604d','f4a582','fddbc7','d1e5f0','92c5de','4393c3','2166ac'],
+ 9: ['b2182b','d6604d','f4a582','fddbc7','f7f7f7','d1e5f0','92c5de','4393c3','2166ac'],
+ 10: ['67001f','b2182b','d6604d','f4a582','fddbc7','d1e5f0','92c5de','4393c3','2166ac','053061'],
+ 11: ['67001f','b2182b','d6604d','f4a582','fddbc7','f7f7f7','d1e5f0','92c5de','4393c3','2166ac','053061']
+ },
+ RdGy: {
+ type: 'diverging',
+ cbf: 42,
+ 3: ['ef8a62','ffffff','999999'],
+ 4: ['ca0020','f4a582','bababa','404040'],
+ 5: ['ca0020','f4a582','ffffff','bababa','404040'],
+ 6: ['b2182b','ef8a62','fddbc7','e0e0e0','999999','4d4d4d'],
+ 7: ['b2182b','ef8a62','fddbc7','ffffff','e0e0e0','999999','4d4d4d'],
+ 8: ['b2182b','d6604d','f4a582','fddbc7','e0e0e0','bababa','878787','4d4d4d'],
+ 9: ['b2182b','d6604d','f4a582','fddbc7','ffffff','e0e0e0','bababa','878787','4d4d4d'],
+ 10: ['67001f','b2182b','d6604d','f4a582','fddbc7','e0e0e0','bababa','878787','4d4d4d','1a1a1a'],
+ 11: ['67001f','b2182b','d6604d','f4a582','fddbc7','ffffff','e0e0e0','bababa','878787','4d4d4d','1a1a1a']
+ },
+ RdYlBu: {
+ type: 'diverging',
+ cbf: 42,
+ 3: ['fc8d59','ffffbf','91bfdb'],
+ 4: ['d7191c','fdae61','abd9e9','2c7bb6'],
+ 5: ['d7191c','fdae61','ffffbf','abd9e9','2c7bb6'],
+ 6: ['d73027','fc8d59','fee090','e0f3f8','91bfdb','4575b4'],
+ 7: ['d73027','fc8d59','fee090','ffffbf','e0f3f8','91bfdb','4575b4'],
+ 8: ['d73027','f46d43','fdae61','fee090','e0f3f8','abd9e9','74add1','4575b4'],
+ 9: ['d73027','f46d43','fdae61','fee090','ffffbf','e0f3f8','abd9e9','74add1','4575b4'],
+ 10: ['a50026','d73027','f46d43','fdae61','fee090','e0f3f8','abd9e9','74add1','4575b4','313695'],
+ 11: ['a50026','d73027','f46d43','fdae61','fee090','ffffbf','e0f3f8','abd9e9','74add1','4575b4','313695']
+ },
+ Spectral: {
+ type: 'diverging',
+ cbf: 0,
+ 3: ['fc8d59','ffffbf','99d594'],
+ 4: ['d7191c','fdae61','abdda4','2b83ba'],
+ 5: ['d7191c','fdae61','ffffbf','abdda4','2b83ba'],
+ 6: ['d53e4f','fc8d59','fee08b','e6f598','99d594','3288bd'],
+ 7: ['d53e4f','fc8d59','fee08b','ffffbf','e6f598','99d594','3288bd'],
+ 8: ['d53e4f','f46d43','fdae61','fee08b','e6f598','abdda4','66c2a5','3288bd'],
+ 9: ['d53e4f','f46d43','fdae61','fee08b','ffffbf','e6f598','abdda4','66c2a5','3288bd'],
+ 10: ['9e0142','d53e4f','f46d43','fdae61','fee08b','e6f598','abdda4','66c2a5','3288bd','5e4fa2'],
+ 11: ['9e0142','d53e4f','f46d43','fdae61','fee08b','ffffbf','e6f598','abdda4','66c2a5','3288bd','5e4fa2']
+ },
+ RdYlGn: {
+ type: 'diverging',
+ cbf: 0,
+ 3: ['fc8d59','ffffbf','91cf60'],
+ 4: ['d7191c','fdae61','a6d96a','1a9641'],
+ 5: ['d7191c','fdae61','ffffbf','a6d96a','1a9641'],
+ 6: ['d73027','fc8d59','fee08b','d9ef8b','91cf60','1a9850'],
+ 7: ['d73027','fc8d59','fee08b','ffffbf','d9ef8b','91cf60','1a9850'],
+ 8: ['d73027','f46d43','fdae61','fee08b','d9ef8b','a6d96a','66bd63','1a9850'],
+ 9: ['d73027','f46d43','fdae61','fee08b','ffffbf','d9ef8b','a6d96a','66bd63','1a9850'],
+ 10: ['a50026','d73027','f46d43','fdae61','fee08b','d9ef8b','a6d96a','66bd63','1a9850','006837'],
+ 11: ['a50026','d73027','f46d43','fdae61','fee08b','ffffbf','d9ef8b','a6d96a','66bd63','1a9850','006837']
+ },
+ Accent: {
+ type: 'qualitative',
+ cbf: 0,
+ 3: ['7fc97f','beaed4','fdc086'],
+ 4: ['7fc97f','beaed4','fdc086','ffff99'],
+ 5: ['7fc97f','beaed4','fdc086','ffff99','386cb0'],
+ 6: ['7fc97f','beaed4','fdc086','ffff99','386cb0','f0027f'],
+ 7: ['7fc97f','beaed4','fdc086','ffff99','386cb0','f0027f','bf5b17'],
+ 8: ['7fc97f','beaed4','fdc086','ffff99','386cb0','f0027f','bf5b17','666666']
+ },
+ Dark2: {
+ type: 'qualitative',
+ cbf: 3,
+ 3: ['1b9e77','d95f02','7570b3'],
+ 4: ['1b9e77','d95f02','7570b3','e7298a'],
+ 5: ['1b9e77','d95f02','7570b3','e7298a','66a61e'],
+ 6: ['1b9e77','d95f02','7570b3','e7298a','66a61e','e6ab02'],
+ 7: ['1b9e77','d95f02','7570b3','e7298a','66a61e','e6ab02','a6761d'],
+ 8: ['1b9e77','d95f02','7570b3','e7298a','66a61e','e6ab02','a6761d','666666']
+ },
+ Paired: {
+ type: 'qualitative',
+ cbf: 4,
+ 3: ['a6cee3','1f78b4','b2df8a'],
+ 4: ['a6cee3','1f78b4','b2df8a','33a02c'],
+ 5: ['a6cee3','1f78b4','b2df8a','33a02c','fb9a99'],
+ 6: ['a6cee3','1f78b4','b2df8a','33a02c','fb9a99','e31a1c'],
+ 7: ['a6cee3','1f78b4','b2df8a','33a02c','fb9a99','e31a1c','fdbf6f'],
+ 8: ['a6cee3','1f78b4','b2df8a','33a02c','fb9a99','e31a1c','fdbf6f','ff7f00'],
+ 9: ['a6cee3','1f78b4','b2df8a','33a02c','fb9a99','e31a1c','fdbf6f','ff7f00','cab2d6'],
+ 10: ['a6cee3','1f78b4','b2df8a','33a02c','fb9a99','e31a1c','fdbf6f','ff7f00','cab2d6','6a3d9a'],
+ 11: ['a6cee3','1f78b4','b2df8a','33a02c','fb9a99','e31a1c','fdbf6f','ff7f00','cab2d6','6a3d9a','ffff99'],
+ 12: ['a6cee3','1f78b4','b2df8a','33a02c','fb9a99','e31a1c','fdbf6f','ff7f00','cab2d6','6a3d9a','ffff99','b15928']
+ },
+ Pastel1: {
+ type: 'qualitative',
+ cbf: 0,
+ 3: ['fbb4ae','b3cde3','ccebc5'],
+ 4: ['fbb4ae','b3cde3','ccebc5','decbe4'],
+ 5: ['fbb4ae','b3cde3','ccebc5','decbe4','fed9a6'],
+ 6: ['fbb4ae','b3cde3','ccebc5','decbe4','fed9a6','ffffcc'],
+ 7: ['fbb4ae','b3cde3','ccebc5','decbe4','fed9a6','ffffcc','e5d8bd'],
+ 8: ['fbb4ae','b3cde3','ccebc5','decbe4','fed9a6','ffffcc','e5d8bd','fddaec'],
+ 9: ['fbb4ae','b3cde3','ccebc5','decbe4','fed9a6','ffffcc','e5d8bd','fddaec','f2f2f2']
+ },
+ Pastel2: {
+ type: 'qualitative',
+ cbf: 0,
+ 3: ['b3e2cd','fdcdac','cbd5e8'],
+ 4: ['b3e2cd','fdcdac','cbd5e8','f4cae4'],
+ 5: ['b3e2cd','fdcdac','cbd5e8','f4cae4','e6f5c9'],
+ 6: ['b3e2cd','fdcdac','cbd5e8','f4cae4','e6f5c9','fff2ae'],
+ 7: ['b3e2cd','fdcdac','cbd5e8','f4cae4','e6f5c9','fff2ae','f1e2cc'],
+ 8: ['b3e2cd','fdcdac','cbd5e8','f4cae4','e6f5c9','fff2ae','f1e2cc','cccccc']
+ },
+ Set1: {
+ type: 'qualitative',
+ cbf: 0,
+ 3: ['e41a1c','377eb8','4daf4a'],
+ 4: ['e41a1c','377eb8','4daf4a','984ea3'],
+ 5: ['e41a1c','377eb8','4daf4a','984ea3','ff7f00'],
+ 6: ['e41a1c','377eb8','4daf4a','984ea3','ff7f00','ffff33'],
+ 7: ['e41a1c','377eb8','4daf4a','984ea3','ff7f00','ffff33','a65628'],
+ 8: ['e41a1c','377eb8','4daf4a','984ea3','ff7f00','ffff33','a65628','f781bf'],
+ 9: ['e41a1c','377eb8','4daf4a','984ea3','ff7f00','ffff33','a65628','f781bf','999999']
+ },
+ Set2: {
+ type: 'qualitative',
+ cbf: 3,
+ 3: ['66c2a5','fc8d62','8da0cb'],
+ 4: ['66c2a5','fc8d62','8da0cb','e78ac3'],
+ 5: ['66c2a5','fc8d62','8da0cb','e78ac3','a6d854'],
+ 6: ['66c2a5','fc8d62','8da0cb','e78ac3','a6d854','ffd92f'],
+ 7: ['66c2a5','fc8d62','8da0cb','e78ac3','a6d854','ffd92f','e5c494'],
+ 8: ['66c2a5','fc8d62','8da0cb','e78ac3','a6d854','ffd92f','e5c494','b3b3b3']
+ },
+ Set3: {
+ type: 'qualitative',
+ cbf: 0,
+ 3: ['8dd3c7','ffffb3','bebada'],
+ 4: ['8dd3c7','ffffb3','bebada','fb8072'],
+ 5: ['8dd3c7','ffffb3','bebada','fb8072','80b1d3'],
+ 6: ['8dd3c7','ffffb3','bebada','fb8072','80b1d3','fdb462'],
+ 7: ['8dd3c7','ffffb3','bebada','fb8072','80b1d3','fdb462','b3de69'],
+ 8: ['8dd3c7','ffffb3','bebada','fb8072','80b1d3','fdb462','b3de69','fccde5'],
+ 9: ['8dd3c7','ffffb3','bebada','fb8072','80b1d3','fdb462','b3de69','fccde5','d9d9d9'],
+ 10: ['8dd3c7','ffffb3','bebada','fb8072','80b1d3','fdb462','b3de69','fccde5','d9d9d9','bc80bd'],
+ 11: ['8dd3c7','ffffb3','bebada','fb8072','80b1d3','fdb462','b3de69','fccde5','d9d9d9','bc80bd','ccebc5'],
+ 12: ['8dd3c7','ffffb3','bebada','fb8072','80b1d3','fdb462','b3de69','fccde5','d9d9d9','bc80bd','ccebc5','ffed6f']
+ }
+ };
+
+ for (var name in schemes) {
+ var scheme = schemes[name];
+ scheme = palette.Scheme.fromPalettes(
+ 'cb-' + name, [scheme.type, 'cb-' + scheme.type], scheme, 12, scheme.cbf);
+ palette.register(scheme);
+ }
+})();