From 6cc6a76707a545f0d01f560104ae436ce1c96ba8 Mon Sep 17 00:00:00 2001
From: Alexander Rose <alex.rose@rcsb.org>
Date: Mon, 5 Nov 2018 17:04:28 -0800
Subject: [PATCH] wip, color schemes: scales

---
 src/apps/canvas/assembly-symmetry.ts          |  5 ++-
 src/apps/canvas/index.ts                      |  4 +-
 src/mol-geo/geometry/color-data.ts            | 10 ++++-
 .../direct-volume/transfer-function.ts        |  2 +-
 src/mol-geo/geometry/geometry.ts              |  3 +-
 src/mol-repr/index.ts                         |  5 ++-
 src/mol-repr/util.ts                          |  5 ++-
 src/mol-theme/color.ts                        | 44 ++++++++++++++++++-
 src/mol-theme/color/carbohydrate-symbol.ts    |  1 +
 src/mol-theme/color/chain-id.ts               |  1 +
 src/mol-theme/color/cross-link.ts             | 10 ++++-
 src/mol-theme/color/custom.ts                 |  1 +
 src/mol-theme/color/element-index.ts          |  3 +-
 src/mol-theme/color/element-symbol.ts         |  1 +
 src/mol-theme/color/molecule-type.ts          |  1 +
 src/mol-theme/color/polymer-index.ts          |  3 +-
 src/mol-theme/color/residue-name.ts           |  1 +
 src/mol-theme/color/secondary-structure.ts    |  1 +
 src/mol-theme/color/sequence-id.ts            |  4 +-
 src/mol-theme/color/shape-group.ts            |  1 +
 src/mol-theme/color/uniform.ts                |  1 +
 src/mol-theme/color/unit-index.ts             |  1 +
 src/mol-util/color/color.ts                   |  4 +-
 src/mol-util/color/index.ts                   |  5 +--
 src/mol-util/color/scale.ts                   |  8 ++--
 25 files changed, 101 insertions(+), 24 deletions(-)

diff --git a/src/apps/canvas/assembly-symmetry.ts b/src/apps/canvas/assembly-symmetry.ts
index 0fe6a7347..f4cdb2888 100644
--- a/src/apps/canvas/assembly-symmetry.ts
+++ b/src/apps/canvas/assembly-symmetry.ts
@@ -66,10 +66,10 @@ export function getClusterColorTheme(symmetryId: number, assemblySymmetry: Assem
     const DefaultColor = Color(0xCCCCCC)
     const s = assemblySymmetry.db.rcsb_assembly_symmetry
     const symmetry = Table.pickRow(s, i => s.id.value(i) === symmetryId)
-    if (!symmetry) return { granularity: 'uniform', color: () => DefaultColor }
+    if (!symmetry) return { features: {}, granularity: 'uniform', color: () => DefaultColor }
 
     const clusters = assemblySymmetry.getClusters(symmetryId)
-    if (!clusters._rowCount) return { granularity: 'uniform', color: () => DefaultColor }
+    if (!clusters._rowCount) return { features: {}, granularity: 'uniform', color: () => DefaultColor }
 
     const clusterByMember = new Map<string, number>()
     for (let i = 0, il = clusters._rowCount; i < il; ++i) {
@@ -83,6 +83,7 @@ export function getClusterColorTheme(symmetryId: number, assemblySymmetry: Assem
     const scale = ColorScale.create({ domain: [ 0, clusters._rowCount - 1 ] })
 
     return {
+        features: {},
         granularity: 'instance',
         color: (location: Location): Color => {
             if (StructureElement.isLocation(location)) {
diff --git a/src/apps/canvas/index.ts b/src/apps/canvas/index.ts
index cbc1a3a56..dd72f8aaa 100644
--- a/src/apps/canvas/index.ts
+++ b/src/apps/canvas/index.ts
@@ -25,8 +25,8 @@ if (pdbId) app.loadPdbIdOrMmcifUrl(pdbId, { assemblyId })
 
 // app.loadPdbIdOrMmcifUrl('http://localhost:8091/ngl/data/1crn.cif')
 
-app.loadPdbIdOrMmcifUrl('3pqr')
-app.loadCcp4Url('http://localhost:8091/ngl/data/3pqr-mode0.ccp4')
+// app.loadPdbIdOrMmcifUrl('3pqr')
+// app.loadCcp4Url('http://localhost:8091/ngl/data/3pqr-mode0.ccp4')
 
 // app.loadPdbIdOrMmcifUrl('1lee')
 // app.loadCcp4Url('http://localhost:8091/ngl/data/1lee.ccp4')
diff --git a/src/mol-geo/geometry/color-data.ts b/src/mol-geo/geometry/color-data.ts
index cc66f80c9..59c2a1668 100644
--- a/src/mol-geo/geometry/color-data.ts
+++ b/src/mol-geo/geometry/color-data.ts
@@ -6,11 +6,11 @@
 
 import { ValueCell } from 'mol-util';
 import { TextureImage, createTextureImage } from 'mol-gl/renderable/util';
-import { Color } from 'mol-util/color';
+import { Color, ColorMap } from 'mol-util/color';
 import { Vec2, Vec3 } from 'mol-math/linear-algebra';
 import { LocationIterator } from '../util/location-iterator';
 import { NullLocation } from 'mol-model/location';
-import { LocationColor, ColorThemeProps, ColorTheme, ColorThemeName, ScaleLegend, TableLegend } from 'mol-theme/color';
+import { LocationColor, ColorThemeProps, ColorTheme, ColorThemeName, ScaleLegend, TableLegend, ColorScaleName, getColorScaleFromName } from 'mol-theme/color';
 import { RuntimeContext } from 'mol-task';
 import { getGranularity } from './geometry';
 import { Structure } from 'mol-model/structure';
@@ -27,6 +27,8 @@ export type ColorData = {
 
 export interface ColorProps {
     colorTheme: ColorThemeName
+    colorList?: Color[] | ColorScaleName
+    colorMap?: ColorMap<any>
     colorDomain?: [number, number]
     colorValue?: Color
     colorFunction?: LocationColor,
@@ -41,6 +43,10 @@ export function getColorThemeProps(props: ColorProps): ColorThemeProps {
         name: props.colorTheme
     }
     if (props.colorDomain !== undefined) p.domain = props.colorDomain
+    if (props.colorList !== undefined) {
+        p.list = typeof props.colorList === 'string' ? getColorScaleFromName(props.colorList) : props.colorList
+    }
+    if (props.colorMap !== undefined) p.map = props.colorMap
     if (props.colorValue !== undefined) p.value = props.colorValue
     if (props.structure !== undefined) p.structure = props.structure
     if (props.colorFunction !== undefined) p.color = props.colorFunction
diff --git a/src/mol-geo/geometry/direct-volume/transfer-function.ts b/src/mol-geo/geometry/direct-volume/transfer-function.ts
index 98f496f14..1679daa27 100644
--- a/src/mol-geo/geometry/direct-volume/transfer-function.ts
+++ b/src/mol-geo/geometry/direct-volume/transfer-function.ts
@@ -29,7 +29,7 @@ export function createTransferFunctionTexture(controlPoints: ControlPoint[], tex
     ]
     const scale = ColorScale.create({
         domain: [0, 1],
-        colors: ColorMatplotlib.viridis
+        list: ColorMatplotlib.viridis
     })
 
     const n = 256
diff --git a/src/mol-geo/geometry/geometry.ts b/src/mol-geo/geometry/geometry.ts
index 42cef994a..57df5ab48 100644
--- a/src/mol-geo/geometry/geometry.ts
+++ b/src/mol-geo/geometry/geometry.ts
@@ -10,7 +10,7 @@ import { RenderableState } from 'mol-gl/renderable';
 import { ValueCell } from 'mol-util';
 import { BaseValues } from 'mol-gl/renderable/schema';
 import { Color } from 'mol-util/color';
-import { ColorThemeOptions, ColorThemeName } from 'mol-theme/color';
+import { ColorThemeOptions, ColorThemeName, ColorScaleOptions, ColorScaleName } from 'mol-theme/color';
 import { LocationIterator } from '../util/location-iterator';
 import { ColorType } from './color-data';
 import { SizeType } from './size-data';
@@ -65,6 +65,7 @@ export namespace Geometry {
         useFog: BooleanParam('Use Fog', '', false),
         quality: SelectParam<VisualQuality>('Quality', '', 'auto', VisualQualityOptions),
         colorTheme: SelectParam<ColorThemeName>('Color Theme', '', 'uniform', ColorThemeOptions),
+        colorList: SelectParam<ColorScaleName>('Color Scale', '', 'default', ColorScaleOptions),
         colorValue: ColorParam('Color Value', '', Color(0xCCCCCC)),
     }
     export const DefaultProps = paramDefaultValues(Params)
diff --git a/src/mol-repr/index.ts b/src/mol-repr/index.ts
index 7ae464d95..a293cf595 100644
--- a/src/mol-repr/index.ts
+++ b/src/mol-repr/index.ts
@@ -11,6 +11,7 @@ import { Loci, isEmptyLoci, EmptyLoci } from 'mol-model/loci';
 import { MarkerAction } from '../mol-geo/geometry/marker-data';
 import { Params, MultiSelectParam } from 'mol-util/parameter';
 import { WebGLContext } from 'mol-gl/webgl/context';
+// import { ColorTheme } from 'mol-theme/color';
 
 // export interface RepresentationProps {
 //     visuals?: string[]
@@ -106,7 +107,9 @@ export namespace Representation {
 //
 
 export interface VisualContext extends RepresentationContext {
-    runtime: RuntimeContext
+    runtime: RuntimeContext,
+    // TODO
+    // colorTheme: ColorTheme,
 }
 
 export interface Visual<D, P extends RepresentationProps> {
diff --git a/src/mol-repr/util.ts b/src/mol-repr/util.ts
index 792e9ff05..0b71cd247 100644
--- a/src/mol-repr/util.ts
+++ b/src/mol-repr/util.ts
@@ -44,7 +44,10 @@ export function sizeChanged(oldProps: SizeProps, newProps: SizeProps) {
 export function colorChanged(oldProps: ColorProps, newProps: ColorProps) {
     return (
         oldProps.colorTheme !== newProps.colorTheme ||
-        oldProps.colorValue !== newProps.colorValue
+        oldProps.colorValue !== newProps.colorValue ||
+        oldProps.colorDomain !== newProps.colorDomain ||
+        oldProps.colorList !== newProps.colorList ||
+        oldProps.colorMap !== newProps.colorMap
     )
 }
 
diff --git a/src/mol-theme/color.ts b/src/mol-theme/color.ts
index c11848731..d087e249c 100644
--- a/src/mol-theme/color.ts
+++ b/src/mol-theme/color.ts
@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Color } from 'mol-util/color';
+import { Color, ColorMap } from 'mol-util/color';
 import { Structure } from 'mol-model/structure';
 import { Location } from 'mol-model/location';
 import { ColorType } from 'mol-geo/geometry/color-data';
@@ -23,6 +23,7 @@ import { SequenceIdColorTheme } from './color/sequence-id';
 import { SecondaryStructureColorTheme } from './color/secondary-structure';
 import { MoleculeTypeColorTheme } from './color/molecule-type';
 import { PolymerIndexColorTheme } from './color/polymer-index';
+import { ColorMatplotlib, ColorBrewer, ColorOther } from 'mol-util/color/tables';
 
 export type LocationColor = (location: Location, isSecondary: boolean) => Color
 
@@ -36,6 +37,29 @@ export function ScaleLegend(minLabel: string, maxLabel: string, colors: Color[])
     return { kind: 'scale-legend', minLabel, maxLabel, colors }
 }
 
+export type ColorScaleName = (
+    'default' |
+    keyof typeof ColorBrewer | keyof typeof ColorMatplotlib | keyof typeof ColorOther
+)
+export const ColorScaleNames = [
+    'default',
+    ...Object.keys(ColorBrewer), ...Object.keys(ColorMatplotlib), ...Object.keys(ColorOther)
+]
+export const ColorScaleOptions = ColorScaleNames.map(n => [n, n] as [ColorScaleName, string])
+
+export function getColorScaleFromName(name: string) {
+    if (name === 'default') {
+        return
+    } else if (name in ColorBrewer) {
+        return ColorBrewer[name as keyof typeof ColorBrewer]
+    } else if (name in ColorMatplotlib) {
+        return ColorMatplotlib[name as keyof typeof ColorMatplotlib]
+    } else if (name in ColorOther) {
+        return ColorOther[name as keyof typeof ColorOther]
+    }
+    console.warn(`unknwon color list named '${name}'`)
+}
+
 export interface TableLegend {
     kind: 'table-legend'
     table: [ string, Color ][]
@@ -44,7 +68,23 @@ export function TableLegend(table: [ string, Color ][]): TableLegend {
     return { kind: 'table-legend', table }
 }
 
+export interface ColorThemeFeatures {
+    /** Does allow providing a structure object */
+    structure?: boolean
+    /** Does allow providing a volume object */
+    volume?: boolean
+    /** Does allow providing a list of colors (for creating a scale) */
+    list?: boolean
+    /** Does allow providing a map of colors */
+    map?: boolean
+    /** Does allow providing the boundaries for the scale */
+    domain?: boolean
+    /** Does allow providing a single/special color value */
+    value?: boolean
+}
+
 export interface ColorTheme {
+    features: ColorThemeFeatures
     granularity: ColorType
     color: LocationColor
     description?: string
@@ -74,6 +114,8 @@ export interface ColorThemeProps {
     name: ColorThemeName
     domain?: [number, number]
     value?: Color
+    list?: Color[]
+    map?: ColorMap<any>
     structure?: Structure
     color?: LocationColor
     granularity?: ColorType,
diff --git a/src/mol-theme/color/carbohydrate-symbol.ts b/src/mol-theme/color/carbohydrate-symbol.ts
index c777c91d5..a21853d87 100644
--- a/src/mol-theme/color/carbohydrate-symbol.ts
+++ b/src/mol-theme/color/carbohydrate-symbol.ts
@@ -47,6 +47,7 @@ export function CarbohydrateSymbolColorTheme(props: ColorThemeProps): ColorTheme
     }
 
     return {
+        features: {},
         granularity: 'group',
         color: color,
         description: Description,
diff --git a/src/mol-theme/color/chain-id.ts b/src/mol-theme/color/chain-id.ts
index e281dc9a2..0fd9e3955 100644
--- a/src/mol-theme/color/chain-id.ts
+++ b/src/mol-theme/color/chain-id.ts
@@ -63,6 +63,7 @@ export function ChainIdColorTheme(props: ColorThemeProps): ColorTheme {
     }
 
     return {
+        features: {},
         granularity: 'group',
         color,
         description: Description,
diff --git a/src/mol-theme/color/cross-link.ts b/src/mol-theme/color/cross-link.ts
index 6f8ab371e..bb3cf176c 100644
--- a/src/mol-theme/color/cross-link.ts
+++ b/src/mol-theme/color/cross-link.ts
@@ -6,10 +6,12 @@
 
 import { Link } from 'mol-model/structure';
 
-import { Color, ColorScale, ColorBrewer } from 'mol-util/color';
+import { Color, ColorScale } from 'mol-util/color';
 import { Location } from 'mol-model/location';
 import { ColorThemeProps, ColorTheme, LocationColor } from '../color';
 import { Vec3 } from 'mol-math/linear-algebra';
+import { ColorBrewer } from 'mol-util/color/tables';
+import { defaults } from 'mol-util';
 
 const DefaultColor = Color(0xCCCCCC)
 const Description = 'Colors cross-links by the deviation of the observed distance versus the modeled distance (e.g. `ihm_cross_link_restraint.distance_threshold`).'
@@ -27,7 +29,10 @@ export function CrossLinkColorTheme(props: ColorThemeProps): ColorTheme {
 
     if (props.structure) {
         const crosslinks = props.structure.crossLinkRestraints
-        scale = ColorScale.create({ domain: [ -10, 10 ], colors: ColorBrewer.RdYlBu })
+        scale = ColorScale.create({
+            domain: defaults(props.domain, [ -10, 10 ]),
+            list: defaults(props.list, ColorBrewer.RdYlBu)
+        })
         const scaleColor = scale.color
 
         color = (location: Location): Color => {
@@ -44,6 +49,7 @@ export function CrossLinkColorTheme(props: ColorThemeProps): ColorTheme {
     }
 
     return {
+        features: { list: true, domain: true },
         granularity: 'group',
         color,
         description: Description,
diff --git a/src/mol-theme/color/custom.ts b/src/mol-theme/color/custom.ts
index 4901ac06f..4eb5a10ea 100644
--- a/src/mol-theme/color/custom.ts
+++ b/src/mol-theme/color/custom.ts
@@ -13,6 +13,7 @@ const DefaultColor = Color(0xCCCCCC)
 export function CustomColorTheme(props: ColorThemeProps): ColorTheme {
     const value = defaults(props.value, DefaultColor)
     return {
+        features: {},
         granularity: defaults(props.granularity, 'uniform'),
         color: defaults(props.color, () => value),
         description: props.description,
diff --git a/src/mol-theme/color/element-index.ts b/src/mol-theme/color/element-index.ts
index 8ca2d273a..ecce0a1c1 100644
--- a/src/mol-theme/color/element-index.ts
+++ b/src/mol-theme/color/element-index.ts
@@ -29,7 +29,7 @@ export function ElementIndexColorTheme(props: ColorThemeProps): ColorTheme {
             elementCount += units[i].elements.length
             unitIdIndex.set(units[i].id, i)
         }
-        scale = ColorScale.create({ domain: [ 0, elementCount - 1 ] })
+        scale = ColorScale.create({ domain: [ 0, elementCount - 1 ], list: props.list })
         const scaleColor = scale.color
 
         color = (location: Location): Color => {
@@ -48,6 +48,7 @@ export function ElementIndexColorTheme(props: ColorThemeProps): ColorTheme {
     }
 
     return {
+        features: { list: true },
         granularity: 'groupInstance',
         color,
         description: Description,
diff --git a/src/mol-theme/color/element-symbol.ts b/src/mol-theme/color/element-symbol.ts
index e382f14d8..8d7f87b21 100644
--- a/src/mol-theme/color/element-symbol.ts
+++ b/src/mol-theme/color/element-symbol.ts
@@ -40,6 +40,7 @@ export function ElementSymbolColorTheme(props: ColorThemeProps): ColorTheme {
     }
 
     return {
+        features: {},
         granularity: 'group',
         color,
         description: Description,
diff --git a/src/mol-theme/color/molecule-type.ts b/src/mol-theme/color/molecule-type.ts
index f2be520fe..9bdc21d39 100644
--- a/src/mol-theme/color/molecule-type.ts
+++ b/src/mol-theme/color/molecule-type.ts
@@ -49,6 +49,7 @@ export function MoleculeTypeColorTheme(props: ColorThemeProps): ColorTheme {
     }
 
     return {
+        features: {},
         granularity: 'group',
         color,
         description: Description,
diff --git a/src/mol-theme/color/polymer-index.ts b/src/mol-theme/color/polymer-index.ts
index 891b17300..b32fa80cb 100644
--- a/src/mol-theme/color/polymer-index.ts
+++ b/src/mol-theme/color/polymer-index.ts
@@ -22,7 +22,7 @@ export function PolymerIndexColorTheme(props: ColorThemeProps): ColorTheme {
         for (let i = 0, il = units.length; i <il; ++i) {
             if (units[i].polymerElements.length > 0) ++polymerCount
         }
-        scale = ColorScale.create({ domain: [ 0, polymerCount - 1 ] })
+        scale = ColorScale.create({ list: props.list, domain: [ 0, polymerCount - 1 ] })
         const unitIdColor = new Map<number, Color>()
         for (let i = 0, j = 0, il = units.length; i <il; ++i) {
             if (units[i].polymerElements.length > 0) {
@@ -45,6 +45,7 @@ export function PolymerIndexColorTheme(props: ColorThemeProps): ColorTheme {
     }
 
     return {
+        features: { structure: true, list: true },
         granularity: 'instance',
         color,
         description: Description,
diff --git a/src/mol-theme/color/residue-name.ts b/src/mol-theme/color/residue-name.ts
index 02f2425fb..756ef8c48 100644
--- a/src/mol-theme/color/residue-name.ts
+++ b/src/mol-theme/color/residue-name.ts
@@ -105,6 +105,7 @@ export function ResidueNameColorTheme(props: ColorThemeProps): ColorTheme {
     }
 
     return {
+        features: {},
         granularity: 'group',
         color,
         description: Description,
diff --git a/src/mol-theme/color/secondary-structure.ts b/src/mol-theme/color/secondary-structure.ts
index 55e76a3da..d9a6fd7b6 100644
--- a/src/mol-theme/color/secondary-structure.ts
+++ b/src/mol-theme/color/secondary-structure.ts
@@ -72,6 +72,7 @@ export function SecondaryStructureColorTheme(props: ColorThemeProps): ColorTheme
     }
 
     return {
+        features: {},
         granularity: 'group',
         color,
         description: Description,
diff --git a/src/mol-theme/color/sequence-id.ts b/src/mol-theme/color/sequence-id.ts
index 7f68bf57e..808e4ace5 100644
--- a/src/mol-theme/color/sequence-id.ts
+++ b/src/mol-theme/color/sequence-id.ts
@@ -10,6 +10,7 @@ import { ColorScale, Color } from 'mol-util/color';
 import { Location } from 'mol-model/location';
 import { ColorThemeProps, ColorTheme } from '../color';
 import { ColorOther } from 'mol-util/color/tables';
+import { defaults } from 'mol-util';
 
 const DefaultColor = Color(0xCCCCCC)
 const Description = 'Gives every polymer residue a color based on its `seq_id` value.'
@@ -57,7 +58,7 @@ function getSequenceLength(unit: Unit, element: ElementIndex) {
 export function SequenceIdColorTheme(props: ColorThemeProps): ColorTheme {
     const p = {
         ...props,
-        colors: ColorOther.rainbow,
+        list: defaults(props.list, ColorOther.rainbow),
         minLabel: 'Start',
         maxLabel: 'End',
     }
@@ -83,6 +84,7 @@ export function SequenceIdColorTheme(props: ColorThemeProps): ColorTheme {
     }
 
     return {
+        features: { list: true },
         granularity: 'group',
         color,
         description: Description,
diff --git a/src/mol-theme/color/shape-group.ts b/src/mol-theme/color/shape-group.ts
index 6743791a3..0d74a08c7 100644
--- a/src/mol-theme/color/shape-group.ts
+++ b/src/mol-theme/color/shape-group.ts
@@ -13,6 +13,7 @@ const DefaultColor = Color(0xCCCCCC)
 
 export function ShapeGroupColorTheme(props: ColorThemeProps): ColorTheme {
     return {
+        features: {},
         granularity: 'group',
         color: (location: Location): Color => {
             if (Shape.isLocation(location)) {
diff --git a/src/mol-theme/color/uniform.ts b/src/mol-theme/color/uniform.ts
index d9ab15c4d..f7fb57769 100644
--- a/src/mol-theme/color/uniform.ts
+++ b/src/mol-theme/color/uniform.ts
@@ -14,6 +14,7 @@ export function UniformColorTheme(props: ColorThemeProps): ColorTheme {
     const color = props.value || DefaultColor
 
     return {
+        features: {},
         granularity: 'uniform',
         color: () => color,
         description: Description,
diff --git a/src/mol-theme/color/unit-index.ts b/src/mol-theme/color/unit-index.ts
index 3e4fed18b..f41b29199 100644
--- a/src/mol-theme/color/unit-index.ts
+++ b/src/mol-theme/color/unit-index.ts
@@ -37,6 +37,7 @@ export function UnitIndexColorTheme(props: ColorThemeProps): ColorTheme {
     }
 
     return {
+        features: {},
         granularity: 'instance',
         color,
         description: Description,
diff --git a/src/mol-util/color/color.ts b/src/mol-util/color/color.ts
index 1668282d9..426c639b5 100644
--- a/src/mol-util/color/color.ts
+++ b/src/mol-util/color/color.ts
@@ -65,8 +65,8 @@ export namespace Color {
     }
 }
 
-type ColorTable<T extends { [k: string]: number[] }> = { [k in keyof T]: Color[] }
+export type ColorTable<T extends { [k: string]: number[] }> = { [k in keyof T]: Color[] }
 export function ColorTable<T extends { [k: string]: number[] }>(o: T) { return o as ColorTable<T> }
 
-type ColorMap<T extends { [k: string]: number }> = { [k in keyof T]: Color }
+export type ColorMap<T extends { [k: string]: number }> = { [k in keyof T]: Color }
 export function ColorMap<T extends { [k: string]: number }>(o: T) { return o as ColorMap<T> }
\ No newline at end of file
diff --git a/src/mol-util/color/index.ts b/src/mol-util/color/index.ts
index 2332d4a24..33691a411 100644
--- a/src/mol-util/color/index.ts
+++ b/src/mol-util/color/index.ts
@@ -4,6 +4,5 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-export { Color, ColorMap, ColorTable } from './color'
-export { ColorScale } from './scale';
-export { ColorBrewer, ColorNames } from './tables'
\ No newline at end of file
+export { Color, ColorMap, ColorTable } from './color';
+export { ColorScale } from './scale';
\ No newline at end of file
diff --git a/src/mol-util/color/scale.ts b/src/mol-util/color/scale.ts
index e4bc9bb02..c7cf7980c 100644
--- a/src/mol-util/color/scale.ts
+++ b/src/mol-util/color/scale.ts
@@ -25,7 +25,7 @@ export interface ColorScale {
 export const DefaultColorScale = {
     domain: [0, 1],
     reverse: false,
-    colors: ColorBrewer.RdYlBu,
+    list: ColorBrewer.RdYlBu,
     minLabel: '' as string | undefined,
     maxLabel: '' as string | undefined,
 }
@@ -33,8 +33,10 @@ export type ColorScaleProps = Partial<typeof DefaultColorScale>
 
 export namespace ColorScale {
     export function create(props: ColorScaleProps): ColorScale {
-        const { domain, reverse, colors: _colors } = { ...DefaultColorScale, ...props }
-        const colors = reverse ? _colors.slice().reverse() : _colors
+        // ensure that no undefined .list property exists so that the default assignment works
+        if (props.list === undefined) delete props.list
+        const { domain, reverse, list } = { ...DefaultColorScale, ...props }
+        const colors = reverse ? list.slice().reverse() : list
         const count1 = colors.length - 1
 
         let diff = 0, min = 0, max = 0
-- 
GitLab