Skip to content
Snippets Groups Projects
Commit 77554146 authored by Alexander Rose's avatar Alexander Rose
Browse files

saturation and lightness color theme options

parent 633869d7
No related branches found
No related tags found
No related merge requests found
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
......@@ -12,37 +12,44 @@ import { ColorTheme } from '../color';
import { ParamDefinition as PD } from 'mol-util/param-definition'
import { ThemeDataContext } from '../theme';
import { TableLegend } from 'mol-util/color/tables';
import { getAdjustedColorMap } from 'mol-util/color/color';
// from Jmol http://jmol.sourceforge.net/jscolors/ (or 0xFFFFFF)
export const ElementSymbolColors = ColorMap({
'H': 0xFFFFFF, 'D': 0xFFFFC0, 'T': 0xFFFFA0, 'HE': 0xD9FFFF, 'LI': 0xCC80FF, 'BE': 0xC2FF00, 'B': 0xFFB5B5, 'C': 0x909090, 'N': 0x3050F8, 'O': 0xFF0D0D, 'F': 0x90E050, 'NE': 0xB3E3F5, 'NA': 0xAB5CF2, 'MG': 0x8AFF00, 'AL': 0xBFA6A6, 'SI': 0xF0C8A0, 'P': 0xFF8000, 'S': 0xFFFF30, 'CL': 0x1FF01F, 'AR': 0x80D1E3, 'K': 0x8F40D4, 'CA': 0x3DFF00, 'SC': 0xE6E6E6, 'TI': 0xBFC2C7, 'V': 0xA6A6AB, 'CR': 0x8A99C7, 'MN': 0x9C7AC7, 'FE': 0xE06633, 'CO': 0xF090A0, 'NI': 0x50D050, 'CU': 0xC88033, 'ZN': 0x7D80B0, 'GA': 0xC28F8F, 'GE': 0x668F8F, 'AS': 0xBD80E3, 'SE': 0xFFA100, 'BR': 0xA62929, 'KR': 0x5CB8D1, 'RB': 0x702EB0, 'SR': 0x00FF00, 'Y': 0x94FFFF, 'ZR': 0x94E0E0, 'NB': 0x73C2C9, 'MO': 0x54B5B5, 'TC': 0x3B9E9E, 'RU': 0x248F8F, 'RH': 0x0A7D8C, 'PD': 0x006985, 'AG': 0xC0C0C0, 'CD': 0xFFD98F, 'IN': 0xA67573, 'SN': 0x668080, 'SB': 0x9E63B5, 'TE': 0xD47A00, 'I': 0x940094, 'XE': 0x940094, 'CS': 0x57178F, 'BA': 0x00C900, 'LA': 0x70D4FF, 'CE': 0xFFFFC7, 'PR': 0xD9FFC7, 'ND': 0xC7FFC7, 'PM': 0xA3FFC7, 'SM': 0x8FFFC7, 'EU': 0x61FFC7, 'GD': 0x45FFC7, 'TB': 0x30FFC7, 'DY': 0x1FFFC7, 'HO': 0x00FF9C, 'ER': 0x00E675, 'TM': 0x00D452, 'YB': 0x00BF38, 'LU': 0x00AB24, 'HF': 0x4DC2FF, 'TA': 0x4DA6FF, 'W': 0x2194D6, 'RE': 0x267DAB, 'OS': 0x266696, 'IR': 0x175487, 'PT': 0xD0D0E0, 'AU': 0xFFD123, 'HG': 0xB8B8D0, 'TL': 0xA6544D, 'PB': 0x575961, 'BI': 0x9E4FB5, 'PO': 0xAB5C00, 'AT': 0x754F45, 'RN': 0x428296, 'FR': 0x420066, 'RA': 0x007D00, 'AC': 0x70ABFA, 'TH': 0x00BAFF, 'PA': 0x00A1FF, 'U': 0x008FFF, 'NP': 0x0080FF, 'PU': 0x006BFF, 'AM': 0x545CF2, 'CM': 0x785CE3, 'BK': 0x8A4FE3, 'CF': 0xA136D4, 'ES': 0xB31FD4, 'FM': 0xB31FBA, 'MD': 0xB30DA6, 'NO': 0xBD0D87, 'LR': 0xC70066, 'RF': 0xCC0059, 'DB': 0xD1004F, 'SG': 0xD90045, 'BH': 0xE00038, 'HS': 0xE6002E, 'MT': 0xEB0026, 'DS': 0xFFFFFF, 'RG': 0xFFFFFF, 'CN': 0xFFFFFF, 'UUT': 0xFFFFFF, 'FL': 0xFFFFFF, 'UUP': 0xFFFFFF, 'LV': 0xFFFFFF, 'UUH': 0xFFFFFF
})
export type ElementSymbolColors = typeof ElementSymbolColors
const DefaultElementSymbolColor = Color(0xFFFFFF)
const Description = 'Assigns a color to every atom according to its chemical element.'
export const ElementSymbolColorThemeParams = {}
export const ElementSymbolColorThemeParams = {
saturation: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }),
lightness: PD.Numeric(0.7, { min: -6, max: 6, step: 0.1 })
}
export type ElementSymbolColorThemeParams = typeof ElementSymbolColorThemeParams
export function getElementSymbolColorThemeParams(ctx: ThemeDataContext) {
return ElementSymbolColorThemeParams // TODO return copy
}
export function elementSymbolColor(element: ElementSymbol): Color {
const c = (ElementSymbolColors as { [k: string]: Color })[element];
export function elementSymbolColor(colorMap: ElementSymbolColors, element: ElementSymbol): Color {
const c = colorMap[element as keyof ElementSymbolColors]
return c === undefined ? DefaultElementSymbolColor : c
}
export function ElementSymbolColorTheme(ctx: ThemeDataContext, props: PD.Values<ElementSymbolColorThemeParams>): ColorTheme<ElementSymbolColorThemeParams> {
const colorMap = getAdjustedColorMap(ElementSymbolColors, props.saturation, props.lightness)
function color(location: Location): Color {
if (StructureElement.isLocation(location)) {
if (Unit.isAtomic(location.unit)) {
const { type_symbol } = location.unit.model.atomicHierarchy.atoms
return elementSymbolColor(type_symbol.value(location.element))
return elementSymbolColor(colorMap, type_symbol.value(location.element))
}
} else if (Link.isLocation(location)) {
if (Unit.isAtomic(location.aUnit)) {
const { type_symbol } = location.aUnit.model.atomicHierarchy.atoms
return elementSymbolColor(type_symbol.value(location.aUnit.elements[location.aIndex]))
return elementSymbolColor(colorMap, type_symbol.value(location.aUnit.elements[location.aIndex]))
}
}
return DefaultElementSymbolColor
......
......@@ -11,7 +11,8 @@ import { Location } from 'mol-model/location';
import { ColorTheme } from '../color';
import { ParamDefinition as PD } from 'mol-util/param-definition'
import { ThemeDataContext } from '../theme';
import { elementSymbolColor } from './element-symbol';
import { elementSymbolColor, ElementSymbolColors } from './element-symbol';
import { getAdjustedColorMap } from 'mol-util/color/color';
const DefaultIllustrativeColor = Color(0xFFFFFF)
const Description = `Assigns an illustrative color similar to David Goodsell's Molecule of the Month style.`
......@@ -22,7 +23,7 @@ export function getIllustrativeColorThemeParams(ctx: ThemeDataContext) {
return IllustrativeColorThemeParams // TODO return copy
}
function illustrativeColor(typeSymbol: ElementSymbol, moleculeType: MoleculeType) {
export function illustrativeColor(colorMap: ElementSymbolColors, typeSymbol: ElementSymbol, moleculeType: MoleculeType) {
if (isNucleic(moleculeType)) {
if (typeSymbol === 'O') {
return Color(0xFF8C8C)
......@@ -38,24 +39,26 @@ function illustrativeColor(typeSymbol: ElementSymbol, moleculeType: MoleculeType
return Color(0x6699FF)
}
} else {
return elementSymbolColor(typeSymbol)
return elementSymbolColor(colorMap, typeSymbol)
}
}
export function IllustrativeColorTheme(ctx: ThemeDataContext, props: PD.Values<IllustrativeColorThemeParams>): ColorTheme<IllustrativeColorThemeParams> {
const colorMap = getAdjustedColorMap(ElementSymbolColors, 0, 0.7)
function color(location: Location): Color {
if (StructureElement.isLocation(location)) {
if (Unit.isAtomic(location.unit)) {
const moleculeType = location.unit.model.atomicHierarchy.derived.residue.moleculeType[location.unit.residueIndex[location.element]]
const typeSymbol = location.unit.model.atomicHierarchy.atoms.type_symbol.value(location.element)
return illustrativeColor(typeSymbol, moleculeType)
return illustrativeColor(colorMap, typeSymbol, moleculeType)
}
} else if (Link.isLocation(location)) {
if (Unit.isAtomic(location.aUnit)) {
const elementIndex = location.aUnit.elements[location.aIndex]
const moleculeType = location.aUnit.model.atomicHierarchy.derived.residue.moleculeType[location.aUnit.residueIndex[elementIndex]]
const typeSymbol = location.aUnit.model.atomicHierarchy.atoms.type_symbol.value(elementIndex)
return illustrativeColor(typeSymbol, moleculeType)
return illustrativeColor(colorMap, typeSymbol, moleculeType)
}
}
return DefaultIllustrativeColor
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
......@@ -13,8 +13,9 @@ import { getElementMoleculeType } from 'mol-model/structure/util';
import { ParamDefinition as PD } from 'mol-util/param-definition'
import { ThemeDataContext } from '../theme';
import { TableLegend } from 'mol-util/color/tables';
import { getAdjustedColorMap } from 'mol-util/color/color';
const MoleculeTypeColors = ColorMap({
export const MoleculeTypeColors = ColorMap({
water: 0x386cb0,
ion: 0xf0027f,
protein: 0xbeaed4,
......@@ -23,36 +24,42 @@ const MoleculeTypeColors = ColorMap({
PNA: 0x42A49A,
saccharide: 0x7fc97f,
})
export type MoleculeTypeColors = typeof MoleculeTypeColors
const DefaultMoleculeTypeColor = Color(0xffff99)
const Description = 'Assigns a color based on the molecule type of a residue.'
export const MoleculeTypeColorThemeParams = {}
export const MoleculeTypeColorThemeParams = {
saturation: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }),
lightness: PD.Numeric(0, { min: -6, max: 6, step: 0.1 })
}
export type MoleculeTypeColorThemeParams = typeof MoleculeTypeColorThemeParams
export function getMoleculeTypeColorThemeParams(ctx: ThemeDataContext) {
return MoleculeTypeColorThemeParams // TODO return copy
}
export function moleculeTypeColor(unit: Unit, element: ElementIndex): Color {
export function moleculeTypeColor(colorMap: MoleculeTypeColors, unit: Unit, element: ElementIndex): Color {
const moleculeType = getElementMoleculeType(unit, element)
switch (moleculeType) {
case MoleculeType.water: return MoleculeTypeColors.water
case MoleculeType.ion: return MoleculeTypeColors.ion
case MoleculeType.protein: return MoleculeTypeColors.protein
case MoleculeType.RNA: return MoleculeTypeColors.RNA
case MoleculeType.DNA: return MoleculeTypeColors.DNA
case MoleculeType.PNA: return MoleculeTypeColors.PNA
case MoleculeType.saccharide: return MoleculeTypeColors.saccharide
case MoleculeType.water: return colorMap.water
case MoleculeType.ion: return colorMap.ion
case MoleculeType.protein: return colorMap.protein
case MoleculeType.RNA: return colorMap.RNA
case MoleculeType.DNA: return colorMap.DNA
case MoleculeType.PNA: return colorMap.PNA
case MoleculeType.saccharide: return colorMap.saccharide
}
return DefaultMoleculeTypeColor
}
export function MoleculeTypeColorTheme(ctx: ThemeDataContext, props: PD.Values<MoleculeTypeColorThemeParams>): ColorTheme<MoleculeTypeColorThemeParams> {
const colorMap = getAdjustedColorMap(MoleculeTypeColors, props.saturation, props.lightness)
function color(location: Location): Color {
if (StructureElement.isLocation(location)) {
return moleculeTypeColor(location.unit, location.element)
return moleculeTypeColor(colorMap, location.unit, location.element)
} else if (Link.isLocation(location)) {
return moleculeTypeColor(location.aUnit, location.aUnit.elements[location.aIndex])
return moleculeTypeColor(colorMap, location.aUnit, location.aUnit.elements[location.aIndex])
}
return DefaultMoleculeTypeColor
}
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
......@@ -11,9 +11,10 @@ import { ColorTheme } from '../color';
import { ParamDefinition as PD } from 'mol-util/param-definition'
import { ThemeDataContext } from '../theme';
import { TableLegend } from 'mol-util/color/tables';
import { getAdjustedColorMap } from 'mol-util/color/color';
// protein colors from Jmol http://jmol.sourceforge.net/jscolors/
const ResidueNameColors = ColorMap({
export const ResidueNameColors = ColorMap({
// standard amino acids
'ALA': 0x8CFF8C,
'ARG': 0x00007C,
......@@ -58,21 +59,20 @@ const ResidueNameColors = ColorMap({
'CPN': 0xFFD700,
'TPN': 0x4169E1,
})
export type ResidueNameColors = typeof ResidueNameColors
const DefaultResidueNameColor = Color(0xFF00FF)
const Description = 'Assigns a color to every residue according to its name.'
export const ResidueNameColorThemeParams = {}
export const ResidueNameColorThemeParams = {
saturation: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }),
lightness: PD.Numeric(1, { min: -6, max: 6, step: 0.1 })
}
export type ResidueNameColorThemeParams = typeof ResidueNameColorThemeParams
export function getResidueNameColorThemeParams(ctx: ThemeDataContext) {
return ResidueNameColorThemeParams // TODO return copy
}
export function residueNameColor(residueName: string): Color {
const c = (ResidueNameColors as { [k: string]: Color })[residueName];
return c === undefined ? DefaultResidueNameColor : c
}
function getAtomicCompId(unit: Unit.Atomic, element: ElementIndex) {
const { modifiedResidues } = unit.model.properties
const compId = unit.model.atomicHierarchy.residues.label_comp_id.value(unit.residueIndex[element])
......@@ -93,21 +93,30 @@ function getCoarseCompId(unit: Unit.Spheres | Unit.Gaussians, element: ElementIn
}
}
export function residueNameColor(colorMap: ResidueNameColors, residueName: string): Color {
const c = colorMap[residueName as keyof ResidueNameColors]
return c === undefined ? DefaultResidueNameColor : c
}
export function ResidueNameColorTheme(ctx: ThemeDataContext, props: PD.Values<ResidueNameColorThemeParams>): ColorTheme<ResidueNameColorThemeParams> {
const colorMap = getAdjustedColorMap(ResidueNameColors, props.saturation, props.lightness)
function color(location: Location): Color {
if (StructureElement.isLocation(location)) {
if (Unit.isAtomic(location.unit)) {
return residueNameColor(getAtomicCompId(location.unit, location.element))
const compId = getAtomicCompId(location.unit, location.element)
return residueNameColor(colorMap, compId)
} else {
const compId = getCoarseCompId(location.unit, location.element)
if (compId) return residueNameColor(compId)
if (compId) return residueNameColor(colorMap, compId)
}
} else if (Link.isLocation(location)) {
if (Unit.isAtomic(location.aUnit)) {
return residueNameColor(getAtomicCompId(location.aUnit, location.aUnit.elements[location.aIndex]))
const compId = getAtomicCompId(location.aUnit, location.aUnit.elements[location.aIndex])
return residueNameColor(colorMap, compId)
} else {
const compId = getCoarseCompId(location.aUnit, location.aUnit.elements[location.aIndex])
if (compId) return residueNameColor(compId)
if (compId) return residueNameColor(colorMap, compId)
}
}
return DefaultResidueNameColor
......
......@@ -14,6 +14,7 @@ import { ParamDefinition as PD } from 'mol-util/param-definition'
import { ThemeDataContext } from '../theme';
import { TableLegend } from 'mol-util/color/tables';
import { ComputedSecondaryStructure } from 'mol-model-props/computed/secondary-structure';
import { getAdjustedColorMap } from 'mol-util/color/color';
// from Jmol http://jmol.sourceforge.net/jscolors/ (shapely)
const SecondaryStructureColors = ColorMap({
......@@ -31,17 +32,21 @@ const SecondaryStructureColors = ColorMap({
'carbohydrate': 0xA6A6FA
})
export type SecondaryStructureColors = typeof SecondaryStructureColors
const DefaultSecondaryStructureColor = Color(0x808080)
const Description = 'Assigns a color based on the type of secondary structure and basic molecule type.'
export const SecondaryStructureColorThemeParams = {}
export const SecondaryStructureColorThemeParams = {
saturation: PD.Numeric(-1, { min: -6, max: 6, step: 0.1 }),
lightness: PD.Numeric(0, { min: -6, max: 6, step: 0.1 })
}
export type SecondaryStructureColorThemeParams = typeof SecondaryStructureColorThemeParams
export function getSecondaryStructureColorThemeParams(ctx: ThemeDataContext) {
return SecondaryStructureColorThemeParams // TODO return copy
}
export function secondaryStructureColor(unit: Unit, element: ElementIndex, computedSecondaryStructure: ComputedSecondaryStructure.Property | undefined): Color {
export function secondaryStructureColor(colorMap: SecondaryStructureColors, unit: Unit, element: ElementIndex, computedSecondaryStructure: ComputedSecondaryStructure.Property | undefined): Color {
let secStrucType = SecondaryStructureType.create(SecondaryStructureType.Flag.None)
if (Unit.isAtomic(unit)) {
secStrucType = unit.model.properties.secondaryStructure.type[unit.residueIndex[element]]
......@@ -53,43 +58,44 @@ export function secondaryStructureColor(unit: Unit, element: ElementIndex, compu
if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Helix)) {
if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Helix3Ten)) {
return SecondaryStructureColors.threeTenHelix
return colorMap.threeTenHelix
} else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.HelixPi)) {
return SecondaryStructureColors.piHelix
return colorMap.piHelix
}
return SecondaryStructureColors.alphaHelix
return colorMap.alphaHelix
} else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Beta)) {
return SecondaryStructureColors.betaStrand
return colorMap.betaStrand
} else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Bend)) {
return SecondaryStructureColors.bend
return colorMap.bend
} else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Turn)) {
return SecondaryStructureColors.turn
return colorMap.turn
} else {
const moleculeType = getElementMoleculeType(unit, element)
if (moleculeType === MoleculeType.DNA) {
return SecondaryStructureColors.dna
return colorMap.dna
} else if (moleculeType === MoleculeType.RNA) {
return SecondaryStructureColors.rna
return colorMap.rna
} else if (moleculeType === MoleculeType.saccharide) {
return SecondaryStructureColors.carbohydrate
return colorMap.carbohydrate
} else if (moleculeType === MoleculeType.protein) {
return SecondaryStructureColors.coil
return colorMap.coil
}
}
return DefaultSecondaryStructureColor
}
export function SecondaryStructureColorTheme(ctx: ThemeDataContext, props: PD.Values<SecondaryStructureColorThemeParams>): ColorTheme<SecondaryStructureColorThemeParams> {
const computedSecondaryStructure = ctx.structure && ComputedSecondaryStructure.get(ctx.structure)
// use `computedSecondaryStructure.id` as context hash, when available
const contextHash = computedSecondaryStructure && computedSecondaryStructure.id
const colorMap = getAdjustedColorMap(SecondaryStructureColors, props.saturation, props.lightness)
function color(location: Location): Color {
if (StructureElement.isLocation(location)) {
return secondaryStructureColor(location.unit, location.element, computedSecondaryStructure)
return secondaryStructureColor(colorMap, location.unit, location.element, computedSecondaryStructure)
} else if (Link.isLocation(location)) {
return secondaryStructureColor(location.aUnit, location.aUnit.elements[location.aIndex], computedSecondaryStructure)
return secondaryStructureColor(colorMap, location.aUnit, location.aUnit.elements[location.aIndex], computedSecondaryStructure)
}
return DefaultSecondaryStructureColor
}
......
......@@ -117,11 +117,21 @@ export namespace Color {
export function lighten(c: Color, amount: number): Color {
return darken(c, -amount)
}
}
}
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 unknown as ColorTable<T> }
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 unknown as ColorMap<T> }
\ No newline at end of file
export function ColorMap<T extends { [k: string]: number }>(o: T) { return o as unknown as ColorMap<T> }
export function getAdjustedColorMap<T extends { [k: string]: number }>(map: ColorMap<T>, saturation: number, lightness: number) {
const adjustedMap: { [k: string]: Color } = {}
for (const e in map) {
let c = map[e]
c = Color.saturate(c, saturation)
c = Color.darken(c, -lightness)
adjustedMap[e] = c
}
return adjustedMap as ColorMap<T>
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment