basic.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { PluginContext } from 'mol-plugin/context';
  7. import { StateTree, Transformer } from 'mol-state';
  8. import { StateAction } from 'mol-state/action';
  9. import { StateSelection } from 'mol-state/state/selection';
  10. import { StateTreeBuilder } from 'mol-state/tree/builder';
  11. import { ParamDefinition as PD } from 'mol-util/param-definition';
  12. import { PluginStateObject } from '../objects';
  13. import { StateTransforms } from '../transforms';
  14. import { Download } from '../transforms/data';
  15. import { StructureRepresentation3DHelpers } from '../transforms/representation';
  16. import * as data_functions from "mol-io/reader/ply//read_data/data"
  17. // TODO: "structure parser provider"
  18. export { DownloadStructure };
  19. type DownloadStructure = typeof DownloadStructure
  20. const DownloadStructure = StateAction.build({
  21. from: PluginStateObject.Root,
  22. display: { name: 'Download Structure', description: 'Load a structure from the provided source and create its default Assembly and visual.' },
  23. params: {
  24. source: PD.MappedStatic('bcif-static', {
  25. 'pdbe-updated': PD.Group({
  26. id: PD.Text('1cbs', { label: 'Id' }),
  27. supportProps: PD.Boolean(false)
  28. }, { isFlat: true }),
  29. 'rcsb': PD.Group({
  30. id: PD.Text('1tqn', { label: 'Id' }),
  31. supportProps: PD.Boolean(false)
  32. }, { isFlat: true }),
  33. 'bcif-static': PD.Group({
  34. id: PD.Text('1tqn', { label: 'Id' }),
  35. supportProps: PD.Boolean(false)
  36. }, { isFlat: true }),
  37. 'url': PD.Group({
  38. url: PD.Text(''),
  39. isBinary: PD.Boolean(false),
  40. supportProps: PD.Boolean(false)
  41. }, { isFlat: true })
  42. }, {
  43. options: [
  44. ['pdbe-updated', 'PDBe Updated'],
  45. ['rcsb', 'RCSB'],
  46. ['bcif-static', 'BinaryCIF (static PDBe Updated)'],
  47. ['url', 'URL']
  48. ]
  49. })
  50. }
  51. })(({ params, state }, ctx: PluginContext) => {
  52. const b = state.build();
  53. const src = params.source;
  54. let url: Transformer.Params<Download>;
  55. switch (src.name) {
  56. case 'url':
  57. url = src.params;
  58. break;
  59. case 'pdbe-updated':
  60. url = { url: `https://www.ebi.ac.uk/pdbe/static/entry/${src.params.id.toLowerCase()}_updated.cif`, isBinary: false, label: `PDBe: ${src.params.id}` };
  61. break;
  62. case 'rcsb':
  63. url = { url: `https://files.rcsb.org/download/${src.params.id.toUpperCase()}.cif`, isBinary: false, label: `RCSB: ${src.params.id}` };
  64. break;
  65. case 'bcif-static':
  66. url = { url: `https://webchem.ncbr.muni.cz/ModelServer/static/bcif/${src.params.id.toLowerCase()}`, isBinary: true, label: `BinaryCIF: ${src.params.id}` };
  67. break;
  68. default: throw new Error(`${(src as any).name} not supported.`);
  69. }
  70. const data = b.toRoot().apply(StateTransforms.Data.Download, url);
  71. return state.update(createStructureTree(ctx, data, params.source.params.supportProps));
  72. });
  73. export const OpenStructure = StateAction.build({
  74. display: { name: 'Open Structure', description: 'Load a structure from file and create its default Assembly and visual' },
  75. from: PluginStateObject.Root,
  76. params: { file: PD.File({ accept: '.cif,.bcif' }) }
  77. })(({ params, state }, ctx: PluginContext) => {
  78. const b = state.build();
  79. const data = b.toRoot().apply(StateTransforms.Data.ReadFile, { file: params.file, isBinary: /\.bcif$/i.test(params.file.name) });
  80. return state.update(createStructureTree(ctx, data, false));
  81. });
  82. export const PLYtest = StateAction.build({
  83. display: { name: 'PLY Test', description: 'nothing ply' },
  84. from: PluginStateObject.Root,
  85. params: { file: PD.File({ accept: '.ply' }) }
  86. })(({ params, state }, ctx: PluginContext) => {
  87. const b = state.build();
  88. const data = b.toRoot().apply(data_functions.ReadFile_ascii, { file: params.file, isBinary: false });
  89. return state.update(getPLYdata(ctx, data));
  90. });
  91. function getPLYdata(ctx: PluginContext, b: StateTreeBuilder.To<PluginStateObject.Data.String>, ): StateTree {
  92. let root = b
  93. .apply(data_functions.ParsePLY);
  94. console.log(data_functions.ParsePLY);
  95. return root.getTree();
  96. }
  97. function createStructureTree(ctx: PluginContext, b: StateTreeBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, supportProps: boolean): StateTree {
  98. let root = b
  99. .apply(StateTransforms.Data.ParseCif)
  100. .apply(StateTransforms.Model.TrajectoryFromMmCif)
  101. .apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: 0 });
  102. if (supportProps) {
  103. root = root.apply(StateTransforms.Model.CustomModelProperties);
  104. }
  105. const structure = root.apply(StateTransforms.Model.StructureAssemblyFromModel);
  106. complexRepresentation(ctx, structure);
  107. return root.getTree();
  108. }
  109. function complexRepresentation(ctx: PluginContext, root: StateTreeBuilder.To<PluginStateObject.Molecule.Structure>) {
  110. root.apply(StateTransforms.Model.StructureComplexElement, { type: 'atomic-sequence' })
  111. .apply(StateTransforms.Representation.StructureRepresentation3D,
  112. StructureRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'cartoon'));
  113. root.apply(StateTransforms.Model.StructureComplexElement, { type: 'atomic-het' })
  114. .apply(StateTransforms.Representation.StructureRepresentation3D,
  115. StructureRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'ball-and-stick'));
  116. root.apply(StateTransforms.Model.StructureComplexElement, { type: 'water' })
  117. .apply(StateTransforms.Representation.StructureRepresentation3D,
  118. StructureRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'ball-and-stick', { alpha: 0.51 }));
  119. root.apply(StateTransforms.Model.StructureComplexElement, { type: 'spheres' })
  120. .apply(StateTransforms.Representation.StructureRepresentation3D,
  121. StructureRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'spacefill'));
  122. }
  123. export const CreateComplexRepresentation = StateAction.build({
  124. display: { name: 'Create Complex', description: 'Split the structure into Sequence/Water/Ligands/... ' },
  125. from: PluginStateObject.Molecule.Structure
  126. })(({ ref, state }, ctx: PluginContext) => {
  127. const root = state.build().to(ref);
  128. complexRepresentation(ctx, root);
  129. return state.update(root.getTree());
  130. });
  131. export const UpdateTrajectory = StateAction.build({
  132. display: { name: 'Update Trajectory' },
  133. params: {
  134. action: PD.Select<'advance' | 'reset'>('advance', [['advance', 'Advance'], ['reset', 'Reset']]),
  135. by: PD.makeOptional(PD.Numeric(1, { min: -1, max: 1, step: 1 }))
  136. }
  137. })(({ params, state }) => {
  138. const models = state.select(q => q.rootsOfType(PluginStateObject.Molecule.Model)
  139. .filter(c => c.transform.transformer === StateTransforms.Model.ModelFromTrajectory));
  140. const update = state.build();
  141. if (params.action === 'reset') {
  142. for (const m of models) {
  143. update.to(m.transform.ref).update(StateTransforms.Model.ModelFromTrajectory,
  144. () => ({ modelIndex: 0 }));
  145. }
  146. } else {
  147. for (const m of models) {
  148. const parent = StateSelection.findAncestorOfType(state.tree, state.cells, m.transform.ref, [PluginStateObject.Molecule.Trajectory]);
  149. if (!parent || !parent.obj) continue;
  150. const traj = parent.obj as PluginStateObject.Molecule.Trajectory;
  151. update.to(m.transform.ref).update(StateTransforms.Model.ModelFromTrajectory,
  152. old => {
  153. let modelIndex = (old.modelIndex + params.by!) % traj.data.length;
  154. if (modelIndex < 0) modelIndex += traj.data.length;
  155. return { modelIndex };
  156. });
  157. }
  158. }
  159. return state.update(update);
  160. });