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 + + +
+
+ Settings + + + +
+ +

+

+
+ +
+
+
+
+
+

“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); + } +})();