app/assets/javascripts/palette.js
/** @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 proto = Array.prototype;
var slice = function(arr, opt_begin, opt_end) {
return proto.slice.apply(arr, proto.slice.call(arguments, 1));
};
var extend = function(arr, arr2) {
return proto.push.apply(arr, arr2);
};
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 {!palette.SchemeType|string|palette.Palette} 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.
* @param {...*} varargs Additional arguments to pass to palette or colour
* generator (if the chosen scheme uses those).
* @return {Array<string>} Array of abs(number) 'RRGGBB' strings or null if
* no matching scheme was found.
*/
var palette = function(scheme, number, opt_index, varargs) {
number |= 0;
if (number == 0) {
return [];
}
if (typeof scheme !== function_type) {
var arr = palette.listSchemes(
/** @type {string|palette.Palette} */ (scheme), number);
if (!arr.length) {
return null;
}
scheme = arr[(opt_index || 0) % arr.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<string>=} 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 {!palette.SchemeType} 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<number, palette.Palette>}
*/
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.
* @param {...*} 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) {
var take_head =
'shrinking_takes_head' in colors ?
colors.shrinking_takes_head : self.shrinking_takes_head;
if (take_head) {
colors = colors.slice(0, number);
i = number;
} else {
return palette.generate(
function(x) { return colors[Math.round(x)]; },
_number, 0, colors.length - 1);
}
}
colors = colors.slice();
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_cyclic);
} else {
return null;
}
};
/**
* The name of the palette.
* @type {string}
*/
self.scheme_name = name;
/**
* A list of groups the palette belongs to.
* @type {!Array<string>}
*/
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 {palette.Palette} palette 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 {palette.PalettesList} 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_max = opt_max || palettes.length;
for (var i = 0; i < opt_max; ++i) {
if (i in palettes) {
self.addPalette(palettes[i], true);
}
}
self.cbf_max = Math.min(self.cbf_max, opt_cbf_max || 1);
};
/**
* Enable shrinking palettes taking head of the list of colours.
*
* When user requests n-colour palette but the smallest palette added with
* addPalette (or addPalettes) is m-colour one (where n < m), n colours
* across the palette will be returned. For example:
* var ex = palette.Scheme('ex');
* ex.addPalette(['000000', 'bcbcbc', 'ffffff']);
* var pal = ex(2);
* // pal == ['000000', 'ffffff']
*
* This works for palettes where the distance between colours is
* correlated to distance in the palette array, which is true in gradients
* such as the one above.
*
* To turn this feature off shrinkByTakingHead can be set to true either
* for all palettes in the scheme (if opt_idx is not given) or for palette
* with given number of colours only. In general, setting the option for
* given palette overwrites whatever has been set for the scheme. The
* default, as described above, is false.
*
* Alternatively, the feature can be enabled by setting shrinking_takes_head
* property for the palette Array or the scheme object.
*
* For example, all of the below give equivalent results:
* var pal = ['ff0000', '00ff00', '0000ff'];
*
* var ex = palette.Scheme('ex');
* ex.addPalette(pal); // ex(2) == ['ff0000', '0000ff']
* ex.shrinkByTakingHead(true); // ex(2) == ['ff0000', '00ff00']
*
* ex = palette.Scheme('ex');
* ex.addPalette(pal); // ex(2) == ['ff0000', '0000ff']
* ex.shrinkByTakingHead(true, 3); // ex(2) == ['ff0000', '00ff00']
*
* ex = palette.Scheme('ex');
* ex.addPalette(pal);
* ex.addPalette(pal); // ex(2) == ['ff0000', '0000ff']
* pal.shrinking_takes_head = true; // ex(2) == ['ff0000', '00ff00']
*
* @param {boolean} enabled Whether to enable or disable the “shrinking
* takes head” feature. It is disabled by default.
* @param {number=} opt_idx If given, the “shrinking takes head” option
* for palette with given number of colours is set. If such palette
* does not exist, nothing happens.
*/
self.shrinkByTakingHead = function(enabled, opt_idx) {
if (opt_idx !== void(0)) {
if (opt_idx in palettes) {
palettes[opt_idx].shrinking_takes_head = !!enabled;
}
} else {
self.shrinking_takes_head = !!enabled;
}
};
/**
* 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_cyclic should be set to true.
*
* @param {palette.ColorFunction} func A colour generator function.
* @param {boolean=} opt_is_cbf Whether palette generate with the function
* is colour-blind friendly.
* @param {boolean=} opt_cyclic Whether colour at 0.0 is the same as the
* one at 1.0.
*/
self.setColorFunction = function(func, opt_is_cbf, opt_cyclic) {
self.color_func = func;
self.color_func_cyclic = !!opt_cyclic;
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<string>} groups A group name or list of group
* names the scheme belongs to.
* @param {!Object<number, palette.Palette>|!Array<palette.Palette>}
* 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 {!palette.SchemeType} 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<string>} groups A group name or list of group
* names the scheme belongs to.
* @param {palette.ColorFunction} func A colour generator function.
* @param {boolean=} opt_is_cbf Whether palette generate with the function
* is colour-blind friendly.
* @param {boolean=} opt_cyclic Whether colour at 0.0 is the same as the
* one at 1.0.
* @return {!palette.SchemeType} 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_cyclic) {
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-<name>' for single scheme
* names or 'g-<name>' for scheme group names.
*
* @type {!Object<string, !Array<!Object>>}
*/
var registered_schemes = {};
/**
* Registers a new colour scheme.
*
* @param {!palette.SchemeType} 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-sq 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<string>} 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<!palette.SchemeType>} 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_cyclic 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_cyclic is set).
*
* @param {palette.ColorFunction} 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_cyclic If true, function will assume colour at
* point opt_start is the same as one at opt_end.
* @return {palette.Palette} An array of 'RRGGBB' colours.
*/
palette.generate = function(color_func, number, opt_start, opt_end,
opt_cyclic) {
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_cyclic ? 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);
default: return palette.rgbColor(v, m, x);
}
};
palette.register(palette.Scheme.withColorFunction(
'rainbow', 'qualitative', palette.hsvColor, false, true));
return palette;
})();
/** @typedef {function(number): string} */
palette.ColorFunction;
/** @typedef {!Array<string>} */
palette.Palette;
/** @typedef {!Object<number, palette.Palette>|!Array<palette.Palette>} */
palette.PalettesList;
/**
* @typedef {
* function(number, ...?): Array<string>|
* {
* scheme_name: string,
* groups: !Array<string>,
* max: number,
* cbf_max: number,
* addPalette: function(!Array<string>, boolean=),
* addPalettes: function(palette.PalettesList, number=, number=),
* shrinkByTakingHead: function(boolean, number=),
* setColorFunction: function(palette.ColorFunction, boolean=, boolean=),
* color: function(number, ...?): ?string}}
*/
palette.SchemeType;
/* 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 <https://en.wikipedia.org/wiki/Error_function>.
* @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 <http://www.sron.nl/~pault/colourschemes.pdf> 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 <http://www.sron.nl/~pault/colourschemes.pdf> 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 <http://www.sron.nl/~pault/colourschemes.pdf> 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);
}
})();