polymer-index.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /**
  2. * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Color } from '../../mol-util/color';
  7. import { Location } from '../../mol-model/location';
  8. import { StructureElement, Bond, Structure } from '../../mol-model/structure';
  9. import { ColorTheme, LocationColor } from '../color';
  10. import { ParamDefinition as PD } from '../../mol-util/param-definition'
  11. import { ThemeDataContext } from '../../mol-theme/theme';
  12. import { TableLegend, ScaleLegend } from '../../mol-util/legend';
  13. import { getPaletteParams, getPalette } from '../../mol-util/color/palette';
  14. import { ColorLists } from '../../mol-util/color/lists';
  15. const DefaultList = 'dark-2'
  16. const DefaultColor = Color(0xCCCCCC)
  17. const Description = 'Gives every polymer chain instance a unique color based on the position (index) of the polymer in the list of polymers in the structure.'
  18. export const PolymerIndexColorThemeParams = {
  19. ...getPaletteParams({ type: 'set', setList: DefaultList }),
  20. }
  21. export type PolymerIndexColorThemeParams = typeof PolymerIndexColorThemeParams
  22. export function getPolymerIndexColorThemeParams(ctx: ThemeDataContext) {
  23. const params = PD.clone(PolymerIndexColorThemeParams)
  24. if (ctx.structure) {
  25. if (getPolymerChainCount(ctx.structure.root) > ColorLists[DefaultList].list.length) {
  26. params.palette.defaultValue.name = 'scale'
  27. params.palette.defaultValue.params = {
  28. ...params.palette.defaultValue.params,
  29. list: 'red-yellow-blue'
  30. }
  31. }
  32. }
  33. return params
  34. }
  35. export type PolymerIndexColorThemeProps = PD.Values<typeof PolymerIndexColorThemeParams>
  36. function getPolymerChainCount(structure: Structure) {
  37. let polymerChainCount = 0
  38. const { units } = structure
  39. for (let i = 0, il = units.length; i <il; ++i) {
  40. if (units[i].polymerElements.length > 0) ++polymerChainCount
  41. }
  42. return polymerChainCount
  43. }
  44. export function PolymerIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<PolymerIndexColorThemeParams>): ColorTheme<PolymerIndexColorThemeParams> {
  45. let color: LocationColor
  46. let legend: ScaleLegend | TableLegend | undefined
  47. if (ctx.structure) {
  48. const palette = getPalette(getPolymerChainCount(ctx.structure.root), props)
  49. legend = palette.legend
  50. const { units } = ctx.structure.root
  51. const unitIdColor = new Map<number, Color>()
  52. for (let i = 0, j = 0, il = units.length; i <il; ++i) {
  53. if (units[i].polymerElements.length > 0) {
  54. unitIdColor.set(units[i].id, palette.color(j))
  55. ++j
  56. }
  57. }
  58. color = (location: Location): Color => {
  59. let color: Color | undefined
  60. if (StructureElement.Location.is(location)) {
  61. color = unitIdColor.get(location.unit.id)
  62. } else if (Bond.isLocation(location)) {
  63. color = unitIdColor.get(location.aUnit.id)
  64. }
  65. return color !== undefined ? color : DefaultColor
  66. }
  67. } else {
  68. color = () => DefaultColor
  69. }
  70. return {
  71. factory: PolymerIndexColorTheme,
  72. granularity: 'instance',
  73. color,
  74. props,
  75. description: Description,
  76. legend
  77. }
  78. }
  79. export const PolymerIndexColorThemeProvider: ColorTheme.Provider<PolymerIndexColorThemeParams> = {
  80. label: 'Polymer Chain Instance',
  81. category: ColorTheme.Category.Chain,
  82. factory: PolymerIndexColorTheme,
  83. getParams: getPolymerIndexColorThemeParams,
  84. defaultValues: PD.getDefaultValues(PolymerIndexColorThemeParams),
  85. isApplicable: (ctx: ThemeDataContext) => !!ctx.structure
  86. }