index.ts 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /**
  2. * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { PDBeStructureQualityReport } from '../../extensions/pdbe';
  7. import { EmptyLoci } from '../../mol-model/loci';
  8. import { StructureSelection } from '../../mol-model/structure';
  9. import { AnimateModelIndex } from '../../mol-plugin-state/animation/built-in/model-index';
  10. import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory';
  11. import { createPluginUI } from '../../mol-plugin-ui/react18';
  12. import { PluginUIContext } from '../../mol-plugin-ui/context';
  13. import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec';
  14. import { PluginCommands } from '../../mol-plugin/commands';
  15. import { Script } from '../../mol-script/script';
  16. import { Asset } from '../../mol-util/assets';
  17. import { Color } from '../../mol-util/color';
  18. import { StripedResidues } from './coloring';
  19. import { CustomToastMessage } from './controls';
  20. import { CustomColorThemeProvider } from './custom-theme';
  21. import './index.html';
  22. import { buildStaticSuperposition, dynamicSuperpositionTest, StaticSuperpositionTestData } from './superposition';
  23. require('mol-plugin-ui/skin/light.scss');
  24. type LoadParams = { url: string, format?: BuiltInTrajectoryFormat, isBinary?: boolean, assemblyId?: string }
  25. class BasicWrapper {
  26. plugin: PluginUIContext;
  27. async init(target: string | HTMLElement) {
  28. this.plugin = await createPluginUI(typeof target === 'string' ? document.getElementById(target)! : target, {
  29. ...DefaultPluginUISpec(),
  30. layout: {
  31. initial: {
  32. isExpanded: false,
  33. showControls: false
  34. }
  35. },
  36. components: {
  37. remoteState: 'none'
  38. }
  39. });
  40. this.plugin.representation.structure.themes.colorThemeRegistry.add(StripedResidues.colorThemeProvider!);
  41. this.plugin.representation.structure.themes.colorThemeRegistry.add(CustomColorThemeProvider);
  42. this.plugin.managers.lociLabels.addProvider(StripedResidues.labelProvider!);
  43. this.plugin.customModelProperties.register(StripedResidues.propertyProvider, true);
  44. this.plugin.managers.dragAndDrop.addHandler('custom-wrapper', (files) => {
  45. if (files.some(f => f.name.toLowerCase().endsWith('.testext'))) {
  46. console.log('.testext File dropped');
  47. return true;
  48. }
  49. return false;
  50. });
  51. }
  52. async load({ url, format = 'mmcif', isBinary = false, assemblyId = '' }: LoadParams) {
  53. await this.plugin.clear();
  54. const data = await this.plugin.builders.data.download({ url: Asset.Url(url), isBinary }, { state: { isGhost: true } });
  55. const trajectory = await this.plugin.builders.structure.parseTrajectory(data, format);
  56. await this.plugin.builders.structure.hierarchy.applyPreset(trajectory, 'default', {
  57. structure: assemblyId ? {
  58. name: 'assembly',
  59. params: { id: assemblyId }
  60. } : {
  61. name: 'model',
  62. params: {}
  63. },
  64. showUnitcell: false,
  65. representationPreset: 'auto'
  66. });
  67. }
  68. setBackground(color: number) {
  69. PluginCommands.Canvas3D.SetSettings(this.plugin, { settings: props => { props.renderer.backgroundColor = Color(color); } });
  70. }
  71. toggleSpin() {
  72. if (!this.plugin.canvas3d) return;
  73. const trackball = this.plugin.canvas3d.props.trackball;
  74. PluginCommands.Canvas3D.SetSettings(this.plugin, {
  75. settings: {
  76. trackball: {
  77. ...trackball,
  78. animate: trackball.animate.name === 'spin'
  79. ? { name: 'off', params: {} }
  80. : { name: 'spin', params: { speed: 1 } }
  81. }
  82. }
  83. });
  84. if (this.plugin.canvas3d.props.trackball.animate.name !== 'spin') {
  85. PluginCommands.Camera.Reset(this.plugin, {});
  86. }
  87. }
  88. private animateModelIndexTargetFps() {
  89. return Math.max(1, this.animate.modelIndex.targetFps | 0);
  90. }
  91. animate = {
  92. modelIndex: {
  93. targetFps: 8,
  94. onceForward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'once', params: { direction: 'forward' } } }); },
  95. onceBackward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'once', params: { direction: 'backward' } } }); },
  96. palindrome: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'palindrome', params: {} } }); },
  97. loop: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'loop', params: { direction: 'forward' } } }); },
  98. stop: () => this.plugin.managers.animation.stop()
  99. }
  100. };
  101. coloring = {
  102. applyStripes: async () => {
  103. this.plugin.dataTransaction(async () => {
  104. for (const s of this.plugin.managers.structure.hierarchy.current.structures) {
  105. await this.plugin.managers.structure.component.updateRepresentationsTheme(s.components, { color: StripedResidues.propertyProvider.descriptor.name as any });
  106. }
  107. });
  108. },
  109. applyCustomTheme: async () => {
  110. this.plugin.dataTransaction(async () => {
  111. for (const s of this.plugin.managers.structure.hierarchy.current.structures) {
  112. await this.plugin.managers.structure.component.updateRepresentationsTheme(s.components, { color: CustomColorThemeProvider.name as any });
  113. }
  114. });
  115. },
  116. applyDefault: async () => {
  117. this.plugin.dataTransaction(async () => {
  118. for (const s of this.plugin.managers.structure.hierarchy.current.structures) {
  119. await this.plugin.managers.structure.component.updateRepresentationsTheme(s.components, { color: 'default' });
  120. }
  121. });
  122. }
  123. };
  124. interactivity = {
  125. highlightOn: () => {
  126. const data = this.plugin.managers.structure.hierarchy.current.structures[0]?.cell.obj?.data;
  127. if (!data) return;
  128. const seq_id = 7;
  129. const sel = Script.getStructureSelection(Q => Q.struct.generator.atomGroups({
  130. 'residue-test': Q.core.rel.eq([Q.struct.atomProperty.macromolecular.label_seq_id(), seq_id]),
  131. 'group-by': Q.struct.atomProperty.macromolecular.residueKey()
  132. }), data);
  133. const loci = StructureSelection.toLociWithSourceUnits(sel);
  134. this.plugin.managers.interactivity.lociHighlights.highlightOnly({ loci });
  135. },
  136. clearHighlight: () => {
  137. this.plugin.managers.interactivity.lociHighlights.highlightOnly({ loci: EmptyLoci });
  138. }
  139. };
  140. tests = {
  141. staticSuperposition: async () => {
  142. await this.plugin.clear();
  143. return buildStaticSuperposition(this.plugin, StaticSuperpositionTestData);
  144. },
  145. dynamicSuperposition: async () => {
  146. await this.plugin.clear();
  147. return dynamicSuperpositionTest(this.plugin, ['1tqn', '2hhb', '4hhb'], 'HEM');
  148. },
  149. toggleValidationTooltip: () => {
  150. return this.plugin.state.updateBehavior(PDBeStructureQualityReport, params => { params.showTooltip = !params.showTooltip; });
  151. },
  152. showToasts: () => {
  153. PluginCommands.Toast.Show(this.plugin, {
  154. title: 'Toast 1',
  155. message: 'This is an example text, timeout 3s',
  156. key: 'toast-1',
  157. timeoutMs: 3000
  158. });
  159. PluginCommands.Toast.Show(this.plugin, {
  160. title: 'Toast 2',
  161. message: CustomToastMessage,
  162. key: 'toast-2'
  163. });
  164. },
  165. hideToasts: () => {
  166. PluginCommands.Toast.Hide(this.plugin, { key: 'toast-1' });
  167. PluginCommands.Toast.Hide(this.plugin, { key: 'toast-2' });
  168. }
  169. };
  170. }
  171. (window as any).BasicMolStarWrapper = new BasicWrapper();