@@ -5,9 +5,16 @@ import { MVSData } from 'molstar/lib/extensions/mvs/mvs-data';
5
5
import { MolstarSubtree } from 'molstar/lib/extensions/mvs/tree/molstar/molstar-tree' ;
6
6
import { ColorT } from 'molstar/lib/extensions/mvs/tree/mvs/param-types' ;
7
7
import { ShapeRepresentation3D } from 'molstar/lib/mol-plugin-state/transforms/representation' ;
8
- import { AnyColor } from 'src/app/spec' ;
9
8
import { PDBeMolstarPlugin } from '../..' ;
10
9
import { QueryParam , queryParamsToMvsComponentExpressions } from '../../helpers' ;
10
+ import { ExtensionCustomState } from '../../plugin-custom-state' ;
11
+ import { AnyColor } from '../../spec' ;
12
+ import { getInteractionApiData , interactionsFromApiData } from './api' ;
13
+
14
+
15
+ /** Name used when registering extension, custom state, etc. */
16
+ const InteractionsExtensionName = 'pdbe-custom-interactions' ;
17
+ const getExtensionCustomState = ExtensionCustomState . getter < { visuals : StateObjectHandle [ ] } > ( InteractionsExtensionName ) ;
11
18
12
19
13
20
export interface Interaction {
@@ -17,46 +24,55 @@ export interface Interaction {
17
24
tooltip ?: string ,
18
25
}
19
26
20
- const dummyData : Interaction [ ] = [
21
- {
22
- start : { auth_asym_id : 'A' , auth_seq_id : 45 , atoms : [ 'CA' ] } ,
23
- end : { auth_asym_id : 'A' , auth_seq_id : 50 , atoms : [ 'CA' ] } ,
24
- color : 'yellow' ,
25
- tooltip : '<b>Hydrophobic interaction</b><br/> GLN 45 | CA — PHE 50 | CA' ,
26
- } ,
27
- {
28
- start : { auth_asym_id : 'A' , auth_seq_id : 50 , atoms : [ 'CA' ] } ,
29
- end : { auth_asym_id : 'A' , auth_seq_id : 65 , atoms : [ 'CA' ] } ,
30
- color : 'red' ,
31
- tooltip : '<b>Ion interaction</b><br/> PHE 50 | CA — PHE 65 | CA' ,
32
- } ,
33
- ] ;
27
+ export interface StateObjectHandle {
28
+ /** State transform reference */
29
+ ref : string ,
30
+ /** Remove state object from state hierarchy */
31
+ delete : ( ) => Promise < void > ,
32
+ }
33
+
34
+ export function loadInteractions_example ( viewer : PDBeMolstarPlugin ) {
35
+ return loadInteractions ( viewer , { interactions : exampleData } ) ;
36
+ }
34
37
35
- export function foo ( viewer : PDBeMolstarPlugin ) {
36
- return loadInteractions ( viewer , { interactions : dummyData } ) ;
38
+ export async function loadInteractionsFromApi ( viewer : PDBeMolstarPlugin , params : { pdbId : string , authAsymId : string , authSeqId : number , structureId ?: string } ) {
39
+ const data = await getInteractionApiData ( { ...params , pdbeBaseUrl : viewer . initParams . pdbeUrl } ) ;
40
+ const interactions = interactionsFromApiData ( data , params . pdbId ) ;
41
+ await loadInteractions ( viewer , { interactions, structureId : params . structureId } ) ;
37
42
}
38
43
39
44
/** Show custom atom interactions */
40
- export async function loadInteractions ( viewer : PDBeMolstarPlugin , params : { interactions : Interaction [ ] , structureId ?: string } ) {
45
+ export async function loadInteractions ( viewer : PDBeMolstarPlugin , params : { interactions : Interaction [ ] , structureId ?: string } ) : Promise < StateObjectHandle > {
41
46
const structureId = params . structureId ?? PDBeMolstarPlugin . MAIN_STRUCTURE_ID ;
42
47
const struct = viewer . getStructure ( structureId ) ;
43
48
if ( ! struct ) throw new Error ( `Did not find structure with ID "${ structureId } "` ) ;
44
49
45
50
const primitivesMvsNode = interactionsToMvsPrimitiveData ( params . interactions ) ;
46
51
47
52
const update = viewer . plugin . build ( ) ;
48
- const data = update . to ( struct . cell ) . apply ( MVSInlinePrimitiveData , { node : primitivesMvsNode as any } ) ; // TODO tags
49
- data . apply ( MVSBuildPrimitiveShape , { kind : 'mesh' } ) . apply ( ShapeRepresentation3D ) ;
50
- data . apply ( MVSBuildPrimitiveShape , { kind : 'lines' } ) . apply ( ShapeRepresentation3D ) ;
51
- data . apply ( MVSBuildPrimitiveShape , { kind : 'labels' } ) . apply ( ShapeRepresentation3D ) ; // TODO tags
53
+ const data = update . to ( struct . cell ) . apply ( MVSInlinePrimitiveData , { node : primitivesMvsNode as any } , { tags : [ 'custom-interactions-data' ] } ) ;
54
+ data . apply ( MVSBuildPrimitiveShape , { kind : 'mesh' } ) . apply ( ShapeRepresentation3D , { } , { tags : [ 'custom-interactions-mesh' ] } ) ;
55
+ data . apply ( MVSBuildPrimitiveShape , { kind : 'lines' } ) . apply ( ShapeRepresentation3D , { } , { tags : [ 'custom-interactions-lines' ] } ) ;
56
+ data . apply ( MVSBuildPrimitiveShape , { kind : 'labels' } ) . apply ( ShapeRepresentation3D , { } , { tags : [ 'custom-interactions-labels' ] } ) ;
52
57
await update . commit ( ) ;
53
58
54
- return {
59
+ const visual : StateObjectHandle = {
55
60
ref : data . ref ,
56
- delete ( ) : Promise < void > {
57
- return viewer . plugin . build ( ) . delete ( data . ref ) . commit ( ) ;
58
- } ,
61
+ delete : ( ) => viewer . plugin . build ( ) . delete ( data . ref ) . commit ( ) ,
59
62
} ;
63
+ const visualsList = getExtensionCustomState ( viewer . plugin ) . visuals ??= [ ] ;
64
+ visualsList . push ( visual ) ;
65
+ return visual ;
66
+ }
67
+
68
+ /** Remove any previously added interactions */
69
+ export async function clearInteractions ( viewer : PDBeMolstarPlugin ) : Promise < void > {
70
+ const visuals = getExtensionCustomState ( viewer . plugin ) . visuals ;
71
+ if ( ! visuals ) return ;
72
+ for ( const visual of visuals ) {
73
+ await visual . delete ( ) ;
74
+ }
75
+ visuals . length = 0 ;
60
76
}
61
77
62
78
function interactionsToMvsPrimitiveData ( interactions : Interaction [ ] ) : MolstarSubtree < 'primitives' > {
@@ -67,25 +83,42 @@ function interactionsToMvsPrimitiveData(interactions: Interaction[]): MolstarSub
67
83
primitives . tube ( {
68
84
start : { expressions : queryParamsToMvsComponentExpressions ( [ interaction . start ] ) } ,
69
85
end : { expressions : queryParamsToMvsComponentExpressions ( [ interaction . end ] ) } ,
70
- radius : 0.1 ,
86
+ radius : 0.075 ,
71
87
dash_length : 0.1 ,
72
88
color : interaction . color as ColorT ,
73
89
tooltip : interaction . tooltip ,
74
90
} ) ;
75
91
}
76
- // use primitives.distance to add labels to tubes
77
- // primitives.distance({
78
- // start: { auth_asym_id: 'A', auth_seq_id: 50, auth_atom_id: 'CA' },
79
- // end: { auth_asym_id: 'A', auth_seq_id: 65, auth_atom_id: 'CA' },
80
- // radius: 0.1,
81
- // dash_length: 0.1,
82
- // color: 'yellow',
83
- // label_template: 'hydrophobic',
84
- // label_color: 'yellow',
85
- // label_size: 0.5,
86
- // });
87
92
const state = builder . getState ( ) ;
88
93
const primitivesNode = state . root . children ?. find ( child => child . kind === 'primitives' ) as MolstarSubtree < 'primitives' > | undefined ;
89
94
if ( ! primitivesNode ) throw new Error ( 'AssertionError: Failed to create MVS "primitives" subtree.' ) ;
90
95
return primitivesNode ;
91
96
}
97
+
98
+ /** Selected interactions from https://www.ebi.ac.uk/pdbe/graph-api/pdb/bound_ligand_interactions/1hda/C/143 */
99
+ const exampleData = [
100
+ {
101
+ 'start' : { 'auth_asym_id' : 'C' , 'auth_seq_id' : 143 , 'atoms' : [ 'CBC' ] } ,
102
+ 'end' : { 'auth_asym_id' : 'C' , 'auth_seq_id' : 32 , 'atoms' : [ 'CE' ] } ,
103
+ 'color' : 'yellow' ,
104
+ 'tooltip' : '<strong>Hydrophobic interaction</strong><br>HEM 143 | CBC — MET 32 | CE' ,
105
+ } ,
106
+ {
107
+ 'start' : { 'auth_asym_id' : 'C' , 'auth_seq_id' : 143 , 'atoms' : [ 'CBC' ] } ,
108
+ 'end' : { 'auth_asym_id' : 'C' , 'auth_seq_id' : 32 , 'atoms' : [ 'SD' ] } ,
109
+ 'color' : 'yellow' ,
110
+ 'tooltip' : '<strong>Hydrophobic interaction</strong><br>HEM 143 | CBC — MET 32 | SD' ,
111
+ } ,
112
+ {
113
+ 'start' : { 'auth_asym_id' : 'C' , 'auth_seq_id' : 143 , 'atoms' : [ 'CMD' ] } ,
114
+ 'end' : { 'auth_asym_id' : 'C' , 'auth_seq_id' : 42 , 'atoms' : [ 'O' ] } ,
115
+ 'color' : 'gray' ,
116
+ 'tooltip' : '<strong>Mixed interaction</strong><br>Vdw, Weak polar<br>HEM 143 | CMD — TYR 42 | O' ,
117
+ } ,
118
+ {
119
+ 'start' : { 'auth_asym_id' : 'C' , 'auth_seq_id' : 143 , 'atoms' : [ 'C1B' , 'C2B' , 'C3B' , 'C4B' , 'NB' ] } ,
120
+ 'end' : { 'auth_asym_id' : 'C' , 'auth_seq_id' : 136 , 'atoms' : [ 'CD1' ] } ,
121
+ 'color' : 'magenta' ,
122
+ 'tooltip' : '<strong>CARBONPI interaction</strong><br>HEM 143 | C1B, C2B, C3B, C4B, NB — LEU 136 | CD1' ,
123
+ } ,
124
+ ] ;
0 commit comments