From c88693dfddb240eedebf1da8e4e4afae1ce97528 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Mon, 7 Oct 2019 11:18:08 -0700 Subject: [PATCH] improved color theme legend with labels from data --- src/mol-theme/color/chain-id.ts | 8 +++++++- src/mol-theme/color/entity-source.ts | 12 +++++++++++- src/mol-theme/color/polymer-id.ts | 8 +++++++- src/mol-theme/color/polymer-index.ts | 5 ++++- src/mol-theme/color/unit-index.ts | 5 ++++- src/mol-util/color/palette.ts | 27 +++++++++++++++++++++++---- 6 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/mol-theme/color/chain-id.ts b/src/mol-theme/color/chain-id.ts index e7188bedb..b35d23a27 100644 --- a/src/mol-theme/color/chain-id.ts +++ b/src/mol-theme/color/chain-id.ts @@ -26,7 +26,10 @@ export function getChainIdColorThemeParams(ctx: ThemeDataContext) { if (ctx.structure) { if (getAsymIdSerialMap(ctx.structure.root).size > 12) { params.palette.defaultValue.name = 'scale' - params.palette.defaultValue.params = { list: 'red-yellow-blue' } + params.palette.defaultValue.params = { + ...params.palette.defaultValue.params, + list: 'red-yellow-blue' + } } } return params @@ -79,6 +82,9 @@ export function ChainIdColorTheme(ctx: ThemeDataContext, props: PD.Values<ChainI const l = StructureElement.Location.create() const asymIdSerialMap = getAsymIdSerialMap(ctx.structure.root) + const labelTable = Array.from(asymIdSerialMap.keys()) + props.palette.params.valueLabel = (i: number) => labelTable[i] + const palette = getPalette(asymIdSerialMap.size, props) legend = palette.legend diff --git a/src/mol-theme/color/entity-source.ts b/src/mol-theme/color/entity-source.ts index 5a553b87c..18f696839 100644 --- a/src/mol-theme/color/entity-source.ts +++ b/src/mol-theme/color/entity-source.ts @@ -27,7 +27,10 @@ export function getEntitySourceColorThemeParams(ctx: ThemeDataContext) { if (ctx.structure) { if (getMaps(ctx.structure.root.models).srcKeySerialMap.size > 12) { params.palette.defaultValue.name = 'scale' - params.palette.defaultValue.params = { list: 'red-yellow-blue' } + params.palette.defaultValue.params = { + ...params.palette.defaultValue.params, + list: 'red-yellow-blue' + } } } return params @@ -108,6 +111,13 @@ export function EntitySourceColorTheme(ctx: ThemeDataContext, props: PD.Values<E const { models } = ctx.structure.root const { seqToSrcByModelEntity, srcKeySerialMap } = getMaps(models) + const labelTable = Array.from(srcKeySerialMap.keys()).map(v => { + const l = v.split('|')[2] + return l === '1' ? 'Unnamed' : l + }) + labelTable.push('Unknown') + props.palette.params.valueLabel = (i: number) => labelTable[i] + const palette = getPalette(srcKeySerialMap.size + 1, props) legend = palette.legend diff --git a/src/mol-theme/color/polymer-id.ts b/src/mol-theme/color/polymer-id.ts index 5df2bc599..39b74bd84 100644 --- a/src/mol-theme/color/polymer-id.ts +++ b/src/mol-theme/color/polymer-id.ts @@ -27,7 +27,10 @@ export function getPolymerIdColorThemeParams(ctx: ThemeDataContext) { if (ctx.structure) { if (getPolymerAsymIdSerialMap(ctx.structure.root).size > 12) { params.palette.defaultValue.name = 'scale' - params.palette.defaultValue.params = { list: 'red-yellow-blue' } + params.palette.defaultValue.params = { + ...params.palette.defaultValue.params, + list: 'red-yellow-blue' + } } } return params @@ -88,6 +91,9 @@ export function PolymerIdColorTheme(ctx: ThemeDataContext, props: PD.Values<Poly const l = StructureElement.Location.create() const polymerAsymIdSerialMap = getPolymerAsymIdSerialMap(ctx.structure.root) + const labelTable = Array.from(polymerAsymIdSerialMap.keys()) + props.palette.params.valueLabel = (i: number) => labelTable[i] + const palette = getPalette(polymerAsymIdSerialMap.size, props) legend = palette.legend diff --git a/src/mol-theme/color/polymer-index.ts b/src/mol-theme/color/polymer-index.ts index 223348740..cb94750b0 100644 --- a/src/mol-theme/color/polymer-index.ts +++ b/src/mol-theme/color/polymer-index.ts @@ -25,7 +25,10 @@ export function getPolymerIndexColorThemeParams(ctx: ThemeDataContext) { if (ctx.structure) { if (getPolymerChainCount(ctx.structure.root) > 12) { params.palette.defaultValue.name = 'scale' - params.palette.defaultValue.params = { list: 'red-yellow-blue' } + params.palette.defaultValue.params = { + ...params.palette.defaultValue.params, + list: 'red-yellow-blue' + } } } return params diff --git a/src/mol-theme/color/unit-index.ts b/src/mol-theme/color/unit-index.ts index c1f42c49f..491d590f2 100644 --- a/src/mol-theme/color/unit-index.ts +++ b/src/mol-theme/color/unit-index.ts @@ -25,7 +25,10 @@ export function getUnitIndexColorThemeParams(ctx: ThemeDataContext) { if (ctx.structure) { if (ctx.structure.root.units.length > 12) { params.palette.defaultValue.name = 'scale' - params.palette.defaultValue.params = { list: 'red-yellow-blue' } + params.palette.defaultValue.params = { + ...params.palette.defaultValue.params, + list: 'red-yellow-blue' + } } } return params diff --git a/src/mol-util/color/palette.ts b/src/mol-util/color/palette.ts index d05fa5aa5..263086f56 100644 --- a/src/mol-util/color/palette.ts +++ b/src/mol-util/color/palette.ts @@ -20,19 +20,28 @@ const DefaultGetPaletteProps = { } type GetPaletteProps = typeof DefaultGetPaletteProps +const LabelParams = { + valueLabel: PD.Value((i: number) => `${i + 1}`, { isHidden: true }), + minLabel: PD.Value('Start', { isHidden: true }), + maxLabel: PD.Value('End', { isHidden: true }), +} + export function getPaletteParams(props: Partial<GetPaletteProps> = {}) { const p = { ...DefaultGetPaletteProps, ...props } return { palette: PD.MappedStatic(p.type, { scale: PD.Group({ + ...LabelParams, list: PD.ColorList<ColorListName>(p.scaleList, ColorListOptionsScale), }, { isFlat: true }), set: PD.Group({ + ...LabelParams, list: PD.ColorList<ColorListName>(p.setList, ColorListOptionsSet), }, { isFlat: true }), generate: PD.Group({ + ...LabelParams, ...DistinctColorsParams, - maxCount: PD.Numeric(75, { min: 1, max: 250, step: 1 }) + maxCount: PD.Numeric(75, { min: 1, max: 250, step: 1 }), }, { isFlat: true }) }, { options: [ @@ -57,9 +66,9 @@ export function getPalette(count: number, props: PaletteProps) { let legend: ScaleLegend | TableLegend | undefined if (props.palette.name === 'scale') { - const listOrName = props.palette.params.list + const { list: listOrName, minLabel, maxLabel } = props.palette.params const domain: [number, number] = [0, count - 1] - const scale = ColorScale.create({ listOrName, domain, minLabel: 'Start', maxLabel: 'End' }) + const scale = ColorScale.create({ listOrName, domain, minLabel, maxLabel }) legend = scale.legend color = scale.color } else { @@ -71,8 +80,18 @@ export function getPalette(count: number, props: PaletteProps) { count = Math.min(count, props.palette.params.maxCount) colors = distinctColors(count, props.palette.params) } + const { valueLabel } = props.palette.params const colorsLength = colors.length - legend = TableLegend(colors.map((c, i) => [`${i + 1}`, c])) + const table: [string, Color][] = [] + for (let i = 0; i < count; ++i) { + const j = i % colorsLength + if (table[j] === undefined) { + table[j] = [valueLabel(i), colors[j]] + } else { + table[j][0] += `, ${valueLabel(i)}` + } + } + legend = TableLegend(table) color = (i: number) => colors[i % colorsLength] } -- GitLab