secondary-structure.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /**
  2. * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Color, ColorMap } from '../../mol-util/color';
  7. import { StructureElement, Unit, Bond, ElementIndex } from '../../mol-model/structure';
  8. import { Location } from '../../mol-model/location';
  9. import { ColorTheme } from '../color';
  10. import { SecondaryStructureType, MoleculeType } from '../../mol-model/structure/model/types';
  11. import { getElementMoleculeType } from '../../mol-model/structure/util';
  12. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  13. import { ThemeDataContext } from '../theme';
  14. import { TableLegend } from '../../mol-util/legend';
  15. import { SecondaryStructureProvider, SecondaryStructureValue } from '../../mol-model-props/computed/secondary-structure';
  16. import { getAdjustedColorMap, getColorMapParams } from '../../mol-util/color/color';
  17. import { CustomProperty } from '../../mol-model-props/common/custom-property';
  18. import { hash2 } from '../../mol-data/util';
  19. // from Jmol http://jmol.sourceforge.net/jscolors/ (shapely)
  20. const SecondaryStructureColors = ColorMap({
  21. 'alphaHelix': 0xFF0080,
  22. 'threeTenHelix': 0xA00080,
  23. 'piHelix': 0x600080,
  24. 'betaTurn': 0x6080FF,
  25. 'betaStrand': 0xFFC800,
  26. 'coil': 0xFFFFFF,
  27. 'bend': 0x66D8C9 /* biting original color used 0x00FF00 */,
  28. 'turn': 0x00B266,
  29. 'dna': 0xAE00FE,
  30. 'rna': 0xFD0162,
  31. 'carbohydrate': 0xA6A6FA
  32. });
  33. export type SecondaryStructureColors = typeof SecondaryStructureColors
  34. const DefaultSecondaryStructureColor = Color(0x808080);
  35. const Description = 'Assigns a color based on the type of secondary structure and basic molecule type.';
  36. export const SecondaryStructureColorThemeParams = {
  37. saturation: PD.Numeric(-1, { min: -6, max: 6, step: 0.1 }),
  38. lightness: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }),
  39. colors: PD.MappedStatic('default', {
  40. 'default': PD.EmptyGroup(),
  41. 'custom': PD.Group(getColorMapParams(SecondaryStructureColors))
  42. })
  43. };
  44. export type SecondaryStructureColorThemeParams = typeof SecondaryStructureColorThemeParams
  45. export function getSecondaryStructureColorThemeParams(ctx: ThemeDataContext) {
  46. return SecondaryStructureColorThemeParams; // TODO return copy
  47. }
  48. export function secondaryStructureColor(colorMap: SecondaryStructureColors, unit: Unit, element: ElementIndex, computedSecondaryStructure?: SecondaryStructureValue): Color {
  49. let secStrucType = SecondaryStructureType.create(SecondaryStructureType.Flag.None);
  50. if (computedSecondaryStructure && Unit.isAtomic(unit)) {
  51. const secondaryStructure = computedSecondaryStructure.get(unit.invariantId);
  52. if (secondaryStructure) secStrucType = secondaryStructure.type[secondaryStructure.getIndex(unit.residueIndex[element])];
  53. }
  54. if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Helix)) {
  55. if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Helix3Ten)) {
  56. return colorMap.threeTenHelix;
  57. } else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.HelixPi)) {
  58. return colorMap.piHelix;
  59. }
  60. return colorMap.alphaHelix;
  61. } else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Beta)) {
  62. return colorMap.betaStrand;
  63. } else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Bend)) {
  64. return colorMap.bend;
  65. } else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Turn)) {
  66. return colorMap.turn;
  67. } else {
  68. const moleculeType = getElementMoleculeType(unit, element);
  69. if (moleculeType === MoleculeType.DNA) {
  70. return colorMap.dna;
  71. } else if (moleculeType === MoleculeType.RNA) {
  72. return colorMap.rna;
  73. } else if (moleculeType === MoleculeType.Saccharide) {
  74. return colorMap.carbohydrate;
  75. } else if (moleculeType === MoleculeType.Protein) {
  76. return colorMap.coil;
  77. }
  78. }
  79. return DefaultSecondaryStructureColor;
  80. }
  81. export function SecondaryStructureColorTheme(ctx: ThemeDataContext, props: PD.Values<SecondaryStructureColorThemeParams>): ColorTheme<SecondaryStructureColorThemeParams> {
  82. const computedSecondaryStructure = ctx.structure && SecondaryStructureProvider.get(ctx.structure);
  83. const contextHash = computedSecondaryStructure ? hash2(computedSecondaryStructure.id, computedSecondaryStructure.version) : -1;
  84. const colorMap = getAdjustedColorMap(props.colors.name === 'default' ? SecondaryStructureColors : props.colors.params, props.saturation, props.lightness);
  85. function color(location: Location): Color {
  86. if (StructureElement.Location.is(location)) {
  87. return secondaryStructureColor(colorMap, location.unit, location.element, computedSecondaryStructure?.value);
  88. } else if (Bond.isLocation(location)) {
  89. return secondaryStructureColor(colorMap, location.aUnit, location.aUnit.elements[location.aIndex], computedSecondaryStructure?.value);
  90. }
  91. return DefaultSecondaryStructureColor;
  92. }
  93. return {
  94. factory: SecondaryStructureColorTheme,
  95. granularity: 'group',
  96. preferSmoothing: true,
  97. color,
  98. props,
  99. contextHash,
  100. description: Description,
  101. legend: TableLegend(Object.keys(colorMap).map(name => {
  102. return [name, (colorMap as any)[name] as Color] as [string, Color];
  103. }).concat([['Other', DefaultSecondaryStructureColor]]))
  104. };
  105. }
  106. export const SecondaryStructureColorThemeProvider: ColorTheme.Provider<SecondaryStructureColorThemeParams, 'secondary-structure'> = {
  107. name: 'secondary-structure',
  108. label: 'Secondary Structure',
  109. category: ColorTheme.Category.Residue,
  110. factory: SecondaryStructureColorTheme,
  111. getParams: getSecondaryStructureColorThemeParams,
  112. defaultValues: PD.getDefaultValues(SecondaryStructureColorThemeParams),
  113. isApplicable: (ctx: ThemeDataContext) => !!ctx.structure,
  114. ensureCustomProperties: {
  115. attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? SecondaryStructureProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(),
  116. detach: (data) => data.structure && SecondaryStructureProvider.ref(data.structure, false)
  117. }
  118. };