uncertainty.ts 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /**
  2. * Copyright (c) 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, ColorScale } from '../../mol-util/color';
  7. import { StructureElement, Unit, Bond, ElementIndex } from '../../mol-model/structure';
  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 '../theme';
  12. import { ColorListName, ColorListOptionsScale } from '../../mol-util/color/lists';
  13. const DefaultUncertaintyColor = Color(0xffff99)
  14. const Description = `Assigns a color based on the uncertainty or disorder of an element's position, e.g. B-factor or RMSF, depending on the data availability and experimental technique.`
  15. export const UncertaintyColorThemeParams = {
  16. domain: PD.Interval([0, 100]),
  17. list: PD.ColorList<ColorListName>('red-white-blue', ColorListOptionsScale),
  18. }
  19. export type UncertaintyColorThemeParams = typeof UncertaintyColorThemeParams
  20. export function getUncertaintyColorThemeParams(ctx: ThemeDataContext) {
  21. return UncertaintyColorThemeParams // TODO return copy
  22. }
  23. export function getUncertainty(unit: Unit, element: ElementIndex): number {
  24. if (Unit.isAtomic(unit)) {
  25. return unit.model.atomicConformation.B_iso_or_equiv.value(element)
  26. } else if (Unit.isSpheres(unit)) {
  27. return unit.model.coarseConformation.spheres.rmsf[element]
  28. } else {
  29. return 0
  30. }
  31. }
  32. export function UncertaintyColorTheme(ctx: ThemeDataContext, props: PD.Values<UncertaintyColorThemeParams>): ColorTheme<UncertaintyColorThemeParams> {
  33. const scale = ColorScale.create({
  34. reverse: true,
  35. domain: props.domain,
  36. listOrName: props.list,
  37. })
  38. // TODO calc domain based on data, set min/max as 10/90 percentile to be robust against outliers
  39. function color(location: Location): Color {
  40. if (StructureElement.Location.is(location)) {
  41. return scale.color(getUncertainty(location.unit, location.element))
  42. } else if (Bond.isLocation(location)) {
  43. return scale.color(getUncertainty(location.aUnit, location.aUnit.elements[location.aIndex]))
  44. }
  45. return DefaultUncertaintyColor
  46. }
  47. return {
  48. factory: UncertaintyColorTheme,
  49. granularity: 'group',
  50. color,
  51. props,
  52. description: Description,
  53. legend: scale ? scale.legend : undefined
  54. }
  55. }
  56. export const UncertaintyColorThemeProvider: ColorTheme.Provider<UncertaintyColorThemeParams> = {
  57. label: 'Uncertainty/Disorder',
  58. factory: UncertaintyColorTheme,
  59. getParams: getUncertaintyColorThemeParams,
  60. defaultValues: PD.getDefaultValues(UncertaintyColorThemeParams),
  61. isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && ctx.structure.models.some(m => m.atomicConformation.B_iso_or_equiv.isDefined || m.coarseHierarchy.isDefined)
  62. }