superposition.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. // TODO: move to an "example"
  7. import { PluginContext } from '../../mol-plugin/context';
  8. import { Mat4 } from '../../mol-math/linear-algebra';
  9. import { StateHelper } from './helpers';
  10. import { PluginCommands } from '../../mol-plugin/command';
  11. import { StateSelection, StateBuilder } from '../../mol-state';
  12. import { PluginStateObject as PSO } from '../../mol-plugin/state/objects';
  13. import { MolScriptBuilder as MS } from '../../mol-script/language/builder';
  14. import { compile } from '../../mol-script/runtime/query/compiler';
  15. import { StructureSelection, QueryContext } from '../../mol-model/structure';
  16. import { superposeStructures } from '../../mol-model/structure/structure/util/superposition';
  17. import Expression from '../../mol-script/language/expression';
  18. export type SuperpositionTestInput = {
  19. pdbId: string,
  20. auth_asym_id: string,
  21. matrix: Mat4
  22. }[];
  23. // function getAxisAngleTranslation(m: Mat4) {
  24. // const translation = Mat4.getTranslation(Vec3.zero(), m);
  25. // const axis = Vec3.zero();
  26. // const angle = 180 / Math.PI * Quat.getAxisAngle(axis, Mat4.getRotation(Quat.zero(), m));
  27. // return { translation, axis, angle };
  28. // }
  29. export function buildStaticSuperposition(ctx: PluginContext, src: SuperpositionTestInput) {
  30. const b = ctx.state.dataState.build().toRoot();
  31. for (const s of src) {
  32. StateHelper.visual(ctx,
  33. StateHelper.transform(
  34. StateHelper.selectChain(
  35. StateHelper.structure(
  36. StateHelper.getModel(StateHelper.download(b, `https://www.ebi.ac.uk/pdbe/static/entry/${s.pdbId}_updated.cif`), 'cif')),
  37. s.auth_asym_id
  38. ),
  39. s.matrix
  40. )
  41. );
  42. }
  43. return b;
  44. }
  45. export const StaticSuperpositionTestData: SuperpositionTestInput = [
  46. { pdbId: '1aj5', auth_asym_id: 'A', matrix: Mat4.identity() },
  47. { pdbId: '1df0', auth_asym_id: 'B', matrix: Mat4.ofRows(
  48. [[0.406, 0.879, 0.248, -200.633],
  49. [0.693, -0.473, 0.544, 73.403],
  50. [0.596, -0.049, -0.802, -14.209],
  51. [0, 0, 0, 1]] )},
  52. { pdbId: '1dvi', auth_asym_id: 'A', matrix: Mat4.ofRows(
  53. [[-0.053, -0.077, 0.996, -45.633],
  54. [-0.312, 0.949, 0.057, -12.255],
  55. [-0.949, -0.307, -0.074, 53.562],
  56. [0, 0, 0, 1]] )}
  57. ];
  58. export async function dynamicSuperpositionTest(ctx: PluginContext, src: string[], comp_id: string) {
  59. const state = ctx.state.dataState;
  60. const structures = state.build().toRoot();
  61. for (const s of src) {
  62. StateHelper.structure(
  63. StateHelper.getModel(StateHelper.download(structures, `https://www.ebi.ac.uk/pdbe/static/entry/${s}_updated.cif`), 'cif'));
  64. }
  65. await PluginCommands.State.Update.dispatch(ctx, { state, tree: structures });
  66. const pivot = MS.struct.filter.first([
  67. MS.struct.generator.atomGroups({
  68. 'residue-test': MS.core.rel.eq([MS.struct.atomProperty.macromolecular.label_comp_id(), comp_id]),
  69. 'group-by': MS.struct.atomProperty.macromolecular.residueKey()
  70. })
  71. ]);
  72. const rest = MS.struct.modifier.exceptBy({
  73. 0: MS.struct.generator.all(),
  74. by: pivot
  75. });
  76. const query = compile<StructureSelection>(pivot);
  77. const xs = state.select(StateSelection.Generators.rootsOfType(PSO.Molecule.Structure));
  78. const selections = xs.map(s => StructureSelection.toLociWithCurrentUnits(query(new QueryContext(s.obj!.data))));
  79. const transforms = superposeStructures(selections);
  80. const visuals = state.build();
  81. siteVisual(ctx, StateHelper.selectSurroundingsOfFirstResidue(visuals.to(xs[0].transform.ref), 'HEM', 7), pivot, rest);
  82. for (let i = 1; i < selections.length; i++) {
  83. const root = visuals.to(xs[i].transform.ref);
  84. siteVisual(ctx,
  85. StateHelper.transform(StateHelper.selectSurroundingsOfFirstResidue(root, 'HEM', 7), transforms[i - 1].bTransform),
  86. pivot, rest);
  87. }
  88. await PluginCommands.State.Update.dispatch(ctx, { state, tree: visuals });
  89. }
  90. function siteVisual(ctx: PluginContext, b: StateBuilder.To<PSO.Molecule.Structure>, pivot: Expression, rest: Expression) {
  91. StateHelper.ballsAndSticks(ctx, b, pivot, 'residue-name');
  92. StateHelper.ballsAndSticks(ctx, b, rest, 'uniform');
  93. }