element-symbol.ts 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /**
  2. * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. * @author Adam Midlik <midlik@gmail.com>
  6. */
  7. import { ElementSymbol } from '../../mol-model/structure/model/types';
  8. import { Color, ColorMap } from '../../mol-util/color';
  9. import { StructureElement, Unit, Bond } from '../../mol-model/structure';
  10. import { Location } from '../../mol-model/location';
  11. import type { ColorTheme } from '../color';
  12. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  13. import { ThemeDataContext } from '../theme';
  14. import { TableLegend } from '../../mol-util/legend';
  15. import { getAdjustedColorMap } from '../../mol-util/color/color';
  16. import { getColorMapParams } from '../../mol-util/color/params';
  17. import { ChainIdColorTheme, ChainIdColorThemeParams } from './chain-id';
  18. import { OperatorNameColorThemeParams, OperatorNameColorTheme } from './operator-name';
  19. import { EntityIdColorTheme, EntityIdColorThemeParams } from './entity-id';
  20. import { assertUnreachable } from '../../mol-util/type-helpers';
  21. import { EntitySourceColorTheme, EntitySourceColorThemeParams } from './entity-source';
  22. import { ModelIndexColorTheme, ModelIndexColorThemeParams } from './model-index';
  23. import { StructureIndexColorTheme, StructureIndexColorThemeParams } from './structure-index';
  24. import { ColorThemeCategory } from './categories';
  25. import { UnitIndexColorTheme, UnitIndexColorThemeParams } from './unit-index';
  26. import { UniformColorTheme, UniformColorThemeParams } from './uniform';
  27. // from Jmol http://jmol.sourceforge.net/jscolors/ (or 0xFFFFFF)
  28. export const ElementSymbolColors = ColorMap({
  29. '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
  30. });
  31. export type ElementSymbolColors = typeof ElementSymbolColors
  32. const DefaultElementSymbolColor = Color(0xFFFFFF);
  33. const Description = 'Assigns a color to every atom according to its chemical element.';
  34. export const ElementSymbolColorThemeParams = {
  35. carbonColor: PD.MappedStatic('chain-id', {
  36. 'chain-id': PD.Group(ChainIdColorThemeParams),
  37. 'unit-index': PD.Group(UnitIndexColorThemeParams, { label: 'Chain Instance' }),
  38. 'entity-id': PD.Group(EntityIdColorThemeParams),
  39. 'entity-source': PD.Group(EntitySourceColorThemeParams),
  40. 'operator-name': PD.Group(OperatorNameColorThemeParams),
  41. 'model-index': PD.Group(ModelIndexColorThemeParams),
  42. 'structure-index': PD.Group(StructureIndexColorThemeParams),
  43. 'uniform': PD.Group(UniformColorThemeParams),
  44. 'element-symbol': PD.EmptyGroup(),
  45. }, { description: 'Use chain-id coloring for carbon atoms.' }),
  46. saturation: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }),
  47. lightness: PD.Numeric(0.2, { min: -6, max: 6, step: 0.1 }),
  48. colors: PD.MappedStatic('default', {
  49. 'default': PD.EmptyGroup(),
  50. 'custom': PD.Group(getColorMapParams(ElementSymbolColors))
  51. })
  52. };
  53. export type ElementSymbolColorThemeParams = typeof ElementSymbolColorThemeParams
  54. export function getElementSymbolColorThemeParams(ctx: ThemeDataContext) {
  55. return PD.clone(ElementSymbolColorThemeParams);
  56. }
  57. type ElementSymbolColorThemeProps = PD.Values<ElementSymbolColorThemeParams>
  58. export function elementSymbolColor(colorMap: ElementSymbolColors, element: ElementSymbol): Color {
  59. const c = colorMap[element as keyof ElementSymbolColors];
  60. return c === undefined ? DefaultElementSymbolColor : c;
  61. }
  62. function getCarbonTheme(ctx: ThemeDataContext, props: ElementSymbolColorThemeProps['carbonColor']) {
  63. switch (props.name) {
  64. case 'chain-id': return ChainIdColorTheme(ctx, props.params);
  65. case 'unit-index': return UnitIndexColorTheme(ctx, props.params);
  66. case 'entity-id': return EntityIdColorTheme(ctx, props.params);
  67. case 'entity-source': return EntitySourceColorTheme(ctx, props.params);
  68. case 'operator-name': return OperatorNameColorTheme(ctx, props.params);
  69. case 'model-index': return ModelIndexColorTheme(ctx, props.params);
  70. case 'structure-index': return StructureIndexColorTheme(ctx, props.params);
  71. case 'uniform': return UniformColorTheme(ctx, props.params);
  72. case 'element-symbol': return undefined;
  73. default: assertUnreachable(props);
  74. }
  75. }
  76. export function ElementSymbolColorTheme(ctx: ThemeDataContext, props: PD.Values<ElementSymbolColorThemeParams>): ColorTheme<ElementSymbolColorThemeParams> {
  77. const colorMap = getAdjustedColorMap(props.colors.name === 'default' ? ElementSymbolColors : props.colors.params, props.saturation, props.lightness);
  78. const carbonColor = getCarbonTheme(ctx, props.carbonColor)?.color;
  79. function elementColor(element: ElementSymbol, location: Location) {
  80. return (carbonColor && element === 'C')
  81. ? carbonColor(location, false)
  82. : elementSymbolColor(colorMap, element);
  83. }
  84. function color(location: Location): Color {
  85. if (StructureElement.Location.is(location)) {
  86. if (Unit.isAtomic(location.unit)) {
  87. const { type_symbol } = location.unit.model.atomicHierarchy.atoms;
  88. return elementColor(type_symbol.value(location.element), location);
  89. }
  90. } else if (Bond.isLocation(location)) {
  91. if (Unit.isAtomic(location.aUnit)) {
  92. const { type_symbol } = location.aUnit.model.atomicHierarchy.atoms;
  93. const element = type_symbol.value(location.aUnit.elements[location.aIndex]);
  94. return elementColor(element, location);
  95. }
  96. }
  97. return DefaultElementSymbolColor;
  98. }
  99. const granularity = (props.carbonColor.name === 'operator-name' || props.carbonColor.name === 'unit-index') ? 'groupInstance' : 'group';
  100. return {
  101. factory: ElementSymbolColorTheme,
  102. granularity,
  103. preferSmoothing: true,
  104. color,
  105. props,
  106. description: Description,
  107. legend: TableLegend(Object.keys(colorMap).map(name => {
  108. return [name, (colorMap as any)[name] as Color] as [string, Color];
  109. }))
  110. };
  111. }
  112. export const ElementSymbolColorThemeProvider: ColorTheme.Provider<ElementSymbolColorThemeParams, 'element-symbol'> = {
  113. name: 'element-symbol',
  114. label: 'Element Symbol',
  115. category: ColorThemeCategory.Atom,
  116. factory: ElementSymbolColorTheme,
  117. getParams: getElementSymbolColorThemeParams,
  118. defaultValues: PD.getDefaultValues(ElementSymbolColorThemeParams),
  119. isApplicable: (ctx: ThemeDataContext) => !!ctx.structure
  120. };