index.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /**
  2. * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { DefaultPluginSpec } from 'molstar/lib/mol-plugin';
  7. import { Plugin } from 'molstar/lib/mol-plugin-ui/plugin'
  8. import './index.html'
  9. import './favicon.ico'
  10. import { PluginContext } from 'molstar/lib/mol-plugin/context';
  11. import { PluginCommands } from 'molstar/lib/mol-plugin/commands';
  12. import { PluginBehaviors } from 'molstar/lib/mol-plugin/behavior';
  13. import { AnimateModelIndex } from 'molstar/lib/mol-plugin-state/animation/built-in';
  14. import { SupportedFormats, StructureViewerState, StructureViewerProps } from './types';
  15. import { PluginSpec } from 'molstar/lib/mol-plugin/spec';
  16. import { StructureFocusRepresentation } from 'molstar/lib/mol-plugin/behavior/dynamic/selection/structure-focus-representation';
  17. import { ColorNames } from 'molstar/lib/mol-util/color/names';
  18. import ReactDOM = require('react-dom');
  19. import React = require('react');
  20. import { ModelLoader } from './helpers/model';
  21. import { PresetProps } from './helpers/preset';
  22. import { ControlsWrapper, ViewportWrapper } from './ui/controls';
  23. import { PluginConfig } from 'molstar/lib/mol-plugin/config';
  24. require('./skin/rcsb.scss')
  25. /** package version, filled in at bundle build time */
  26. declare const __RCSB_MOLSTAR_VERSION__: string
  27. export const RCSB_MOLSTAR_VERSION = __RCSB_MOLSTAR_VERSION__;
  28. /** unix time stamp, to be filled in at bundle build time */
  29. declare const __VERSION_TIMESTAMP__: number
  30. export const BUILD_TIMESTAMP = __VERSION_TIMESTAMP__;
  31. export const BUILD_DATE = new Date(BUILD_TIMESTAMP);
  32. export const DefaultStructureViewerProps: StructureViewerProps = {
  33. volumeServerUrl: '//maps.rcsb.org/',
  34. modelUrlProviders: [
  35. (pdbId: string) => ({
  36. url: `//models.rcsb.org/${pdbId.toLowerCase()}.bcif`,
  37. format: 'bcif' as const
  38. }),
  39. (pdbId: string) => ({
  40. url: `//files.rcsb.org/download/${pdbId.toLowerCase()}.cif`,
  41. format: 'cif' as const
  42. })
  43. ],
  44. showOpenFileControls: false,
  45. }
  46. export class StructureViewer {
  47. private readonly plugin: PluginContext;
  48. private readonly props: Readonly<StructureViewerProps>
  49. private get customState() {
  50. return this.plugin.customState as StructureViewerState
  51. }
  52. constructor(target: string | HTMLElement, props: Partial<StructureViewerProps> = {}) {
  53. target = typeof target === 'string' ? document.getElementById(target)! : target
  54. this.props = { ...DefaultStructureViewerProps, ...props }
  55. this.plugin = new PluginContext({
  56. ...DefaultPluginSpec,
  57. behaviors: [
  58. PluginSpec.Behavior(PluginBehaviors.Representation.HighlightLoci),
  59. PluginSpec.Behavior(PluginBehaviors.Representation.SelectLoci),
  60. PluginSpec.Behavior(PluginBehaviors.Representation.DefaultLociLabelProvider),
  61. PluginSpec.Behavior(PluginBehaviors.Representation.FocusLoci),
  62. PluginSpec.Behavior(PluginBehaviors.Camera.FocusLoci),
  63. PluginSpec.Behavior(StructureFocusRepresentation),
  64. PluginSpec.Behavior(PluginBehaviors.CustomProps.AccessibleSurfaceArea),
  65. PluginSpec.Behavior(PluginBehaviors.CustomProps.Interactions),
  66. PluginSpec.Behavior(PluginBehaviors.CustomProps.SecondaryStructure),
  67. PluginSpec.Behavior(PluginBehaviors.CustomProps.ValenceModel),
  68. PluginSpec.Behavior(PluginBehaviors.CustomProps.CrossLinkRestraint),
  69. PluginSpec.Behavior(PluginBehaviors.CustomProps.RCSBAssemblySymmetry),
  70. PluginSpec.Behavior(PluginBehaviors.CustomProps.RCSBValidationReport),
  71. ],
  72. animations: [
  73. AnimateModelIndex
  74. ],
  75. layout: {
  76. initial: {
  77. isExpanded: false,
  78. showControls: true,
  79. controlsDisplay: 'reactive'
  80. },
  81. controls: {
  82. left: 'none',
  83. right: ControlsWrapper,
  84. bottom: 'none'
  85. }
  86. },
  87. components: {
  88. viewport: {
  89. view: ViewportWrapper,
  90. }
  91. },
  92. config: new Map([
  93. [PluginConfig.VolumeStreaming.DefaultServer, this.props.volumeServerUrl]
  94. ])
  95. });
  96. (this.plugin.customState as StructureViewerState) = {
  97. props: this.props,
  98. modelLoader: new ModelLoader(this.plugin),
  99. }
  100. ReactDOM.render(React.createElement(Plugin, { plugin: this.plugin }), target)
  101. const renderer = this.plugin.canvas3d!.props.renderer;
  102. PluginCommands.Canvas3D.SetSettings(this.plugin, { settings: { renderer: { ...renderer, backgroundColor: ColorNames.white } } })
  103. PluginCommands.Toast.Show(this.plugin, {
  104. title: 'Welcome',
  105. message: `RCSB PDB Mol* Viewer ${RCSB_MOLSTAR_VERSION} [${BUILD_DATE.toLocaleString()}]`,
  106. key: 'toast-welcome',
  107. timeoutMs: 5000
  108. })
  109. }
  110. //
  111. async loadPdbId(pdbId: string, props?: PresetProps) {
  112. for (const provider of this.props.modelUrlProviders) {
  113. try {
  114. const p = provider(pdbId)
  115. await this.customState.modelLoader.load({ fileOrUrl: p.url, format: p.format }, props)
  116. break
  117. } catch (e) {
  118. console.warn(`loading '${pdbId}' failed with '${e}', trying next model-loader-provider`)
  119. }
  120. }
  121. }
  122. async loadUrl(url: string, props?: PresetProps) {
  123. await this.customState.modelLoader.load({ fileOrUrl: url, format: 'cif', }, props)
  124. }
  125. }