Kaynağa Gözat

trajectory preset providers

bioinsilico 3 yıl önce
ebeveyn
işleme
77f3be60c9

+ 1 - 1
examples/local.html

@@ -12,7 +12,7 @@
 <div id="pfv" style="position: absolute" ></div>
 
 <script>
-    const fv = new RcsbFv3D.assembly({config:{entryId:" 7B9F", title: "3D Protein Feature View:  7BAA", subtitle: "Cys-42-tethered stabilizer 12 of 14-3-3(sigma)/ERa PPI"}});
+    const fv = new RcsbFv3D.assembly({config:{entryId:" 2UZI", title: "3D Protein Feature View:  7BAA", subtitle: "Cys-42-tethered stabilizer 12 of 14-3-3(sigma)/ERa PPI"}});
     fv.render();
 </script>
 

+ 3 - 3
package-lock.json

@@ -2089,9 +2089,9 @@
       "integrity": "sha512-FM3y6kfJaj5MCoAjdv24EDCTDbuFz+4+pgAunbjYfugwIE4O/xx8mPNji1n/ouG8pHCntSnBr1xwTOensF23Gg=="
     },
     "@rcsb/rcsb-molstar": {
-      "version": "2.0.0-dev.2",
-      "resolved": "https://registry.npmjs.org/@rcsb/rcsb-molstar/-/rcsb-molstar-2.0.0-dev.2.tgz",
-      "integrity": "sha512-OQNf9WdwvOvsMhKOLYncLiexLDvKfE7Asrki0iWTIakSk4iD832f94D7ij8YUcKRjbJ7bm9gvAbpKeCOjy/q4w=="
+      "version": "2.0.0-dev.3",
+      "resolved": "https://registry.npmjs.org/@rcsb/rcsb-molstar/-/rcsb-molstar-2.0.0-dev.3.tgz",
+      "integrity": "sha512-aqxv+QVtpMOHOFhF/FIqlu6fxwyRLelKHX17Ng6aS+p2dN/28gXQmLk5wWMtrkp/Y9WMhbBr9VyeQTln7McQpw=="
     },
     "@rcsb/rcsb-saguaro": {
       "version": "1.8.0",

+ 2 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "@rcsb/rcsb-saguaro-3d",
-  "version": "0.0.46",
+  "version": "0.0.47",
   "description": "RCSB Molstar/Saguaro Web App",
   "main": "build/dist/RcsbFv3DBuilder.js",
   "files": [
@@ -76,7 +76,7 @@
     "webpack-cli": "^3.3.12"
   },
   "dependencies": {
-    "@rcsb/rcsb-molstar": "^2.0.0-dev.2",
+    "@rcsb/rcsb-molstar": "^2.0.0-dev.3",
     "@rcsb/rcsb-saguaro": "^1.8.0",
     "@rcsb/rcsb-saguaro-app": "^2.0.2",
     "molstar": "^2.0.7",

+ 8 - 6
src/RcsbFv3D/RcsbFv3DAssembly.tsx

@@ -1,5 +1,6 @@
 import {LoadMethod} from "../RcsbFvStructure/StructurePlugins/MolstarPlugin";
 import {RcsbFv3DAbstract, RcsbFv3DAbstractInterface} from "./RcsbFv3DAbstract";
+import {RcsbRepresentationPreset} from "../RcsbFvStructure/StructurePlugins/StructureRepresentation";
 
 export interface RcsbFv3DAssemblyInterface extends RcsbFv3DAbstractInterface {
    config: {
@@ -18,21 +19,22 @@ export class RcsbFv3DAssembly extends RcsbFv3DAbstract{
     init(assemblyData: RcsbFv3DAssemblyInterface) {
         this.elementId = assemblyData.elementId ?? "RcsbFv3D_mainDiv_"+Math.random().toString(36).substr(2);
         this.structureConfig = {
-            loadConfig:{
-                method: LoadMethod.loadPdbId,
-                params: {
+            loadConfig: {
+                loadMethod: LoadMethod.loadPdbId,
+                loadParams: {
                     pdbId:assemblyData.config.entryId,
                     id:assemblyData.config.entryId,
-                    props:{
+                    props: {
                         kind:'standard',
                         assemblyId:'1'
-                    }
+                    },
+                    reprProvider: RcsbRepresentationPreset
                 }
             }
         };
         this.sequenceConfig = {
             type:"assembly",
-            config:{
+            config: {
                 entryId:assemblyData.config.entryId
             },
             title: assemblyData.config.title,

+ 1 - 1
src/RcsbFvContextManager/RcsbFvContextManager.ts

@@ -29,7 +29,7 @@ export class RcsbFvContextManager {
     public next( obj: RcsbFvContextManagerInterface ):void {
         this.subject.next(obj);
     }
-    /**Subscribe method
+    /**Subscribe loadMethod
      * @return Subscription
      * */
     public subscribe(f:(x:RcsbFvContextManagerInterface)=>void):Subscription {

+ 1 - 1
src/RcsbFvSequence/SequenceViews/AssemblyView/AssemblyView.tsx

@@ -315,7 +315,7 @@ function processMultipleGaps(modelId: string, asymId: string, list: Array<RcsbFv
 }
 
 async function createComponents(plugin: SaguaroPluginInterface, modelMap:SaguaroPluginModelMapType): Promise<void> {
-    await plugin.displayComponent("Water", false);
+    plugin.displayComponent("Water", false);
     await plugin.colorComponent("Polymer", 'chain-id');
     const chains: Array<{modelId: string; auth: string; label: string;}> = new Array<{modelId: string; auth: string; label: string;}>();
     modelMap.forEach((entry, modelId)=>{

+ 51 - 63
src/RcsbFvStructure/StructurePlugins/MolstarPlugin.ts

@@ -21,7 +21,7 @@ import {
 import {OrderedSet} from "molstar/lib/mol-data/int";
 import { PluginStateObject as PSO } from 'molstar/lib/mol-plugin-state/objects';
 import {State, StateObject} from "molstar/lib/mol-state";
-import {StructureRef} from "molstar/lib/mol-plugin-state/manager/structure/hierarchy-state";
+import {StructureComponentRef, StructureRef} from "molstar/lib/mol-plugin-state/manager/structure/hierarchy-state";
 import {RcsbFvSelection, ResidueSelectionInterface} from "../../RcsbFvSelection/RcsbFvSelection";
 import {AbstractPlugin} from "./AbstractPlugin";
 import {Subscription} from "rxjs";
@@ -30,6 +30,7 @@ import {MolScriptBuilder} from "molstar/lib/mol-script/language/builder";
 import {SetUtils} from "molstar/lib/mol-util/set";
 import {StructureRepresentationRegistry} from "molstar/lib/mol-repr/structure/registry";
 import {ColorTheme} from "molstar/lib/mol-theme/color";
+import {TrajectoryHierarchyPresetProvider} from "molstar/lib/mol-plugin-state/builder/structure/hierarchy-preset";
 
 export enum LoadMethod {
     loadPdbId = "loadPdbId",
@@ -40,11 +41,11 @@ export enum LoadMethod {
 }
 
 export interface LoadMolstarInterface {
-    method: LoadMethod;
-    params: LoadParams | Array<LoadParams>;
+    loadMethod: LoadMethod;
+    loadParams: LoadParams | Array<LoadParams>;
 }
 
-interface LoadParams {
+interface LoadParams<P=any,S={}> {
     pdbId?: string;
     props?: PresetProps;
     matrix?: Mat4;
@@ -54,6 +55,8 @@ interface LoadParams {
     type?: PluginState.SnapshotType,
     data?: string | number[]
     id?:string;
+    reprProvider?: TrajectoryHierarchyPresetProvider<P,S>;
+    params?:P;
 }
 
 export class MolstarPlugin extends AbstractPlugin implements SaguaroPluginInterface {
@@ -64,8 +67,7 @@ export class MolstarPlugin extends AbstractPlugin implements SaguaroPluginInterf
     private modelChangeCallback: (chainMap:SaguaroPluginModelMapType)=>void;
     private modelChangeCallbackSubs: Subscription;
     private modelMap: Map<string,string|undefined> = new Map<string, string>();
-    private readonly componentSet: Set<string> = new Set<string>();
-    private readonly componentVisibility: Map<string,boolean> = new Map<string, boolean>();
+    private readonly componentMap: Map<string, StructureComponentRef> = new Map<string, StructureComponentRef>();
 
     constructor(props: RcsbFvSelection) {
         super(props);
@@ -82,53 +84,53 @@ export class MolstarPlugin extends AbstractPlugin implements SaguaroPluginInterf
     async load(loadConfig: LoadMolstarInterface): Promise<void>{
         this.loadingFlag = true;
         if(MolstarPlugin.checkLoadData(loadConfig)) {
-            if (loadConfig.method == LoadMethod.loadPdbId) {
-                const config: LoadParams = loadConfig.params as LoadParams;
-                await this.viewer.loadPdbId(config.pdbId!, config.props, config.matrix);
-            } else if (loadConfig.method == LoadMethod.loadPdbIds) {
-                const config: Array<LoadParams> = loadConfig.params as Array<LoadParams>;
+            if (loadConfig.loadMethod == LoadMethod.loadPdbId) {
+                const config: LoadParams = loadConfig.loadParams as LoadParams;
+                await this.viewer.loadPdbId(config.pdbId!, {props: config.props, matrix: config.matrix, reprProvider: config.reprProvider, params: config.params});
+            } else if (loadConfig.loadMethod == LoadMethod.loadPdbIds) {
+                const config: Array<LoadParams> = loadConfig.loadParams as Array<LoadParams>;
                 await this.viewer.loadPdbIds(config.map((d) => {
-                    return {pdbId: d.pdbId!, props: d.props, matrix: d.matrix}
+                    return {pdbId: d.pdbId!, config:{props: d.props, matrix: d.matrix, reprProvider: d.reprProvider, params: d.params}}
                 }));
-            } else if (loadConfig.method == LoadMethod.loadStructureFromUrl) {
-                const config: LoadParams = loadConfig.params as LoadParams;
-                await this.viewer.loadStructureFromUrl(config.url!, config.format!, config.isBinary!);
-            } else if (loadConfig.method == LoadMethod.loadSnapshotFromUrl) {
-                const config: LoadParams = loadConfig.params as LoadParams;
+            } else if (loadConfig.loadMethod == LoadMethod.loadStructureFromUrl) {
+                const config: LoadParams = loadConfig.loadParams as LoadParams;
+                await this.viewer.loadStructureFromUrl(config.url!, config.format!, config.isBinary!,{props: config.props, matrix: config.matrix, reprProvider: config.reprProvider, params: config.params});
+            } else if (loadConfig.loadMethod == LoadMethod.loadSnapshotFromUrl) {
+                const config: LoadParams = loadConfig.loadParams as LoadParams;
                 await this.viewer.loadSnapshotFromUrl(config.url!, config.type!);
-            } else if (loadConfig.method == LoadMethod.loadStructureFromData) {
-                const config: LoadParams = loadConfig.params as LoadParams;
-                await this.viewer.loadStructureFromData(config.data!, config.format!, config.isBinary!);
+            } else if (loadConfig.loadMethod == LoadMethod.loadStructureFromData) {
+                const config: LoadParams = loadConfig.loadParams as LoadParams;
+                await this.viewer.loadStructureFromData(config.data!, config.format!, config.isBinary!, {props: config.props, matrix: config.matrix, reprProvider: config.reprProvider, params: config.params});
             }
         }
         this.viewer.plugin.selectionMode = true;
         this.loadingFlag = false;
-        this.mapModels(loadConfig.params);
+        this.mapModels(loadConfig.loadParams);
         this.modelChangeCallback(this.getChains());
     }
 
     private static checkLoadData(loadConfig: LoadMolstarInterface): boolean{
-        const method: LoadMethod = loadConfig.method;
-        const params: LoadParams | Array<LoadParams> = loadConfig.params;
+        const method: LoadMethod = loadConfig.loadMethod;
+        const params: LoadParams | Array<LoadParams> = loadConfig.loadParams;
         if( method == LoadMethod.loadPdbId ){
             if(params instanceof Array || params.pdbId == null)
-                throw loadConfig.method+": missing pdbId";
+                throw loadConfig.loadMethod+": missing pdbId";
         }else if( method == LoadMethod.loadPdbIds ){
             if(!(params instanceof Array))
-                throw loadConfig.method+": Array object spected";
+                throw loadConfig.loadMethod+": Array object spected";
             for(const d of params){
                 if(d.pdbId == null)
-                    throw loadConfig.method+": missing pdbId"
+                    throw loadConfig.loadMethod+": missing pdbId"
             }
         }else if( method == LoadMethod.loadStructureFromUrl ){
             if(params instanceof Array || params.url == null || params.isBinary == null || params.format == null)
-                throw loadConfig.method+": arguments needed url, format, isBinary"
+                throw loadConfig.loadMethod+": arguments needed url, format, isBinary"
         }else if( method == LoadMethod.loadSnapshotFromUrl ){
             if(params instanceof Array || params.url == null || params.type == null)
-                throw loadConfig.method+": arguments needed url, type"
+                throw loadConfig.loadMethod+": arguments needed url, type"
         }else if( method == LoadMethod.loadStructureFromData ){
             if(params instanceof Array || params.data == null || params.format == null || params.isBinary == null)
-                throw loadConfig.method+": arguments needed data, format, isBinary"
+                throw loadConfig.loadMethod+": arguments needed data, format, isBinary"
         }
         return true;
     }
@@ -225,8 +227,6 @@ export class MolstarPlugin extends AbstractPlugin implements SaguaroPluginInterf
     public async createComponent(componentLabel: string, modelId:string, residues: Array<{asymId: string; begin: number; end: number;}>, representationType: StructureRepresentationRegistry.BuiltIn): Promise<void>;
     public async createComponent(...args: any[]): Promise<void> {
         this.removeComponent(args[0]);
-        this.componentVisibility.set(args[0], true);
-        this.componentSet.add(args[0]);
         if(args.length === 4){
             if( args[2] instanceof Array && args[2].length > 0 ) {
                 if(typeof args[2][0].position === "number"){
@@ -241,6 +241,7 @@ export class MolstarPlugin extends AbstractPlugin implements SaguaroPluginInterf
         else if(args.length === 6){
             await this.viewer.createComponent(args[0], {modelId: this.getModelId(args[1]), labelAsymId: args[2], labelSeqRange:{beg:args[3], end:args[4]}}, args[5]);
         }
+        this.componentMap.set(args[0], this.viewer.plugin.managers.structure.hierarchy.currentComponentGroups[this.viewer.plugin.managers.structure.hierarchy.currentComponentGroups.length-1][0]);
     }
 
     public isComponent(componentLabel: string): boolean{
@@ -281,15 +282,13 @@ export class MolstarPlugin extends AbstractPlugin implements SaguaroPluginInterf
 
     public removeComponent(componentLabel?: string): void{
         if(componentLabel == null){
-            this.componentSet.forEach(id=>{
+            this.componentMap.forEach((comp, id)=>{
                 this.viewer.removeComponent(id);
+                this.componentMap.delete(id);
             })
-            this.componentSet.clear();
-            this.componentVisibility.clear();
         }else{
             this.viewer.removeComponent(componentLabel);
-            this.componentSet.delete(componentLabel);
-            this.componentVisibility.delete(componentLabel);
+            this.componentMap.delete(componentLabel);
         }
     }
 
@@ -302,39 +301,28 @@ export class MolstarPlugin extends AbstractPlugin implements SaguaroPluginInterf
             return this.getComponentDisplay(componentLabel);
     }
     private changeComponentDisplay(componentLabel: string, visibilityFlag: boolean): void{
-        if(this.isComponent(componentLabel) && !this.componentVisibility.has(componentLabel))
-            this.componentVisibility.set(componentLabel, true);
-        if(this.componentVisibility.get(componentLabel) != visibilityFlag) {
+        if(this.componentMap.has(componentLabel) && this.getComponentDisplay(componentLabel) != visibilityFlag) {
+            this.viewer.plugin.managers.structure.component.toggleVisibility([this.componentMap.get(componentLabel)!]);
+        }else if(!this.componentMap.has(componentLabel)){
             for (const c of this.viewer.plugin.managers.structure.hierarchy.currentComponentGroups) {
                 for (const comp of c) {
-                    if (comp.cell.obj?.label === componentLabel) {
-                        if(this.getComponentDisplay(componentLabel) != visibilityFlag)
-                            this.viewer.plugin.managers.structure.component.toggleVisibility([comp]);
-                        return void 0;
+                    if(comp.cell.obj?.label === componentLabel) {
+                        if(!comp.cell.state.isHidden != visibilityFlag) {
+                            this.viewer.plugin.managers.structure.component.toggleVisibility(c);
+                            return void 0;
+                        }
                     }
                 }
             }
         }
     }
-    private getComponentDisplay(componentLabel: string): boolean{
-        for (const c of this.viewer.plugin.managers.structure.hierarchy.currentComponentGroups) {
-            for (const comp of c) {
-                if (comp.cell.obj?.label === componentLabel) {
-                    return this.componentVisibility.get(componentLabel) ?? false;
-                }
-            }
+    private getComponentDisplay(componentLabel: string): boolean | undefined{
+        if(this.componentMap.has(componentLabel)) {
+            return !this.componentMap.get(componentLabel)!.cell.state.isHidden!;
         }
-        return false;
     }
 
     public setRepresentationChangeCallback(g:()=>void){
-        this.viewer.plugin.state.events.cell.stateUpdated.subscribe((o)=>{
-            if(o.cell.obj?.type.name === "Structure" && this.componentSet.has(o.cell.obj?.label)){
-                if(o.cell.state.isHidden != null) {
-                    this.componentVisibility.set(o.cell.obj?.label, !o.cell.state.isHidden);
-                }
-            }
-        });
     }
 
     public setHoverCallback(g:()=>void){
@@ -506,9 +494,9 @@ export class MolstarPlugin extends AbstractPlugin implements SaguaroPluginInterf
 
 }
 
-type ChainType = "polymer"|"water"|"branched"|"non-polymer"|"macrolide";
+export type ChainType = "polymer"|"water"|"branched"|"non-polymer"|"macrolide";
 
-function getStructureOptions(plugin: PluginContext): [string,string][] {
+export function getStructureOptions(plugin: PluginContext): [string,string][] {
     const options: [string, string][] = [];
     plugin.managers.structure.hierarchy.current.structures.forEach(s=>{
         options.push([s.cell.transform.ref, s.cell.obj!.data.label]);
@@ -516,7 +504,7 @@ function getStructureOptions(plugin: PluginContext): [string,string][] {
     return options;
 }
 
-function getChainValues(structure: Structure, modelEntityId: string): [{modelId:string, entryId:string},{auth:string;label:string;entityId:string;title:string;type:ChainType;}[]] {
+export function getChainValues(structure: Structure, modelEntityId: string): [{modelId:string, entryId:string},{auth:string;label:string;entityId:string;title:string;type:ChainType;}[]] {
     const options: {auth:string;label:string;entityId:string;title:string;type:ChainType;}[] = [];
     const l = StructureElement.Location.create(structure);
     const seen = new Set<number>();
@@ -547,13 +535,13 @@ function getStructureWithModelId(structures: StructureRef[], modelId: string): S
     }
 }
 
-function getStructure(ref: string, state: State) {
+export function getStructure(ref: string, state: State) {
     const cell = state.select(ref)[0];
     if (!ref || !cell || !cell.obj) return Structure.Empty;
     return (cell.obj as PSO.Molecule.Structure).data;
 }
 
-function getModelEntityOptions(structure: Structure):[string, string][] {
+export function getModelEntityOptions(structure: Structure):[string, string][] {
     const options: [string, string][] = [];
     const l = StructureElement.Location.create(structure);
     const seen = new Set<string>();

+ 55 - 0
src/RcsbFvStructure/StructurePlugins/StructureRepresentation.ts

@@ -0,0 +1,55 @@
+import {
+    PresetStructureRepresentations,
+    StructureRepresentationPresetProvider
+} from "molstar/lib/mol-plugin-state/builder/structure/representation-preset";
+import {TrajectoryHierarchyPresetProvider} from "molstar/lib/mol-plugin-state/builder/structure/hierarchy-preset";
+import {StateObjectSelector} from "molstar/lib/mol-state";
+import {PluginStateObject} from "molstar/lib/mol-plugin-state/objects";
+import {StateObject} from "molstar/lib/mol-state/object";
+import {StateTransformer} from "molstar/lib/mol-state/transformer";
+
+type StructureObject = StateObjectSelector<PluginStateObject.Molecule.Structure, StateTransformer<StateObject<any, StateObject.Type<any>>, StateObject<any, StateObject.Type<any>>, any>>
+
+export const RcsbRepresentationPreset: TrajectoryHierarchyPresetProvider = TrajectoryHierarchyPresetProvider({
+    id: "rcsb-saguaro-3d",
+    display: {
+        name: 'Feature View 3D'
+    },
+    params: () => ({
+    }),
+    async apply(trajectory, params, plugin) {
+        const builder = plugin.builders.structure;
+        const model = await builder.createModel(trajectory, {modelIndex: 0});
+        const modelProperties = await builder.insertModelProperties(model);
+        const structure: StructureObject = await builder.createStructure(modelProperties);
+        const structureProperties: StructureObject = await builder.insertStructureProperties(structure);
+        const unitcell: StateObjectSelector | undefined = await builder.tryCreateUnitcell(modelProperties, undefined, { isHidden: true });
+        const representation: StructureRepresentationPresetProvider.Result | undefined = await plugin.builders.structure.representation.applyPreset(structureProperties, PresetStructureRepresentations.auto);
+        components:
+        for (const c of plugin.managers.structure.hierarchy.currentComponentGroups) {
+            for (const comp of c) {
+                if(comp.cell.obj?.label === "Water") {
+                    plugin.managers.structure.component.toggleVisibility(c);
+                    break components;
+                }
+            }
+        }
+        components:
+        for (const c of plugin.managers.structure.hierarchy.currentComponentGroups) {
+            for (const comp of c) {
+                if(comp.cell.obj?.label === "Polymer") {
+                    this.viewer.plugin.managers.structure.component.updateRepresentationsTheme([comp], { color: 'chain-id' });
+                    break components;
+                }
+            }
+        }
+        return {
+            model,
+            modelProperties,
+            unitcell,
+            structure,
+            structureProperties,
+            representation
+        };
+    }
+});

+ 2 - 2
src/examples/custom-panel/example.tsx

@@ -173,8 +173,8 @@ const sequenceConfig = {
 
 const structureConfig:RcsbFvStructureInterface = {
     loadConfig: {
-        method: LoadMethod.loadPdbIds,
-        params: [{
+        loadMethod: LoadMethod.loadPdbIds,
+        loadParams: [{
             pdbId: "101m",
             id:"model_1"
         },{

+ 2 - 2
src/examples/multiple-entries/MultipleEntries.tsx

@@ -19,8 +19,8 @@ export class MultipleEntries {
             elementId:"test",
             structurePanelConfig:{
                 loadConfig: {
-                    method: LoadMethod.loadPdbIds,
-                    params: []
+                    loadMethod: LoadMethod.loadPdbIds,
+                    loadParams: []
                 }
             },
             sequencePanelConfig:{