Quellcode durchsuchen

Issue #805: added unitmp-specific utils; separated FvConfig

cycle20 vor 1 Jahr
Ursprung
Commit
fd4d1b8473

+ 106 - 0
src/examples/assembly-tm/FeatureViewConfig.ts

@@ -0,0 +1,106 @@
+import { FeatureViewInterface } from "../../RcsbFvSequence/SequenceViews/CustomView/CustomView";
+import {
+    RcsbFv,
+    RcsbFvDisplayTypes,
+    RcsbFvRowConfigInterface,
+    RcsbFvTrackDataElementInterface
+} from "@rcsb/rcsb-saguaro";
+import { RegionSelectionInterface } from "../../RcsbFvState/RcsbFvSelectorManager";
+import {
+    StructureViewerPublicInterface, SaguaroRegionList
+} from "../../RcsbFvStructure/StructureViewerInterface";
+import {
+    LoadMolstarInterface, LoadMolstarReturnType
+} from "../../RcsbFvStructure/StructureViewers/MolstarViewer/MolstarActionManager";
+import {RcsbFvStateManager} from "../../RcsbFvState/RcsbFvStateManager";
+
+export const rowConfig: Array<RcsbFvRowConfigInterface> = [
+    {
+        trackId: "sequenceTrack",
+        trackHeight: 20,
+        trackColor: "#F9F9F9",
+        displayType: RcsbFvDisplayTypes.SEQUENCE,
+        nonEmptyDisplay: true,
+        rowTitle: "1ASH SEQUENCE",
+        trackData: [
+            {
+                begin: 1,
+                value: "ANKTRELCMKSLEHAKVDTSNEARQDGIDLYKHMFENYPPLRKYFKSREEYTAEDVQNDPFFAKQGQKILLACHVLCATYDDRETFNAYTRELLDRHARDHVHMPPEVWTDFWKLFEEYLGKKTTLDEPTKQAWHEIGREFAKEINKHGR"
+            }
+        ]
+    },{
+        trackId: "blockTrack",
+        trackHeight: 20,
+        trackColor: "#F9F9F9",
+        displayType: RcsbFvDisplayTypes.BLOCK,
+        displayColor: "#FF0000",
+        rowTitle: "1ASH",
+        trackData: [{
+            begin: 30,
+            end: 60
+        }]
+    }
+];
+
+export const fvConfig: FeatureViewInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType> = {
+    boardId:"1ash_board",
+    boardConfig: {
+        range: {
+            min: 1,
+            max: 150
+        },
+        rowTitleWidth: 190,
+        includeAxis: true
+    },
+    rowConfig: rowConfig,
+    sequenceSelectionChangeCallback: (plugin: StructureViewerPublicInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType>, stateManager: RcsbFvStateManager, sequenceRegion: Array<RcsbFvTrackDataElementInterface>) => {
+        stateManager.selectionState.clearSelection("select", {modelId:"1ash_model", labelAsymId:"A"});
+        if(sequenceRegion.length > 0) {
+            const regions = sequenceRegion.map(r => ({
+                modelId: "1ash_model",
+                labelAsymId: "A",
+                region: {begin: r.begin, end: r.end ?? r.begin, source: "sequence"} as RegionSelectionInterface
+            }));
+            stateManager.selectionState.addSelectionFromMultipleRegions(regions, "select");
+            plugin.select(regions.map(r => ({
+                ...r,
+                begin: r.region.begin,
+                end: r.region.end
+            })), "select", "set");
+        }else{
+            plugin.clearSelection("select", {modelId: "1ash_model", labelAsymId: "A"})
+            plugin.resetCamera();
+        }
+    },
+    sequenceElementClickCallback: (plugin: StructureViewerPublicInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType>, stateManager: RcsbFvStateManager, d: RcsbFvTrackDataElementInterface) => {
+        if(d!=null)
+            plugin.cameraFocus("1ash_model", "A", d.begin, d.end ?? d.begin);
+    },
+    sequenceHoverCallback: (plugin: StructureViewerPublicInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType>, stateManager: RcsbFvStateManager, elements: Array<RcsbFvTrackDataElementInterface>) => {
+        if(elements == null || elements.length == 0)
+            plugin.clearSelection("hover");
+        else
+            plugin.select(elements.map(e=>({
+                modelId: "1ash_model",
+                labelAsymId: "A",
+                begin: e.begin,
+                end: e.end ?? e.begin
+            })), "hover", "set");
+    },
+    structureSelectionCallback: (plugin: StructureViewerPublicInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType>, pfv: RcsbFv, stateManager: RcsbFvStateManager) => {
+        const sel: SaguaroRegionList | undefined = stateManager.selectionState.getSelectionWithCondition("1ash_model", "A", "select");
+        if(sel == null) {
+            pfv.clearSelection("select");
+            plugin.resetCamera();
+        }else {
+            pfv.setSelection({elements: sel.regions, mode: "select"});
+        }
+    },
+    structureHoverCallback: (plugin: StructureViewerPublicInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType>, pfv: RcsbFv, stateManager: RcsbFvStateManager) => {
+        const sel: SaguaroRegionList | undefined = stateManager.selectionState.getSelectionWithCondition("1ash_model", "A", "hover");
+        if(sel == null)
+            pfv.clearSelection("hover");
+        else
+            pfv.setSelection({elements:sel.regions, mode:"hover"});
+    }
+}

+ 130 - 0
src/examples/assembly-tm/UniTmpColor.ts

@@ -0,0 +1,130 @@
+enum SiteIndexes {
+    Side1 = 0,
+    Side2 = 1,
+    TmAlpha = 2,
+    TmBeta = 3,
+    TmReentrantLoop = 4,
+    InterfacialHelix = 5,
+    UnknownLocalization = 6,
+    MembraneInside = 7,
+    Periplasm = 8
+};
+
+// Old default values - it is overwritten by ult_* CSS classes
+// See below updateSiteColors().
+const siteColors = [
+    'rgb(255,100,100)', // Side1
+    'rgb(100,100,255)', // Side2
+    'rgb(255,255,  0)', // TM alpha
+    'rgb(255,255,  0)', // TM beta
+    'rgb(255,127,  0)', // TM re-entrant loop
+    'rgb(0,255,    0)', // Interfacial Helix
+    'rgb(196,196,196)', // Unknow localization
+    'rgb(0,255,    0)', // Membrane Inside
+    'rgb(255, 0, 255)'  // Periplasm
+];
+
+const siteCssNames = [
+    "ult_side1",
+    "ult_side2",
+    "ult_alpha",
+    "ult_beta",
+    "ult_reentrant",
+    "ult_ifh",
+    "ult_unknown",
+    "ult_membins",
+    "ult_periplasm"
+];
+
+const locationCssMap = {
+    '1': { css: 'ult_side1', label: "Side1" },
+    '2': { css: 'ult_side2', label: "Side2" },
+    'B': { css: 'ult_beta', label: "Beta" },
+    'C': { css: 'ult_coil', label: "Coil" },
+    'F': { css: 'ult_ifh', label: "Interfacial helix" },
+    'H': { css: 'ult_alpha', label: "Alpha" },
+    'N': { css: 'ult_mebins', label: "Membins" },
+    'L': { css: 'ult_reentrant', label: "Re-entrant loop" },
+    'U': { css: 'ult_unknown', label: "Unknown" },
+    'M': { css: 'ult_membrane', label: "Membrane" },
+    'I': { css: 'ult_inside', label: "Inside" },
+    'O': { css: 'ult_outside', label: "Outside" },
+    'Q': { css: 'ult_not_inside', label: "Not Inside" },
+    'J': { css: 'ult_not_outside', label: "Not Outside" },
+    'W': { css: 'ult_not_membrane', label: "Not Membrane" },
+    'S': { css: 'ult_signal', label: "Signal" },
+    'P': { css: 'ult_propeptide', label: "Propeptide" },
+    'T': { css: 'ult_transit', label: "Transit" },
+    'K': { css: 'ult_cleavable', label: "Cleavable" },
+    'D': { css: 'ult_domain', label: "Domain" },
+    'E': { css: 'ult_periplasm', label: "Periplasm" }
+} as any;
+
+
+const regionColorMapFromCss = new Map();
+
+export function getColorByCssClass(cssClass: string): string {
+    return regionColorMapFromCss.get(cssClass);
+}
+
+export function getColorByLocation(location: string): string {
+    return getColorByCssClass(locationCssMap[location].css);
+}
+
+export function getLabelByLocation(location: string): string {
+    return locationCssMap[location].label;
+}
+
+function loadRegionColorsFromStyleSheets(prefix: string = 'ult_'): void {
+    const sheets: CSSStyleSheet[] = Array.from(document.styleSheets);
+    sheets.forEach((sheet: CSSStyleSheet) => {
+        const rules: CSSRule[] = Array.from(sheet.cssRules);
+        rules.forEach((rule: CSSRule) => fetchRule(rule, prefix));
+    });
+}
+
+export function updateSiteColors(side1: "Inside"|"Outside"|null): void {
+    if (!side1) {
+        return;
+    }
+    loadRegionColorsFromStyleSheets();
+    if (regionColorMapFromCss.size == 0) {
+        console.warn('Cannot read any region-related color rules');
+    }
+
+    siteCssNames.forEach((ultClassName, index) => {
+        const color = regionColorMapFromCss.get(ultClassName);
+        if (color != null) {
+            siteColors[index] = color;
+        }
+    });
+
+    const inside = regionColorMapFromCss.get("ult_inside");
+    const outside = regionColorMapFromCss.get("ult_outside");
+    if (side1 == "Inside") {
+        siteColors[SiteIndexes.Side1] = inside;
+        siteColors[SiteIndexes.Side2] = outside;
+    } else if (side1 == "Outside") {
+        siteColors[SiteIndexes.Side1] = outside;
+        siteColors[SiteIndexes.Side2] = inside;
+    }
+}
+
+function fetchRule(rule: CSSRule, prefix: string) {
+    let styleRule = rule as CSSStyleRule;
+    if (styleRule.selectorText?.startsWith('.' + prefix)) {
+        const value = styleRule.style.getPropertyValue('fill');
+        const color: any = getStyleColor(value);
+        const key = styleRule.selectorText.slice(1);
+        regionColorMapFromCss.set(key, color);
+    }
+}
+
+function getStyleColor(cssColorText: string): any {
+    const values = cssColorText?.match(/\d+/g);
+    let intValues = values?.map(value => parseInt(value));
+    if (!intValues) {
+        intValues = [ 0, 0, 0 ];
+    }
+    return `rgb(${intValues[0]}, ${intValues[1]}, ${intValues[2]})`;
+}

+ 51 - 0
src/examples/assembly-tm/UniTmpHelper.ts

@@ -0,0 +1,51 @@
+import { RcsbFvDisplayTypes } from "@rcsb/rcsb-saguaro";
+
+import { getColorByLocation, getLabelByLocation } from "./UniTmpColor";
+
+export async function fetchDescriptor(entryId: string) {
+    const response = await fetch(`https://htp.unitmp.org/api/v1/entry/${entryId}.json`);
+    const descriptor = await response.json();
+    return descriptor;
+}
+
+export function descriptorChainToTrackData(descriptor: any) {
+    const tracks = [] as any[];
+    descriptor.Predictions.Prediction.forEach((prediction: any) => {
+        const trackData = {
+            trackHeight: 20,
+            trackColor: "#F9F9F9",
+            displayType: RcsbFvDisplayTypes.COMPOSITE,
+            rowTitle: prediction['@attributes'].name,
+            displayConfig: [] as any[]
+        };
+        tracks.push(trackData);
+
+        if (!Array.isArray(prediction.Region)) {
+            return;
+        }
+
+        prediction.Region.forEach((region: any) => {
+            trackData.displayConfig.push(createDisplayItem({
+                begin: parseInt(region['@attributes'].from),
+                end: parseInt(region['@attributes'].to),
+                location: region['@attributes'].loc
+            }));    
+        });
+    });
+
+    console.log(tracks);
+    return tracks;
+}
+
+function createDisplayItem(params: any) {
+    return {
+        displayType: RcsbFvDisplayTypes.BLOCK,
+        displayColor: getColorByLocation(params.location),
+        displayId: `${params.begin}_${params.end}_${params.location}`,
+        displayData: [{
+            begin: params.begin,
+            end: params.end,
+            name: getLabelByLocation(params.location)
+        }]
+    };
+}

+ 16 - 106
src/examples/assembly-tm/index.ts

@@ -2,119 +2,18 @@ import {RcsbFv3DCustom} from "../../RcsbFv3D/RcsbFv3DCustom";
 import {RcsbFvStructureConfigInterface} from "../../RcsbFvStructure/RcsbFvStructure";
 import {
     CustomViewInterface,
-    FeatureBlockInterface, FeatureViewInterface
+    FeatureBlockInterface
 } from "../../RcsbFvSequence/SequenceViews/CustomView/CustomView";
-import * as React from "react";
-import {
-    RcsbFv,
-    RcsbFvDisplayTypes,
-    RcsbFvRowConfigInterface,
-    RcsbFvTrackDataElementInterface
-} from "@rcsb/rcsb-saguaro";
-import {
-    RcsbFvSelectorManager,
-    RegionSelectionInterface
-} from "../../RcsbFvState/RcsbFvSelectorManager";
-import {
-    StructureViewerPublicInterface, SaguaroRegionList
-} from "../../RcsbFvStructure/StructureViewerInterface";
 import {
     LoadMethod,
     LoadMolstarInterface, LoadMolstarReturnType
 } from "../../RcsbFvStructure/StructureViewers/MolstarViewer/MolstarActionManager";
 import {ViewerProps} from "@rcsb/rcsb-molstar/build/src/viewer";
-import {RcsbFvStateManager} from "../../RcsbFvState/RcsbFvStateManager";
 
-const rowConfig: Array<RcsbFvRowConfigInterface> = [
-    {
-        trackId: "sequenceTrack",
-        trackHeight: 20,
-        trackColor: "#F9F9F9",
-        displayType: RcsbFvDisplayTypes.SEQUENCE,
-        nonEmptyDisplay: true,
-        rowTitle: "1ASH SEQUENCE",
-        trackData: [
-            {
-                begin: 1,
-                value: "ANKTRELCMKSLEHAKVDTSNEARQDGIDLYKHMFENYPPLRKYFKSREEYTAEDVQNDPFFAKQGQKILLACHVLCATYDDRETFNAYTRELLDRHARDHVHMPPEVWTDFWKLFEEYLGKKTTLDEPTKQAWHEIGREFAKEINKHGR"
-            }
-        ]
-    },{
-        trackId: "blockTrack",
-        trackHeight: 20,
-        trackColor: "#F9F9F9",
-        displayType: RcsbFvDisplayTypes.BLOCK,
-        displayColor: "#FF0000",
-        rowTitle: "1ASH",
-        trackData: [{
-            begin: 30,
-            end: 60
-        }]
-    }
-];
+import { descriptorChainToTrackData, fetchDescriptor } from "./UniTmpHelper";
+import { updateSiteColors } from "./UniTmpColor";
+import { fvConfig, rowConfig } from "./FeatureViewConfig";
 
-const fvConfig: FeatureViewInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType> = {
-    boardId:"1ash_board",
-    boardConfig: {
-        range: {
-            min: 1,
-            max: 150
-        },
-        rowTitleWidth: 190,
-        includeAxis: true
-    },
-    rowConfig: rowConfig,
-    sequenceSelectionChangeCallback: (plugin: StructureViewerPublicInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType>, stateManager: RcsbFvStateManager, sequenceRegion: Array<RcsbFvTrackDataElementInterface>) => {
-        stateManager.selectionState.clearSelection("select", {modelId:"1ash_model", labelAsymId:"A"});
-        if(sequenceRegion.length > 0) {
-            const regions = sequenceRegion.map(r => ({
-                modelId: "1ash_model",
-                labelAsymId: "A",
-                region: {begin: r.begin, end: r.end ?? r.begin, source: "sequence"} as RegionSelectionInterface
-            }));
-            stateManager.selectionState.addSelectionFromMultipleRegions(regions, "select");
-            plugin.select(regions.map(r => ({
-                ...r,
-                begin: r.region.begin,
-                end: r.region.end
-            })), "select", "set");
-        }else{
-            plugin.clearSelection("select", {modelId: "1ash_model", labelAsymId: "A"})
-            plugin.resetCamera();
-        }
-    },
-    sequenceElementClickCallback: (plugin: StructureViewerPublicInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType>, stateManager: RcsbFvStateManager, d: RcsbFvTrackDataElementInterface) => {
-        if(d!=null)
-            plugin.cameraFocus("1ash_model", "A", d.begin, d.end ?? d.begin);
-    },
-    sequenceHoverCallback: (plugin: StructureViewerPublicInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType>, stateManager: RcsbFvStateManager, elements: Array<RcsbFvTrackDataElementInterface>) => {
-        if(elements == null || elements.length == 0)
-            plugin.clearSelection("hover");
-        else
-            plugin.select(elements.map(e=>({
-                modelId: "1ash_model",
-                labelAsymId: "A",
-                begin: e.begin,
-                end: e.end ?? e.begin
-            })), "hover", "set");
-    },
-    structureSelectionCallback: (plugin: StructureViewerPublicInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType>, pfv: RcsbFv, stateManager: RcsbFvStateManager) => {
-        const sel: SaguaroRegionList | undefined = stateManager.selectionState.getSelectionWithCondition("1ash_model", "A", "select");
-        if(sel == null) {
-            pfv.clearSelection("select");
-            plugin.resetCamera();
-        }else {
-            pfv.setSelection({elements: sel.regions, mode: "select"});
-        }
-    },
-    structureHoverCallback: (plugin: StructureViewerPublicInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType>, pfv: RcsbFv, stateManager: RcsbFvStateManager) => {
-        const sel: SaguaroRegionList | undefined = stateManager.selectionState.getSelectionWithCondition("1ash_model", "A", "hover");
-        if(sel == null)
-            pfv.clearSelection("hover");
-        else
-            pfv.setSelection({elements:sel.regions, mode:"hover"});
-    }
-}
 
 const block: FeatureBlockInterface<LoadMolstarInterface<unknown,unknown>,LoadMolstarReturnType> = {
     blockId:"MyBlock_1",
@@ -147,7 +46,18 @@ const molstarConfig: RcsbFvStructureConfigInterface<LoadMolstarInterface<unknown
     }
 };
 
-document.addEventListener("DOMContentLoaded", function(event) {
+document.addEventListener("DOMContentLoaded", async function(event) {
+    updateSiteColors("Inside");
+    const descriptor = await fetchDescriptor("SC5AA_HUMAN");
+
+    let sequence = descriptor.Sequence.Seq;
+    sequence = sequence.replace(/\s+/g, '');
+
+    //sequenceConfig.config.blockConfig[0].featureViewConfig[0] = `${result['@attributes'].id} sequence`;
+    rowConfig[0].trackData![0].value = sequence;
+    rowConfig.push(...descriptorChainToTrackData(descriptor));
+
+
     const panel3d = new RcsbFv3DCustom({
         elementId: "null",
         structurePanelConfig: molstarConfig,

+ 23 - 0
src/examples/html-template/index.html

@@ -4,6 +4,29 @@
     <meta charset="UTF-8">
     <title>RCSB PDB 1D3D Viewer</title>
 </head>
+<style>
+    .ult_side1 { fill: #f88; }
+    .ult_side2 { fill: #88f; }
+    .ult_beta { fill: #ff0; }
+    .ult_coil { fill: #ff0; }
+    .ult_ifh { fill: #0f0; }
+    .ult_alpha { fill: #ff0; }
+    .ult_mebins { fill: #f0f; }
+    .ult_reentrant { fill: #f80; }
+    .ult_unknown { fill: #aaa; }
+    .ult_membrane { fill: #ff0; }
+    .ult_inside { fill: #f00; }
+    .ult_outside { fill: #00f; }
+    .ult_not_inside { fill: #08f; }
+    .ult_not_outside { fill: #f04; }
+    .ult_not_membrane { fill: #f0f; }
+    .ult_signal { fill: #000; }
+    .ult_propeptide { fill: #000; }
+    .ult_transit { fill: #000; }
+    .ult_cleavable { fill: #000; }
+    .ult_domain { fill: #aaf; }
+    .ult_periplasm { fill: #f0f; }
+  </style>
 <body>
 
 <div id="select" ></div>