MolstarAlignmentLoader.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Copyright (c) 2021 RCSB PDB and contributors, licensed under MIT, See LICENSE file for more info.
  3. * @author Joan Segura Mora <joan.segura@rcsb.org>
  4. */
  5. import {StructureLoaderInterface} from "./StructureLoaderInterface";
  6. import {ViewerActionManagerInterface, ViewerCallbackManagerInterface} from "../StructureViewerInterface";
  7. import {StructureRef} from "molstar/lib/mol-plugin-state/manager/structure/hierarchy-state";
  8. import {Loci} from "molstar/lib/mol-model/loci";
  9. import {alignAndSuperpose} from "molstar/lib/mol-model/structure/structure/util/superposition";
  10. import {Structure, StructureElement, Unit} from "molstar/lib/mol-model/structure";
  11. import {PluginContext} from "molstar/lib/mol-plugin/context";
  12. import {StateObjectRef} from "molstar/lib/mol-state";
  13. import {Mat4} from "molstar/lib/mol-math/linear-algebra";
  14. import {SymmetryOperator} from "molstar/lib/mol-math/geometry/symmetry-operator";
  15. import {PluginStateObject} from "molstar/lib/mol-plugin-state/objects";
  16. import {StateTransforms} from "molstar/lib/mol-plugin-state/transforms";
  17. import {PluginCommands} from "molstar/lib/mol-plugin/commands";
  18. import {LoadMethod, LoadMolstarInterface} from "../StructureViewers/MolstarViewer/MolstarActionManager";
  19. import {TagDelimiter} from "@rcsb/rcsb-saguaro-app";
  20. const SuperpositionTag = 'SuperpositionTransform';
  21. export class MolstarAlignmentLoader implements StructureLoaderInterface<[ViewerCallbackManagerInterface & ViewerActionManagerInterface <LoadMolstarInterface>,{entryId:string;entityId:string;},{entryId:string;entityId:string;}]> {
  22. private readonly structureMap: Map<string,string|undefined> = new Map<string,string|undefined>();
  23. async load(structureViewer: ViewerCallbackManagerInterface & ViewerActionManagerInterface <LoadMolstarInterface>, ref: {entryId:string;entityId:string;}, pdb:{entryId:string;entityId:string;}): Promise<void> {
  24. const structureId: string = `${pdb.entryId}${TagDelimiter.entity}${pdb.entityId}`;
  25. if(!this.structureMap.has(structureId)){
  26. await structureViewer.load({
  27. loadMethod: LoadMethod.loadPdbId,
  28. loadParams:{
  29. pdbId:pdb.entryId
  30. }
  31. });
  32. structureViewer.pluginCall(async (plugin)=>{
  33. this.structureMap.set(
  34. structureId,
  35. plugin.managers.structure.hierarchy.current.structures[ plugin.managers.structure.hierarchy.current.structures.length -1].properties?.cell?.obj?.data?.units[0]?.model?.id
  36. );
  37. });
  38. } else {
  39. structureViewer.pluginCall(async (plugin)=>{
  40. const pdbStr: StructureRef|undefined = plugin.managers.structure.hierarchy.current.structures.find(s=>s.properties?.cell?.obj?.data?.units[0]?.model?.id == this.structureMap.get(structureId));
  41. if(pdbStr) {
  42. plugin.managers.structure.hierarchy.remove([pdbStr]);
  43. this.structureMap.delete(structureId);
  44. await PluginCommands.Camera.Reset(plugin);
  45. }
  46. });
  47. return;
  48. }
  49. if(ref.entryId != pdb.entryId)
  50. structureViewer.pluginCall(async (plugin)=>{
  51. const pdbId: string = `${pdb.entryId}${TagDelimiter.entity}${pdb.entityId}`;
  52. const refId: string = `${ref.entryId}${TagDelimiter.entity}${ref.entityId}`;
  53. const refStr: StructureRef|undefined = plugin.managers.structure.hierarchy.current.structures.find(s=>s.properties?.cell?.obj?.data?.units[0]?.model?.id == this.structureMap.get(refId));
  54. const pdbStr: StructureRef|undefined = plugin.managers.structure.hierarchy.current.structures.find(s=>s.properties?.cell?.obj?.data?.units[0]?.model?.id == this.structureMap.get(pdbId));
  55. if(refStr && pdbStr){
  56. const refData: Structure|undefined = refStr.properties?.cell.obj?.data;
  57. const pdbData: Structure|undefined = pdbStr.properties?.cell.obj?.data;
  58. const pdbUnit:Unit|undefined = pdbData?.units.find((u,n)=>u.model.atomicHierarchy.chains.label_entity_id.value(n) === pdb.entityId);
  59. const refUnit:Unit|undefined = refData?.units.find((u,n)=>u.model.atomicHierarchy.chains.label_entity_id.value(n) === ref.entityId);
  60. if(pdbData && pdbUnit && refData && refUnit){
  61. const refLoci: Loci = Structure.toStructureElementLoci(Structure.create([refUnit]));
  62. const pdbLoci: Loci = Structure.toStructureElementLoci(Structure.create([pdbUnit]));
  63. if(StructureElement.Loci.is(refLoci) && StructureElement.Loci.is(pdbLoci)) {
  64. const pivot = plugin.managers.structure.hierarchy.findStructure(refLoci.structure);
  65. const coordinateSystem = pivot?.transform?.cell.obj?.data.coordinateSystem;
  66. const transforms = alignAndSuperpose([refLoci, pdbLoci]);
  67. const { bTransform } = transforms[0];
  68. await this.transform(plugin, plugin.helpers.substructureParent.get(pdbData)!, bTransform, coordinateSystem);
  69. await PluginCommands.Camera.Reset(plugin);
  70. }
  71. }
  72. }
  73. });
  74. }
  75. private async transform(plugin:PluginContext, s: StateObjectRef<PluginStateObject.Molecule.Structure>, matrix: Mat4, coordinateSystem?: SymmetryOperator) {
  76. const r = StateObjectRef.resolveAndCheck(plugin.state.data, s);
  77. if (!r) return;
  78. const o = plugin.state.data.selectQ(q => q.byRef(r.transform.ref).subtree().withTransformer(StateTransforms.Model.TransformStructureConformation))[0];
  79. const transform = coordinateSystem && !Mat4.isIdentity(coordinateSystem.matrix)
  80. ? Mat4.mul(Mat4(), coordinateSystem.matrix, matrix)
  81. : matrix;
  82. const params = {
  83. transform: {
  84. name: 'matrix' as const,
  85. params: { data: transform, transpose: false }
  86. }
  87. };
  88. const b = o
  89. ? plugin.state.data.build().to(o).update(params)
  90. : plugin.state.data.build().to(s)
  91. .insert(StateTransforms.Model.TransformStructureConformation, params, { tags: SuperpositionTag });
  92. await plugin.runTask(plugin.state.data.updateTree(b));
  93. }
  94. }