annotation-color-theme.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /**
  2. * Copyright (c) 2023-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Adam Midlik <midlik@gmail.com>
  5. */
  6. import { Location } from '../../../mol-model/location';
  7. import { Bond, StructureElement } from '../../../mol-model/structure';
  8. import { ColorTheme, LocationColor } from '../../../mol-theme/color';
  9. import { ThemeDataContext } from '../../../mol-theme/theme';
  10. import { ColorNames } from '../../../mol-util/color/names';
  11. import { ParamDefinition as PD } from '../../../mol-util/param-definition';
  12. import { decodeColor } from '../helpers/utils';
  13. import { getMVSAnnotationForStructure } from './annotation-prop';
  14. import { isMVSStructure } from './is-mvs-model-prop';
  15. /** Parameter definition for color theme "MVS Annotation" */
  16. export const MVSAnnotationColorThemeParams = {
  17. annotationId: PD.Text('', { description: 'Reference to "Annotation" custom model property' }),
  18. fieldName: PD.Text('color', { description: 'Annotation field (column) from which to take color values' }),
  19. background: PD.Color(ColorNames.gainsboro, { description: 'Color for elements without annotation' }),
  20. };
  21. export type MVSAnnotationColorThemeParams = typeof MVSAnnotationColorThemeParams
  22. /** Parameter values for color theme "MVS Annotation" */
  23. export type MVSAnnotationColorThemeProps = PD.Values<MVSAnnotationColorThemeParams>
  24. /** Return color theme that assigns colors based on an annotation file.
  25. * The annotation file itself is handled by a custom model property (`MVSAnnotationsProvider`),
  26. * the color theme then just uses this property. */
  27. export function MVSAnnotationColorTheme(ctx: ThemeDataContext, props: MVSAnnotationColorThemeProps): ColorTheme<MVSAnnotationColorThemeParams> {
  28. let color: LocationColor = () => props.background;
  29. if (ctx.structure && !ctx.structure.isEmpty) {
  30. const { annotation } = getMVSAnnotationForStructure(ctx.structure, props.annotationId);
  31. if (annotation) {
  32. const colorForStructureElementLocation = (location: StructureElement.Location) => {
  33. // if (annot.getAnnotationForLocation(location)?.color !== annot.getAnnotationForLocation_Reference(location)?.color) throw new Error('AssertionError');
  34. return decodeColor(annotation?.getValueForLocation(location, props.fieldName)) ?? props.background;
  35. };
  36. const auxLocation = StructureElement.Location.create(ctx.structure);
  37. color = (location: Location) => {
  38. if (StructureElement.Location.is(location)) {
  39. return colorForStructureElementLocation(location);
  40. } else if (Bond.isLocation(location)) {
  41. // this will be applied for each bond twice, to get color of each half (a* refers to the adjacent atom, b* to the opposite atom)
  42. auxLocation.unit = location.aUnit;
  43. auxLocation.element = location.aUnit.elements[location.aIndex];
  44. return colorForStructureElementLocation(auxLocation);
  45. }
  46. return props.background;
  47. };
  48. } else {
  49. console.error(`Annotation source "${props.annotationId}" not present`);
  50. }
  51. }
  52. return {
  53. factory: MVSAnnotationColorTheme,
  54. granularity: 'group',
  55. preferSmoothing: true,
  56. color: color,
  57. props: props,
  58. description: 'Assigns colors based on custom MolViewSpec annotation data.',
  59. };
  60. }
  61. /** A thingy that is needed to register color theme "MVS Annotation" */
  62. export const MVSAnnotationColorThemeProvider: ColorTheme.Provider<MVSAnnotationColorThemeParams, 'mvs-annotation'> = {
  63. name: 'mvs-annotation',
  64. label: 'MVS Annotation',
  65. category: ColorTheme.Category.Misc,
  66. factory: MVSAnnotationColorTheme,
  67. getParams: ctx => MVSAnnotationColorThemeParams,
  68. defaultValues: PD.getDefaultValues(MVSAnnotationColorThemeParams),
  69. isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && isMVSStructure(ctx.structure),
  70. };