sequence-id.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Unit, StructureElement, Bond, ElementIndex } from '../../mol-model/structure';
  7. import { ColorScale, Color } from '../../mol-util/color';
  8. import { Location } from '../../mol-model/location';
  9. import { ColorTheme } from '../color';
  10. import { ParamDefinition as PD } from '../../mol-util/param-definition'
  11. import { ThemeDataContext } from '../../mol-theme/theme';
  12. import { ColorListOptionsScale, ColorListName } from '../../mol-util/color/lists';
  13. const DefaultColor = Color(0xCCCCCC)
  14. const Description = 'Gives every polymer residue a color based on its `seq_id` value.'
  15. export const SequenceIdColorThemeParams = {
  16. list: PD.ColorList<ColorListName>('turbo', ColorListOptionsScale),
  17. }
  18. export type SequenceIdColorThemeParams = typeof SequenceIdColorThemeParams
  19. export function getSequenceIdColorThemeParams(ctx: ThemeDataContext) {
  20. return SequenceIdColorThemeParams // TODO return copy
  21. }
  22. function getSeqId(unit: Unit, element: ElementIndex): number {
  23. const { model } = unit
  24. switch (unit.kind) {
  25. case Unit.Kind.Atomic:
  26. const residueIndex = model.atomicHierarchy.residueAtomSegments.index[element]
  27. return model.atomicHierarchy.residues.label_seq_id.value(residueIndex)
  28. case Unit.Kind.Spheres:
  29. return Math.round(
  30. (model.coarseHierarchy.spheres.seq_id_begin.value(element) +
  31. model.coarseHierarchy.spheres.seq_id_end.value(element)) / 2
  32. )
  33. case Unit.Kind.Gaussians:
  34. return Math.round(
  35. (model.coarseHierarchy.gaussians.seq_id_begin.value(element) +
  36. model.coarseHierarchy.gaussians.seq_id_end.value(element)) / 2
  37. )
  38. }
  39. }
  40. function getSequenceLength(unit: Unit, element: ElementIndex) {
  41. const { model } = unit
  42. let entityId = ''
  43. switch (unit.kind) {
  44. case Unit.Kind.Atomic:
  45. const chainIndex = model.atomicHierarchy.chainAtomSegments.index[element]
  46. entityId = model.atomicHierarchy.chains.label_entity_id.value(chainIndex)
  47. break
  48. case Unit.Kind.Spheres:
  49. entityId = model.coarseHierarchy.spheres.entity_id.value(element)
  50. break
  51. case Unit.Kind.Gaussians:
  52. entityId = model.coarseHierarchy.gaussians.entity_id.value(element)
  53. break
  54. }
  55. if (entityId === '') return 0
  56. const entityIndex = model.entities.getEntityIndex(entityId)
  57. if (entityIndex === -1) return 0
  58. return model.sequence.byEntityKey[entityIndex].sequence.length
  59. }
  60. export function SequenceIdColorTheme(ctx: ThemeDataContext, props: PD.Values<SequenceIdColorThemeParams>): ColorTheme<SequenceIdColorThemeParams> {
  61. const scale = ColorScale.create({
  62. listOrName: props.list,
  63. minLabel: 'Start',
  64. maxLabel: 'End',
  65. })
  66. const color = (location: Location): Color => {
  67. if (StructureElement.Location.is(location)) {
  68. const { unit, element } = location
  69. const seq_id = getSeqId(unit, element)
  70. if (seq_id > 0) {
  71. scale.setDomain(0, getSequenceLength(unit, element) - 1)
  72. return scale.color(seq_id)
  73. }
  74. } else if (Bond.isLocation(location)) {
  75. const { aUnit, aIndex } = location
  76. const seq_id = getSeqId(aUnit, aUnit.elements[aIndex])
  77. if (seq_id > 0) {
  78. scale.setDomain(0, getSequenceLength(aUnit, aUnit.elements[aIndex]) - 1)
  79. return scale.color(seq_id)
  80. }
  81. }
  82. return DefaultColor
  83. }
  84. return {
  85. factory: SequenceIdColorTheme,
  86. granularity: 'group',
  87. color,
  88. props,
  89. description: Description,
  90. legend: scale ? scale.legend : undefined
  91. }
  92. }
  93. export const SequenceIdColorThemeProvider: ColorTheme.Provider<SequenceIdColorThemeParams> = {
  94. label: 'Sequence Id',
  95. factory: SequenceIdColorTheme,
  96. getParams: getSequenceIdColorThemeParams,
  97. defaultValues: PD.getDefaultValues(SequenceIdColorThemeParams),
  98. isApplicable: (ctx: ThemeDataContext) => !!ctx.structure
  99. }