render-structure.ts 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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 } from '../../mol-model/structure';
  10. import { ColorTheme } 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 { MolecularSurfaceRepresentationProvider } from '../../mol-repr/structure/representation/molecular-surface';
  15. import { BallAndStickRepresentationProvider } from '../../mol-repr/structure/representation/ball-and-stick';
  16. import { GaussianSurfaceRepresentationProvider } from '../../mol-repr/structure/representation/gaussian-surface';
  17. import { resizeCanvas } from '../../mol-canvas3d/util';
  18. import { Representation } from '../../mol-repr/representation';
  19. import { throttleTime } from 'rxjs/operators';
  20. import { MarkerAction } from '../../mol-util/marker-action';
  21. import { EveryLoci } from '../../mol-model/loci';
  22. import { lociLabel } from '../../mol-theme/label';
  23. import { InteractionsRepresentationProvider } from '../../mol-model-props/computed/representations/interactions';
  24. import { InteractionsProvider } from '../../mol-model-props/computed/interactions';
  25. import { SecondaryStructureProvider } from '../../mol-model-props/computed/secondary-structure';
  26. import { SyncRuntimeContext } from '../../mol-task/execution/synchronous';
  27. import { AssetManager } from '../../mol-util/assets';
  28. import { AccessibleSurfaceAreaProvider } from '../../mol-model-props/computed/accessible-surface-area';
  29. import { MembraneProvider } from '../../mol-model-props/computed/membrane';
  30. import { SpheresBuilder } from '../../mol-geo/geometry/spheres/spheres-builder';
  31. import { Spheres } from '../../mol-geo/geometry/spheres/spheres';
  32. import { Color } from '../../mol-util/color';
  33. import { createRenderObject } from '../../mol-gl/render-object';
  34. import { Membrane } from '../../mol-model-props/computed/membrane/ANVIL';
  35. const parent = document.getElementById('app')!;
  36. parent.style.width = '100%';
  37. parent.style.height = '100%';
  38. const canvas = document.createElement('canvas');
  39. parent.appendChild(canvas);
  40. resizeCanvas(canvas, parent);
  41. const canvas3d = Canvas3D.fromCanvas(canvas);
  42. canvas3d.animate();
  43. const info = document.createElement('div');
  44. info.style.position = 'absolute';
  45. info.style.fontFamily = 'sans-serif';
  46. info.style.fontSize = '16pt';
  47. info.style.bottom = '20px';
  48. info.style.right = '20px';
  49. info.style.color = 'white';
  50. parent.appendChild(info);
  51. let prevReprLoci = Representation.Loci.Empty;
  52. canvas3d.input.move.pipe(throttleTime(100)).subscribe(({x, y}) => {
  53. const pickingId = canvas3d.identify(x, y);
  54. let label = '';
  55. if (pickingId) {
  56. const reprLoci = canvas3d.getLoci(pickingId);
  57. label = lociLabel(reprLoci.loci);
  58. if (!Representation.Loci.areEqual(prevReprLoci, reprLoci)) {
  59. canvas3d.mark(prevReprLoci, MarkerAction.RemoveHighlight);
  60. canvas3d.mark(reprLoci, MarkerAction.Highlight);
  61. prevReprLoci = reprLoci;
  62. }
  63. } else {
  64. canvas3d.mark({ loci: EveryLoci }, MarkerAction.RemoveHighlight);
  65. prevReprLoci = Representation.Loci.Empty;
  66. }
  67. info.innerHTML = label;
  68. });
  69. async function parseCif(data: string|Uint8Array) {
  70. const comp = CIF.parse(data);
  71. const parsed = await comp.run();
  72. if (parsed.isError) throw parsed;
  73. return parsed.result;
  74. }
  75. async function downloadCif(url: string, isBinary: boolean) {
  76. const data = await fetch(url);
  77. return parseCif(isBinary ? new Uint8Array(await data.arrayBuffer()) : await data.text());
  78. }
  79. async function downloadFromPdb(pdb: string) {
  80. const parsed = await downloadCif(`https://models.rcsb.org/${pdb}.bcif`, true);
  81. return parsed.blocks[0];
  82. }
  83. async function getModels(frame: CifFrame) {
  84. return await trajectoryFromMmCIF(frame).run();
  85. }
  86. async function getStructure(model: Model) {
  87. return Structure.ofModel(model);
  88. }
  89. const reprCtx = {
  90. webgl: canvas3d.webgl,
  91. colorThemeRegistry: ColorTheme.createRegistry(),
  92. sizeThemeRegistry: SizeTheme.createRegistry()
  93. };
  94. function getCartoonRepr() {
  95. return CartoonRepresentationProvider.factory(reprCtx, CartoonRepresentationProvider.getParams);
  96. }
  97. function getInteractionRepr() {
  98. return InteractionsRepresentationProvider.factory(reprCtx, InteractionsRepresentationProvider.getParams);
  99. }
  100. function getBallAndStickRepr() {
  101. return BallAndStickRepresentationProvider.factory(reprCtx, BallAndStickRepresentationProvider.getParams);
  102. }
  103. function getMolecularSurfaceRepr() {
  104. return MolecularSurfaceRepresentationProvider.factory(reprCtx, MolecularSurfaceRepresentationProvider.getParams);
  105. }
  106. function getGaussianSurfaceRepr() {
  107. return GaussianSurfaceRepresentationProvider.factory(reprCtx, GaussianSurfaceRepresentationProvider.getParams);
  108. }
  109. function getMembraneRepr(membrane: Membrane) {
  110. const spheresBuilder = SpheresBuilder.create(membrane.length, 1);
  111. for (let i = 0, il = membrane.length; i < il; i++) {
  112. spheresBuilder.add(membrane[i][0], membrane[i][1], membrane[i][2], 0);
  113. }
  114. const spheres = spheresBuilder.getSpheres();
  115. const values = Spheres.Utils.createValuesSimple(spheres, {}, Color(0xCCCCCC), 1);
  116. const state = Spheres.Utils.createRenderableState({});
  117. const renderObject = createRenderObject('spheres', values, state, -1);
  118. console.log(renderObject);
  119. const repr = Representation.fromRenderObject('spheres', renderObject);
  120. return repr;
  121. }
  122. async function init() {
  123. const ctx = { runtime: SyncRuntimeContext, assetManager: new AssetManager() };
  124. const cif = await downloadFromPdb('3pqr');
  125. const models = await getModels(cif);
  126. const structure = await getStructure(models[0]);
  127. console.time('compute SecondaryStructure');
  128. await SecondaryStructureProvider.attach(ctx, structure);
  129. console.timeEnd('compute SecondaryStructure');
  130. console.time('compute AccessibleSurfaceArea');
  131. await AccessibleSurfaceAreaProvider.attach(ctx, structure);
  132. console.timeEnd('compute AccessibleSurfaceArea');
  133. console.time('compute Membrane');
  134. await MembraneProvider.attach(ctx, structure);
  135. console.timeEnd('compute Membrane');
  136. console.time('compute Interactions');
  137. await InteractionsProvider.attach(ctx, structure);
  138. console.timeEnd('compute Interactions');
  139. console.log(InteractionsProvider.get(structure).value);
  140. const show = {
  141. cartoon: true,
  142. interaction: false,
  143. ballAndStick: false,
  144. molecularSurface: false,
  145. gaussianSurface: false,
  146. membrane: true
  147. };
  148. const cartoonRepr = getCartoonRepr();
  149. const interactionRepr = getInteractionRepr();
  150. const ballAndStickRepr = getBallAndStickRepr();
  151. const molecularSurfaceRepr = getMolecularSurfaceRepr();
  152. const gaussianSurfaceRepr = getGaussianSurfaceRepr();
  153. const membraneRepr = getMembraneRepr(MembraneProvider.get(structure).value!);
  154. if (show.cartoon) {
  155. cartoonRepr.setTheme({
  156. color: reprCtx.colorThemeRegistry.create('element-symbol', { structure }),
  157. size: reprCtx.sizeThemeRegistry.create('uniform', { structure })
  158. });
  159. await cartoonRepr.createOrUpdate({ ...CartoonRepresentationProvider.defaultValues, quality: 'auto' }, structure).run();
  160. }
  161. if (show.interaction) {
  162. interactionRepr.setTheme({
  163. color: reprCtx.colorThemeRegistry.create('interaction-type', { structure }),
  164. size: reprCtx.sizeThemeRegistry.create('uniform', { structure })
  165. });
  166. await interactionRepr.createOrUpdate({ ...InteractionsRepresentationProvider.defaultValues, quality: 'auto' }, structure).run();
  167. }
  168. if (show.ballAndStick) {
  169. ballAndStickRepr.setTheme({
  170. color: reprCtx.colorThemeRegistry.create('element-symbol', { structure }),
  171. size: reprCtx.sizeThemeRegistry.create('uniform', { structure }, { value: 1 })
  172. });
  173. await ballAndStickRepr.createOrUpdate({ ...BallAndStickRepresentationProvider.defaultValues, quality: 'auto' }, structure).run();
  174. }
  175. if (show.molecularSurface) {
  176. molecularSurfaceRepr.setTheme({
  177. color: reprCtx.colorThemeRegistry.create('secondary-structure', { structure }),
  178. size: reprCtx.sizeThemeRegistry.create('physical', { structure })
  179. });
  180. console.time('molecular surface');
  181. await molecularSurfaceRepr.createOrUpdate({ ...MolecularSurfaceRepresentationProvider.defaultValues, quality: 'custom', alpha: 0.5, flatShaded: true, doubleSided: true, resolution: 0.3 }, structure).run();
  182. console.timeEnd('molecular surface');
  183. }
  184. if (show.gaussianSurface) {
  185. gaussianSurfaceRepr.setTheme({
  186. color: reprCtx.colorThemeRegistry.create('secondary-structure', { structure }),
  187. size: reprCtx.sizeThemeRegistry.create('physical', { structure })
  188. });
  189. console.time('gaussian surface');
  190. await gaussianSurfaceRepr.createOrUpdate({ ...GaussianSurfaceRepresentationProvider.defaultValues, quality: 'custom', alpha: 1.0, flatShaded: true, doubleSided: true, resolution: 0.3 }, structure).run();
  191. console.timeEnd('gaussian surface');
  192. }
  193. if (show.cartoon) canvas3d.add(cartoonRepr);
  194. if (show.interaction) canvas3d.add(interactionRepr);
  195. if (show.ballAndStick) canvas3d.add(ballAndStickRepr);
  196. if (show.molecularSurface) canvas3d.add(molecularSurfaceRepr);
  197. if (show.gaussianSurface) canvas3d.add(gaussianSurfaceRepr);
  198. if (show.membrane) canvas3d.add(membraneRepr);
  199. canvas3d.requestCameraReset();
  200. // canvas3d.setProps({ trackball: { ...canvas3d.props.trackball, spin: true } })
  201. }
  202. init();