diff --git a/src/mol-util/color/color.ts b/src/mol-util/color/color.ts index 764875f9470a22faa0e0de4d2d4a8701c41301b1..1668282d9125336756abbd5b20296924472b2552 100644 --- a/src/mol-util/color/color.ts +++ b/src/mol-util/color/color.ts @@ -14,6 +14,10 @@ export namespace Color { return `rgb(${hexColor >> 16 & 255}, ${hexColor >> 8 & 255}, ${hexColor & 255})` } + export function toHexString(hexColor: Color) { + return '0x' + ('000000' + hexColor.toString(16)).slice(-6) + } + export function toRgb(hexColor: Color) { return [ hexColor >> 16 & 255, hexColor >> 8 & 255, hexColor & 255 ] } @@ -26,6 +30,10 @@ export namespace Color { return ((r << 16) | (g << 8) | b) as Color } + export function fromNormalizedRgb(r: number, g: number, b: number ): Color { + return (((r * 255) << 16) | ((g * 255) << 8) | (b * 255)) as Color + } + /** Copies hex color to rgb array */ export function toArray(hexColor: Color, array: Helpers.NumberArray, offset: number) { array[ offset ] = (hexColor >> 16 & 255) diff --git a/src/mol-util/color/scale.ts b/src/mol-util/color/scale.ts index ed486d44d46aa382cf8e5f24402b2060e43f6983..403bf485bec674d3081764df61ddbc7a049f0428 100644 --- a/src/mol-util/color/scale.ts +++ b/src/mol-util/color/scale.ts @@ -7,6 +7,7 @@ import { Color } from './color' import { ColorBrewer } from './tables' import { ScaleLegend } from 'mol-view/theme/color'; +import { defaults } from 'mol-util'; export interface ColorScale { /** Returns hex color for given value */ @@ -15,7 +16,9 @@ export interface ColorScale { colorToArray: (value: number, array: Helpers.NumberArray, offset: number) => void /** Copies normalized (0 to 1) hex color to rgb array */ normalizedColorToArray: (value: number, array: Helpers.NumberArray, offset: number) => void - /** */ + /** */ + setDomain: (min: number, max: number) => void + /** Legend */ readonly legend: ScaleLegend } @@ -23,16 +26,27 @@ export const DefaultColorScale = { domain: [0, 1], reverse: false, colors: ColorBrewer.RdYlBu, + minLabel: '' as string | undefined, + maxLabel: '' as string | undefined, } export type ColorScaleProps = Partial<typeof DefaultColorScale> export namespace ColorScale { export function create(props: ColorScaleProps): ColorScale { const { domain, reverse, colors: _colors } = { ...DefaultColorScale, ...props } - const [ min, max ] = domain const colors = reverse ? _colors.slice().reverse() : _colors const count1 = colors.length - 1 - const diff = (max - min) || 1 + + let diff = 0, min = 0, max = 0 + function setDomain(_min: number, _max: number) { + min = _min + max = _max + diff = (max - min) || 1 + } + setDomain(domain[0], domain[1]) + + const minLabel = defaults(props.minLabel, min.toString()) + const maxLabel = defaults(props.maxLabel, max.toString()) function color(value: number) { const t = Math.min(colors.length - 1, Math.max(0, ((value - min) / diff) * count1)) @@ -49,7 +63,8 @@ export namespace ColorScale { normalizedColorToArray: (value: number, array: Helpers.NumberArray, offset: number) => { Color.toArrayNormalized(color(value), array, offset) }, - get legend() { return ScaleLegend(min, max, colors) } + setDomain, + get legend() { return ScaleLegend(minLabel, maxLabel, colors) } } } } diff --git a/src/mol-util/color/tables.ts b/src/mol-util/color/tables.ts index a9012c3ea2c22a9ed28d914abdab9e75b32f728e..eff1da231b8a5e3f26ff1b21c158a1206d84b542 100644 --- a/src/mol-util/color/tables.ts +++ b/src/mol-util/color/tables.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ColorMap, ColorTable } from './color'; +import { ColorMap, ColorTable, Color } from './color'; /** * Brewer Color Lists @@ -56,6 +56,44 @@ export const ColorBrewer = ColorTable({ Pastel1: [0xfbb4ae, 0xb3cde3, 0xccebc5, 0xdecbe4, 0xfed9a6, 0xffffcc, 0xe5d8bd, 0xfddaec, 0xf2f2f2] }) +/** + * Matplotlib colormaps, including various perceptually uniform shades, see https://bids.github.io/colormap/ + */ +export const ColorMatplotlib = ColorTable({ + /** perceptually uniform shades of black-red-white */ + magma: [ + 0x420f74, 0x4a1079, 0x52127c, 0x5a157e, 0x61187f, 0x691c80, 0x711f81, 0x792281, 0x812581, 0x892881, 0x912a80, 0x992d7f, 0xa12f7e, 0xa9327c, 0xb1357a, 0xb93778, 0xc23a75, 0xca3e72, 0xd1426e, 0xd9466a, 0xe04b66, 0xe65162, 0xec585f, 0xf0605d, 0xf4685b, 0xf7715b, 0xf97b5d, 0xfb8460, 0xfc8e63, 0xfd9768, 0xfda16e, 0xfeaa74, 0xfeb37b, 0xfebc82, 0xfec689, 0xfdcf92, 0xfdd89a, 0xfde1a3, 0xfceaac, 0xfcf3b5, 0xfbfcbf + ], + /** perceptually uniform shades of black-red-yellow */ + inferno: [ + 0x480b6a, 0x500d6c, 0x58106d, 0x60136e, 0x68166e, 0x70196e, 0x781c6d, 0x801f6b, 0x88216a, 0x902468, 0x982765, 0xa02a62, 0xa72d5f, 0xaf315b, 0xb73456, 0xbe3852, 0xc53d4d, 0xcc4148, 0xd24742, 0xd94d3d, 0xde5337, 0xe45a31, 0xe8612b, 0xed6825, 0xf0701e, 0xf37918, 0xf68111, 0xf88a0b, 0xfa9306, 0xfb9d06, 0xfba60b, 0xfbb014, 0xfbb91e, 0xf9c32a, 0xf8cd37, 0xf5d745, 0xf3e056, 0xf1e968, 0xf1f27d, 0xf5f891, 0xfcfea4 + ], + /** perceptually uniform shades of blue-red-yellow */ + plasma: [ + 0x1b068c, 0x250591, 0x2f0495, 0x380499, 0x40039c, 0x49029f, 0x5101a2, 0x5901a4, 0x6100a6, 0x6800a7, 0x7000a8, 0x7801a8, 0x7f03a7, 0x8607a6, 0x8e0ca4, 0x9511a1, 0x9b179e, 0xa21c9a, 0xa82296, 0xae2791, 0xb42d8d, 0xb93388, 0xbe3883, 0xc33e7f, 0xc8447a, 0xcd4975, 0xd14f71, 0xd6556d, 0xda5a68, 0xde6064, 0xe26660, 0xe56c5b, 0xe97257, 0xec7853, 0xef7e4e, 0xf2854a, 0xf58b46, 0xf79241, 0xf9993d, 0xfaa039, 0xfca735, 0xfdaf31, 0xfdb62d, 0xfdbe29, 0xfdc626, 0xfcce25, 0xfad624, 0xf8df24, 0xf5e726, 0xf2f026, 0xeff821 + ], + /** perceptually uniform shades of blue-green-yellow */ + viridis: [ + 0x45085b, 0x470f62, 0x471669, 0x481d6f, 0x482374, 0x472a79, 0x46307d, 0x453681, 0x433c84, 0x414286, 0x3e4888, 0x3c4d8a, 0x3a538b, 0x37588c, 0x355d8c, 0x32628d, 0x30678d, 0x2e6c8e, 0x2c718e, 0x2a768e, 0x287a8e, 0x267f8e, 0x24848d, 0x23898d, 0x218d8c, 0x1f928c, 0x1e978a, 0x1e9b89, 0x1ea087, 0x20a585, 0x23a982, 0x28ae7f, 0x2eb27c, 0x35b778, 0x3dbb74, 0x45bf6f, 0x4fc369, 0x59c764, 0x64cb5d, 0x70ce56, 0x7cd24f, 0x88d547, 0x95d73f, 0xa2da37, 0xafdc2e, 0xbdde26, 0xcae01e, 0xd7e219, 0xe4e318, 0xf1e51c, 0xfde724 + ], + /** + * perceptually uniform shades of blue-green-yellow, + * should look effectively identical to colorblind and non-colorblind users + */ + cividis: [ + 0x002c67, 0x003070, 0x083370, 0x16366f, 0x1f3a6e, 0x273d6d, 0x2e416c, 0x34446c, 0x39486c, 0x3f4b6b, 0x444f6b, 0x49526b, 0x4e566c, 0x52596c, 0x575d6d, 0x5b606e, 0x60646e, 0x64676f, 0x686b71, 0x6d6e72, 0x717273, 0x757575, 0x797977, 0x7e7d78, 0x838078, 0x878478, 0x8c8878, 0x918c77, 0x968f77, 0x9b9376, 0xa09775, 0xa59b73, 0xaa9f72, 0xafa370, 0xb4a76f, 0xb9ab6d, 0xbeb06a, 0xc4b468, 0xc9b865, 0xcebc62, 0xd4c15e, 0xd9c55a, 0xdfca56, 0xe4ce51, 0xead34c, 0xefd846, 0xf5dc3f, 0xfbe136, 0xfde737 + ], + /** perceptually uniform shades of white-blue-black-red-white, cyclic */ + twilight: [ + 0xdfd9e1, 0xd8d7dd, 0xced3d8, 0xc2cdd3, 0xb4c7ce, 0xa7c0ca, 0x9ab8c7, 0x8eb0c5, 0x83a8c3, 0x7a9fc2, 0x7297c0, 0x6b8ebf, 0x6684bd, 0x637bbb, 0x6171b9, 0x5f67b6, 0x5e5cb2, 0x5e51ad, 0x5d46a7, 0x5c3c9f, 0x5b3196, 0x58278b, 0x531e7d, 0x4d176e, 0x46135f, 0x3e1151, 0x381045, 0x32113b, 0x301336, 0x361138, 0x3e113c, 0x471240, 0x521445, 0x5e1749, 0x6a1a4d, 0x761e4f, 0x812350, 0x8b2a50, 0x95324f, 0x9d3a4f, 0xa5434f, 0xac4d50, 0xb25752, 0xb86155, 0xbc6c59, 0xc0775f, 0xc48267, 0xc78d70, 0xc9987b, 0xcca389, 0xceae97, 0xd2b8a6, 0xd6c1b5, 0xdacac4, 0xddd1d1, 0xe0d6db, 0xe1d8e1 + ] +}) + +export const ColorOther = ColorTable({ + rainbow: [ 0x3361E1, 0x35A845, 0xF9FF00, 0xEC8711, 0xBF2222 ], + rwb: [ 0xBF2222, 0xFFFFFF, 0x3361E1 ], +}) + /** X11 color names http://www.w3.org/TR/css3-color/#svg-color */ export const ColorNames = ColorMap({ aliceblue: 0xf0f8ff, diff --git a/src/mol-view/theme/color.ts b/src/mol-view/theme/color.ts index f901a17e9caf7304d0c24ad0a47e72e3c7d17a2f..4f6ff16bd608337a7e4b11d37275836ce53c59e1 100644 --- a/src/mol-view/theme/color.ts +++ b/src/mol-view/theme/color.ts @@ -24,12 +24,12 @@ export type LocationColor = (location: Location, isSecondary: boolean) => Color export interface ScaleLegend { kind: 'scale-legend' - min: number, - max: number, + minLabel: string, + maxLabel: string, colors: Color[] } -export function ScaleLegend(min: number, max: number, colors: Color[]): ScaleLegend { - return { kind: 'scale-legend', min, max, colors } +export function ScaleLegend(minLabel: string, maxLabel: string, colors: Color[]): ScaleLegend { + return { kind: 'scale-legend', minLabel, maxLabel, colors } } export interface TableLegend {