color.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /**
  2. * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { ThemeDataContext } from '../../../mol-theme/theme';
  7. import { ColorTheme, LocationColor } from '../../../mol-theme/color';
  8. import { ParamDefinition as PD } from '../../../mol-util/param-definition';
  9. import { AssemblySymmetryProvider, AssemblySymmetry } from './prop';
  10. import { Color } from '../../../mol-util/color';
  11. import { Unit, StructureElement, StructureProperties, Bond } from '../../../mol-model/structure';
  12. import { Location } from '../../../mol-model/location';
  13. import { ScaleLegend, TableLegend } from '../../../mol-util/legend';
  14. import { getPalette, getPaletteParams } from '../../../mol-util/color/palette';
  15. import { CustomProperty } from '../../../mol-model-props/common/custom-property';
  16. const DefaultColor = Color(0xCCCCCC);
  17. function getAsymId(unit: Unit): StructureElement.Property<string> {
  18. switch (unit.kind) {
  19. case Unit.Kind.Atomic:
  20. return StructureProperties.chain.label_asym_id;
  21. case Unit.Kind.Spheres:
  22. case Unit.Kind.Gaussians:
  23. return StructureProperties.coarse.asym_id;
  24. }
  25. }
  26. function clusterMemberKey(asymId: string, operList: string[]) {
  27. return `${asymId}-${operList.join('|')}`;
  28. }
  29. export const AssemblySymmetryClusterColorThemeParams = {
  30. ...getPaletteParams({ colorList: 'red-yellow-blue' }),
  31. };
  32. export type AssemblySymmetryClusterColorThemeParams = typeof AssemblySymmetryClusterColorThemeParams
  33. export function getAssemblySymmetryClusterColorThemeParams(ctx: ThemeDataContext) {
  34. const params = PD.clone(AssemblySymmetryClusterColorThemeParams);
  35. return params;
  36. }
  37. export function AssemblySymmetryClusterColorTheme(ctx: ThemeDataContext, props: PD.Values<AssemblySymmetryClusterColorThemeParams>): ColorTheme<AssemblySymmetryClusterColorThemeParams> {
  38. let color: LocationColor = () => DefaultColor;
  39. let legend: ScaleLegend | TableLegend | undefined;
  40. const assemblySymmetry = ctx.structure && AssemblySymmetryProvider.get(ctx.structure);
  41. const contextHash = assemblySymmetry?.version;
  42. const clusters = assemblySymmetry?.value?.clusters;
  43. if (clusters?.length && ctx.structure) {
  44. const l = StructureElement.Location.create(ctx.structure);
  45. const clusterByMember = new Map<string, number>();
  46. for (let i = 0, il = clusters.length; i < il; ++i) {
  47. const { members } = clusters[i]!;
  48. for (let j = 0, jl = members.length; j < jl; ++j) {
  49. const asymId = members[j]!.asym_id;
  50. const operList = [...members[j]!.pdbx_struct_oper_list_ids || []] as string[];
  51. clusterByMember.set(clusterMemberKey(asymId, operList), i);
  52. if (operList.length === 0) {
  53. operList.push('1'); // TODO hack assuming '1' is the id of the identity operator
  54. clusterByMember.set(clusterMemberKey(asymId, operList), i);
  55. }
  56. }
  57. }
  58. const palette = getPalette(clusters.length, props);
  59. legend = palette.legend;
  60. const _emptyList: any[] = [];
  61. const getColor = (location: StructureElement.Location) => {
  62. const { assembly } = location.unit.conformation.operator;
  63. const asymId = getAsymId(location.unit)(location);
  64. const cluster = clusterByMember.get(clusterMemberKey(asymId, assembly?.operList || _emptyList));
  65. return cluster !== undefined ? palette.color(cluster) : DefaultColor;
  66. };
  67. color = (location: Location): Color => {
  68. if (StructureElement.Location.is(location)) {
  69. return getColor(location);
  70. } else if (Bond.isLocation(location)) {
  71. l.unit = location.aUnit;
  72. l.element = location.aUnit.elements[location.aIndex];
  73. return getColor(l);
  74. }
  75. return DefaultColor;
  76. };
  77. }
  78. return {
  79. factory: AssemblySymmetryClusterColorTheme,
  80. granularity: 'instance',
  81. color,
  82. props,
  83. contextHash,
  84. description: 'Assigns chain colors according to assembly symmetry cluster membership calculated with BioJava and obtained via RCSB PDB.',
  85. legend
  86. };
  87. }
  88. export const AssemblySymmetryClusterColorThemeProvider: ColorTheme.Provider<AssemblySymmetryClusterColorThemeParams, AssemblySymmetry.Tag.Cluster> = {
  89. name: AssemblySymmetry.Tag.Cluster,
  90. label: 'Assembly Symmetry Cluster',
  91. category: ColorTheme.Category.Symmetry,
  92. factory: AssemblySymmetryClusterColorTheme,
  93. getParams: getAssemblySymmetryClusterColorThemeParams,
  94. defaultValues: PD.getDefaultValues(AssemblySymmetryClusterColorThemeParams),
  95. isApplicable: (ctx: ThemeDataContext) => AssemblySymmetry.isApplicable(ctx.structure),
  96. ensureCustomProperties: {
  97. attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? AssemblySymmetryProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(),
  98. detach: (data) => data.structure && AssemblySymmetryProvider.ref(data.structure, false)
  99. }
  100. };