render-asa.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 './index.html'
  7. import { Canvas3D } from 'mol-canvas3d/canvas3d';
  8. import CIF, { CifFrame } from 'mol-io/reader/cif'
  9. import { Model, Structure, StructureElement, Unit } from 'mol-model/structure';
  10. import { ColorTheme, LocationColor } from 'mol-theme/color';
  11. import { SizeTheme } from 'mol-theme/size';
  12. import { CartoonRepresentationProvider } from 'mol-repr/structure/representation/cartoon';
  13. import { trajectoryFromMmCIF } from 'mol-model-formats/structure/mmcif';
  14. import { AccessibleSurfaceArea } from 'mol-model/structure/structure/accessible-surface-area';
  15. import { Color, ColorScale } from 'mol-util/color';
  16. import { Location } from 'mol-model/location';
  17. import { ThemeDataContext } from 'mol-theme/theme';
  18. import { ParamDefinition as PD } from 'mol-util/param-definition';
  19. import { ColorListName, ColorListOptions } from 'mol-util/color/scale';
  20. const parent = document.getElementById('app')!
  21. parent.style.width = '100%'
  22. parent.style.height = '100%'
  23. const canvas = document.createElement('canvas')
  24. canvas.style.width = '100%'
  25. canvas.style.height = '100%'
  26. parent.appendChild(canvas)
  27. const canvas3d = Canvas3D.create(canvas)
  28. canvas3d.animate()
  29. async function parseCif(data: string|Uint8Array) {
  30. const comp = CIF.parse(data);
  31. const parsed = await comp.run();
  32. if (parsed.isError) throw parsed;
  33. return parsed.result;
  34. }
  35. async function downloadCif(url: string, isBinary: boolean) {
  36. const data = await fetch(url);
  37. return parseCif(isBinary ? new Uint8Array(await data.arrayBuffer()) : await data.text());
  38. }
  39. async function downloadFromPdb(pdb: string) {
  40. // const parsed = await downloadCif(`https://files.rcsb.org/download/${pdb}.cif`, false);
  41. const parsed = await downloadCif(`https://webchem.ncbr.muni.cz/ModelServer/static/bcif/${pdb}`, true);
  42. return parsed.blocks[0];
  43. }
  44. async function getModels(frame: CifFrame) {
  45. return await trajectoryFromMmCIF(frame).run();
  46. }
  47. async function getStructure(model: Model) {
  48. return Structure.ofModel(model);
  49. }
  50. const reprCtx = {
  51. colorThemeRegistry: ColorTheme.createRegistry(),
  52. sizeThemeRegistry: SizeTheme.createRegistry()
  53. }
  54. function getCartoonRepr() {
  55. return CartoonRepresentationProvider.factory(reprCtx, CartoonRepresentationProvider.getParams)
  56. }
  57. let accessibleSurfaceArea: AccessibleSurfaceArea;
  58. async function init(props = {}) {
  59. const cif = await downloadFromPdb(
  60. // '3j3q'
  61. // '1aon'
  62. // '1acj'
  63. // '1pga'
  64. '1brr'
  65. // '1hrc'
  66. )
  67. const models = await getModels(cif)
  68. const structure = await getStructure(models[0])
  69. // async compute ASA
  70. accessibleSurfaceArea = await AccessibleSurfaceArea.compute(structure)
  71. const cartoonRepr = getCartoonRepr()
  72. // create color theme
  73. cartoonRepr.setTheme({
  74. color: AccessibleSurfaceAreaColorTheme(reprCtx, { ...PD.getDefaultValues(AccessibleSurfaceAreaColorThemeParams), ...props }),
  75. size: reprCtx.sizeThemeRegistry.create('uniform', { structure })
  76. })
  77. await cartoonRepr.createOrUpdate({ ...CartoonRepresentationProvider.defaultValues, quality: 'auto' }, structure).run()
  78. canvas3d.add(cartoonRepr)
  79. canvas3d.resetCamera()
  80. }
  81. init()
  82. const DefaultColor = Color(0xFFFFFF)
  83. const Description = 'Assigns a color based on the relative accessible surface area of a residue.'
  84. export const AccessibleSurfaceAreaColorThemeParams = {
  85. list: PD.ColorScale<ColorListName>('Rainbow', ColorListOptions)
  86. }
  87. export type AccessibleSurfaceAreaColorThemeParams = typeof AccessibleSurfaceAreaColorThemeParams
  88. export function getAccessibleSurfaceAreaColorThemeParams(ctx: ThemeDataContext) {
  89. return AccessibleSurfaceAreaColorThemeParams // TODO return copy
  90. }
  91. export function AccessibleSurfaceAreaColorTheme(ctx: ThemeDataContext, props: PD.Values<AccessibleSurfaceAreaColorThemeParams>): ColorTheme<AccessibleSurfaceAreaColorThemeParams> {
  92. let color: LocationColor = () => DefaultColor
  93. const scale = ColorScale.create({
  94. listOrName: props.list,
  95. minLabel: '0.0 (buried)',
  96. maxLabel: '1.0 (exposed)',
  97. domain: [0.0, 1.0]
  98. })
  99. color = (location: Location): Color => {
  100. if (StructureElement.isLocation(location)) {
  101. if (Unit.isAtomic(location.unit)) {
  102. const value = accessibleSurfaceArea.relativeAccessibleSurfaceArea![location.unit.residueIndex[location.element]];
  103. return value !== AccessibleSurfaceArea.VdWLookup[0] /* signals missing value */ ? scale.color(value) : DefaultColor;
  104. }
  105. }
  106. return DefaultColor
  107. }
  108. return {
  109. factory: AccessibleSurfaceAreaColorTheme,
  110. granularity: 'group',
  111. color,
  112. props,
  113. description: Description,
  114. legend: scale ? scale.legend : undefined
  115. }
  116. }
  117. export const AccessibleSurfaceAreaColorThemeProvider: ColorTheme.Provider<AccessibleSurfaceAreaColorThemeParams> = {
  118. label: 'Accessible Surface Area',
  119. factory: AccessibleSurfaceAreaColorTheme,
  120. getParams: getAccessibleSurfaceAreaColorThemeParams,
  121. defaultValues: PD.getDefaultValues(AccessibleSurfaceAreaColorThemeParams),
  122. isApplicable: (ctx: ThemeDataContext) => !!ctx.structure
  123. }