sequence-id.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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. const DefaultColor = Color(0xCCCCCC);
  13. const Description = 'Gives every polymer residue a color based on its `seq_id` value.';
  14. export const SequenceIdColorThemeParams = {
  15. list: PD.ColorList('turbo', { presetKind: 'scale' }),
  16. };
  17. export type SequenceIdColorThemeParams = typeof SequenceIdColorThemeParams
  18. export function getSequenceIdColorThemeParams(ctx: ThemeDataContext) {
  19. return SequenceIdColorThemeParams; // TODO return copy
  20. }
  21. function getSeqId(unit: Unit, element: ElementIndex): number {
  22. const { model } = unit;
  23. switch (unit.kind) {
  24. case Unit.Kind.Atomic:
  25. const residueIndex = model.atomicHierarchy.residueAtomSegments.index[element];
  26. return model.atomicHierarchy.residues.label_seq_id.value(residueIndex);
  27. case Unit.Kind.Spheres:
  28. return Math.round(
  29. (model.coarseHierarchy.spheres.seq_id_begin.value(element) +
  30. model.coarseHierarchy.spheres.seq_id_end.value(element)) / 2
  31. );
  32. case Unit.Kind.Gaussians:
  33. return Math.round(
  34. (model.coarseHierarchy.gaussians.seq_id_begin.value(element) +
  35. model.coarseHierarchy.gaussians.seq_id_end.value(element)) / 2
  36. );
  37. }
  38. }
  39. function getSequenceLength(unit: Unit, element: ElementIndex) {
  40. const { model } = unit;
  41. let entityId = '';
  42. switch (unit.kind) {
  43. case Unit.Kind.Atomic:
  44. const chainIndex = model.atomicHierarchy.chainAtomSegments.index[element];
  45. entityId = model.atomicHierarchy.chains.label_entity_id.value(chainIndex);
  46. break;
  47. case Unit.Kind.Spheres:
  48. entityId = model.coarseHierarchy.spheres.entity_id.value(element);
  49. break;
  50. case Unit.Kind.Gaussians:
  51. entityId = model.coarseHierarchy.gaussians.entity_id.value(element);
  52. break;
  53. }
  54. if (entityId === '') return 0;
  55. const entityIndex = model.entities.getEntityIndex(entityId);
  56. if (entityIndex === -1) return 0;
  57. const entity = model.sequence.byEntityKey[entityIndex];
  58. if (entity === undefined) return 0;
  59. return entity.sequence.length;
  60. }
  61. export function SequenceIdColorTheme(ctx: ThemeDataContext, props: PD.Values<SequenceIdColorThemeParams>): ColorTheme<SequenceIdColorThemeParams> {
  62. const scale = ColorScale.create({
  63. listOrName: props.list.colors,
  64. minLabel: 'Start',
  65. maxLabel: 'End',
  66. });
  67. const color = (location: Location): Color => {
  68. if (StructureElement.Location.is(location)) {
  69. const { unit, element } = location;
  70. const seq_id = getSeqId(unit, element);
  71. if (seq_id > 0) {
  72. const seqLen = getSequenceLength(unit, element);
  73. if (seqLen) {
  74. scale.setDomain(0, seqLen - 1);
  75. return scale.color(seq_id);
  76. }
  77. }
  78. } else if (Bond.isLocation(location)) {
  79. const { aUnit, aIndex } = location;
  80. const seq_id = getSeqId(aUnit, aUnit.elements[aIndex]);
  81. if (seq_id > 0) {
  82. const seqLen = getSequenceLength(aUnit, aUnit.elements[aIndex]);
  83. if (seqLen) {
  84. scale.setDomain(0, seqLen - 1);
  85. return scale.color(seq_id);
  86. }
  87. }
  88. }
  89. return DefaultColor;
  90. };
  91. return {
  92. factory: SequenceIdColorTheme,
  93. granularity: 'group',
  94. color,
  95. props,
  96. description: Description,
  97. legend: scale ? scale.legend : undefined
  98. };
  99. }
  100. export const SequenceIdColorThemeProvider: ColorTheme.Provider<SequenceIdColorThemeParams, 'sequence-id'> = {
  101. name: 'sequence-id',
  102. label: 'Sequence Id',
  103. category: ColorTheme.Category.Residue,
  104. factory: SequenceIdColorTheme,
  105. getParams: getSequenceIdColorThemeParams,
  106. defaultValues: PD.getDefaultValues(SequenceIdColorThemeParams),
  107. isApplicable: (ctx: ThemeDataContext) => !!ctx.structure
  108. };