diff --git a/src/app/components/analysis-panel/analysis-panel.component.html b/src/app/components/analysis-panel/analysis-panel.component.html index 6d6245ab6ce7b37c1c8df6c2b4fd6e99ee5de6db..9aeb4cb9b2cd5088bfa1117ba1676f7d77e25db4 100644 --- a/src/app/components/analysis-panel/analysis-panel.component.html +++ b/src/app/components/analysis-panel/analysis-panel.component.html @@ -89,11 +89,11 @@ <i class="fas fa-wrench" aria-hidden="true"></i> </span> {{ - ["quick", "super", "connect", "connectSelected"].indexOf( - task.info.algorithm - ) === -1 - ? "Algorithm:" - : "Method:" + ["quick", "super", "connect", "connectSelected"].indexOf( + task.info.algorithm + ) === -1 + ? "Algorithm:" + : "Method:" }} {{ algorithmNames[task.info.algorithm] }} </h4> @@ -103,105 +103,105 @@ <div class="column"> <table class="table is-narrow"> <tbody> - <tr - *ngIf=" + <tr + *ngIf=" result && result.geneInteractionDataset !== undefined " - > - <td>Protein-Protein Interaction Dataset</td> - <td> - {{ result.geneInteractionDataset.name }} (Version - {{ result.geneInteractionDataset.version }}) - </td> - </tr> - <tr - *ngIf=" + > + <td>Protein-Protein Interaction Dataset</td> + <td> + {{ result.geneInteractionDataset.name }} (Version + {{ result.geneInteractionDataset.version }}) + </td> + </tr> + <tr + *ngIf=" result && result.drugInteractionDataset !== undefined " - > - <td>Protein-Drug Interaction Dataset</td> - <td> - {{ result.drugInteractionDataset.name }} (Version - {{ result.drugInteractionDataset.version }}) - </td> - </tr> - <tr *ngIf="task.info.parameters.resultSize !== undefined"> - <td>Result Size</td> - <td>{{ task.info.parameters.resultSize }}</td> - </tr> - <tr *ngIf="task.info.parameters.k !== undefined"> - <td>K</td> - <td>{{ task.info.parameters.k }}</td> - </tr> - <tr *ngIf="task.info.parameters.numTrees !== undefined"> - <td>Number of trees</td> - <td>{{ task.info.parameters.numTrees }}</td> - </tr> - <tr *ngIf="task.info.parameters.tolerance !== undefined"> - <td>Tolerance</td> - <td>{{ task.info.parameters.tolerance }}</td> - </tr> - <tr *ngIf="task.info.parameters.dampingFactor !== undefined"> - <td>Damping Factor</td> - <td>{{ task.info.parameters.dampingFactor }}</td> - </tr> - <tr *ngIf="task.info.parameters.maxDeg !== undefined"> - <td>Maximum Degree</td> - <td>{{ task.info.parameters.maxDeg }}</td> - </tr> - <tr *ngIf="task.info.parameters.hubPenalty !== undefined"> - <td>Hub Penality</td> - <td>{{ task.info.parameters.hubPenalty }}</td> - </tr> - <tr - *ngIf=" + > + <td>Protein-Drug Interaction Dataset</td> + <td> + {{ result.drugInteractionDataset.name }} (Version + {{ result.drugInteractionDataset.version }}) + </td> + </tr> + <tr *ngIf="task.info.parameters.resultSize !== undefined"> + <td>Result Size</td> + <td>{{ task.info.parameters.resultSize }}</td> + </tr> + <tr *ngIf="task.info.parameters.k !== undefined"> + <td>K</td> + <td>{{ task.info.parameters.k }}</td> + </tr> + <tr *ngIf="task.info.parameters.numTrees !== undefined"> + <td>Number of trees</td> + <td>{{ task.info.parameters.numTrees }}</td> + </tr> + <tr *ngIf="task.info.parameters.tolerance !== undefined"> + <td>Tolerance</td> + <td>{{ task.info.parameters.tolerance }}</td> + </tr> + <tr *ngIf="task.info.parameters.dampingFactor !== undefined"> + <td>Damping Factor</td> + <td>{{ task.info.parameters.dampingFactor }}</td> + </tr> + <tr *ngIf="task.info.parameters.maxDeg !== undefined"> + <td>Maximum Degree</td> + <td>{{ task.info.parameters.maxDeg }}</td> + </tr> + <tr *ngIf="task.info.parameters.hubPenalty !== undefined"> + <td>Hub Penality</td> + <td>{{ task.info.parameters.hubPenalty }}</td> + </tr> + <tr + *ngIf=" task.info.parameters.includeIndirectDrugs !== undefined && task.info.target === 'drug' " - > - <td>Include indirect drugs</td> - <td> - <i - *ngIf="task.info.parameters.includeIndirectDrugs" - class="fa fa-check" - ></i> - <i - *ngIf="!task.info.parameters.includeIndirectDrugs" - class="fa fa-times color-danger" - ></i> - </td> - </tr> - <tr - *ngIf=" + > + <td>Include indirect drugs</td> + <td> + <i + *ngIf="task.info.parameters.includeIndirectDrugs" + class="fa fa-check" + ></i> + <i + *ngIf="!task.info.parameters.includeIndirectDrugs" + class="fa fa-times color-danger" + ></i> + </td> + </tr> + <tr + *ngIf=" task.info.parameters.includeNonApprovedDrugs !== undefined && task.info.target === 'drug' " - > - <td>Include non-approved drugs</td> - <td> - <i - *ngIf="task.info.parameters.includeNonApprovedDrugs" - class="fa fa-check" - ></i> - <i - *ngIf="!task.info.parameters.includeNonApprovedDrugs" - class="fa fa-times color-danger" - ></i> - </td> - </tr> - <tr *ngIf="task.info.parameters.customEdges !== undefined"> - <td>Include all displayed edges</td> - <td> - <i - *ngIf="task.info.parameters.customEdges" - class="fa fa-check" - ></i> - <i - *ngIf="!task.info.parameters.customEdges" - class="fa fa-times color-danger" - ></i> - </td> - </tr> + > + <td>Include non-approved drugs</td> + <td> + <i + *ngIf="task.info.parameters.includeNonApprovedDrugs" + class="fa fa-check" + ></i> + <i + *ngIf="!task.info.parameters.includeNonApprovedDrugs" + class="fa fa-times color-danger" + ></i> + </td> + </tr> + <tr *ngIf="task.info.parameters.customEdges !== undefined"> + <td>Include all displayed edges</td> + <td> + <i + *ngIf="task.info.parameters.customEdges" + class="fa fa-check" + ></i> + <i + *ngIf="!task.info.parameters.customEdges" + class="fa fa-times color-danger" + ></i> + </td> + </tr> </tbody> </table> </div> @@ -224,18 +224,18 @@ </h4> <table class="table is-narrow"> <tbody> - <tr> - <td>Number of Trees</td> - <td>1</td> - </tr> - <tr> - <td>Tolerance</td> - <td>0</td> - </tr> - <tr> - <td>Hub Penality</td> - <td>1</td> - </tr> + <tr> + <td>Number of Trees</td> + <td>1</td> + </tr> + <tr> + <td>Tolerance</td> + <td>0</td> + </tr> + <tr> + <td>Hub Penality</td> + <td>1</td> + </tr> </tbody> </table> </div> @@ -254,26 +254,26 @@ </h4> <table class="table is-narrow"> <tbody> - <tr> - <td>Include indirect drugs</td> - <td> - <i class="fa fa-times"></i> - </td> - </tr> - <tr> - <td>Include non-approved drugs</td> - <td> - <i class="fa fa-check"></i> - </td> - </tr> - <tr> - <td>Hub Penality</td> - <td>1</td> - </tr> - <tr> - <td>Result Size</td> - <td>10</td> - </tr> + <tr> + <td>Include indirect drugs</td> + <td> + <i class="fa fa-times"></i> + </td> + </tr> + <tr> + <td>Include non-approved drugs</td> + <td> + <i class="fa fa-check"></i> + </td> + </tr> + <tr> + <td>Hub Penality</td> + <td>1</td> + </tr> + <tr> + <td>Result Size</td> + <td>10</td> + </tr> </tbody> </table> </div> diff --git a/src/app/components/analysis-panel/analysis-panel.component.ts b/src/app/components/analysis-panel/analysis-panel.component.ts index 23ff59ce9977cd3066f47a077c9d4113aec5be2c..ca9d637f6c724844dd042add379adc7738e27b47 100644 --- a/src/app/components/analysis-panel/analysis-panel.component.ts +++ b/src/app/components/analysis-panel/analysis-panel.component.ts @@ -122,6 +122,8 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit public expressionMap: NodeAttributeMap; + public loading = false; + constructor(public legendService: LegendService, public networkHandler: NetworkHandlerService, public drugstoneConfig: DrugstoneConfigService, private http: HttpClient, public analysis: AnalysisService, public netex: NetexControllerService) { } @@ -172,160 +174,177 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit } if (this.task && this.task.info.done) { - this.result = await this.netex.getTaskResult(this.token); - if (this.result.parameters.target === 'drug') { - this.legendService.add_to_context('drug') - } else { - this.legendService.add_to_context('drugTarget') - } - const nodeAttributes = this.result.nodeAttributes || {}; - - this.networkHandler.activeNetwork.seedMap = nodeAttributes.isSeed || {}; - - // Reset - this.nodeData = {nodes: null, edges: null}; - this.networkHandler.activeNetwork.networkEl.nativeElement.innerHTML = ''; - this.networkHandler.activeNetwork.networkInternal = null; - - // Create - const {nodes, edges} = this.createNetwork(this.result); - this.networkHandler.activeNetwork.inputNetwork = {nodes: nodes, edges: edges}; - this.nodeData.nodes = new vis.DataSet(nodes); - this.nodeData.edges = new vis.DataSet(edges); - const container = this.networkHandler.activeNetwork.networkEl.nativeElement; - const isBig = nodes.length > 100 || edges.length > 100; - const options = NetworkSettings.getOptions(isBig ? 'analysis-big' : 'analysis', this.myConfig.physicsOn); - this.drugstoneConfig.config.physicsOn = !isBig; - - this.networkHandler.activeNetwork.networkInternal = new vis.Network(container, this.nodeData, options); - - this.networkHandler.activeNetwork.networkInternal.on('stabilizationIterationsDone', () => { - if (!this.drugstoneConfig.config.physicsOn) { - this.networkHandler.activeNetwork.updatePhysicsEnabled(false); - } - }); - this.tableDrugs = nodes.filter(e => e.drugstoneId && e.drugstoneType === 'drug'); - this.tableDrugs.forEach((r) => { - r.rawScore = r.score; - }); - this.tableProteins = nodes.filter(e => e.drugstoneId && e.drugstoneType === 'protein'); - this.tableSelectedProteins = []; - this.tableProteins.forEach((r) => { - r.rawScore = r.score; - r.isSeed = this.networkHandler.activeNetwork.seedMap[r.id]; - const wrapper = getWrapperFromNode(r); - if (this.analysis.inSelection(wrapper)) { - this.tableSelectedProteins.push(r); + this.loading = true; + this.netex.getTaskResult(this.token).then(result => { + this.result = result; + if (this.result.parameters.target === 'drug') { + this.legendService.add_to_context('drug'); + } else { + this.legendService.add_to_context('drugTarget'); } - }); - - - this.tableHasScores = ['trustrank', 'closeness', 'degree', 'betweenness', 'quick', 'super'] - .indexOf(this.task.info.algorithm) !== -1; - if (this.tableHasScores) { - this.toggleNormalization(true); - } + const nodeAttributes = this.result.nodeAttributes || {}; + + this.networkHandler.activeNetwork.seedMap = nodeAttributes.isSeed || {}; + + // Reset + this.nodeData = {nodes: null, edges: null}; + this.networkHandler.activeNetwork.networkEl.nativeElement.innerHTML = ''; + this.networkHandler.activeNetwork.networkInternal = null; + // Create + this.createNetwork(this.result).then(nw => { + const nodes = nw.nodes; + const edges = nw.edges; + + this.networkHandler.activeNetwork.inputNetwork = {nodes: nodes, edges: edges}; + this.nodeData.nodes = new vis.DataSet(nodes); + this.nodeData.edges = new vis.DataSet(edges); + const container = this.networkHandler.activeNetwork.networkEl.nativeElement; + const isBig = nodes.length > 100 || edges.length > 100; + const options = NetworkSettings.getOptions(isBig ? 'analysis-big' : 'analysis', this.myConfig); + // @ts-ignore + options.groups = this.drugstoneConfig.config.nodeGroups; + // @ts-ignore + for (const g of Object.values(options.groups)) { + // @ts-ignore + delete g.renderer + } + this.drugstoneConfig.config.physicsOn = !isBig; + this.networkHandler.activeNetwork.networkInternal = new vis.Network(container, this.nodeData, options); + this.networkHandler.activeNetwork.networkInternal.on('stabilizationIterationsDone', () => { + if (!this.drugstoneConfig.config.physicsOn) { + this.networkHandler.activeNetwork.updatePhysicsEnabled(false); + } + }); + this.tableDrugs = nodes.filter(e => e.drugstoneId && e.drugstoneType === 'drug'); + this.tableDrugs.forEach((r) => { + r.rawScore = r.score; + }); + this.tableProteins = nodes.filter(e => e.drugstoneId && e.drugstoneType === 'protein'); + this.tableSelectedProteins = []; + this.tableProteins.forEach((r) => { + r.rawScore = r.score; + r.isSeed = this.networkHandler.activeNetwork.seedMap[r.id]; + const wrapper = getWrapperFromNode(r); + if (this.analysis.inSelection(wrapper)) { + this.tableSelectedProteins.push(r); + } + }); - this.networkHandler.activeNetwork.networkInternal.on('deselectNode', (properties) => { - this.showDetailsChange.emit(null); - }); - this.networkHandler.activeNetwork.networkInternal.on('doubleClick', (properties) => { - const nodeIds: Array<string> = properties.nodes; - if (nodeIds.length > 0) { - const nodeId = nodeIds[0]; - const node = this.nodeData.nodes.get(nodeId); - if (node.nodeType === 'drug' || node.drugstoneId === undefined || node.drugstoneType !== 'protein') { - return; + this.tableHasScores = ['trustrank', 'closeness', 'degree', 'betweenness', 'quick', 'super'] + .indexOf(this.task.info.algorithm) !== -1; + if (this.tableHasScores) { + this.toggleNormalization(true); } - const wrapper = getWrapperFromNode(node); - if (this.analysis.inSelection(wrapper)) { - this.analysis.removeItems([wrapper]); - this.analysis.getCount(); - } else { - this.analysis.addItems([wrapper]); - this.analysis.getCount(); - } - } - }); - - this.networkHandler.activeNetwork.networkInternal.on('click', (properties) => { - const selectedNodes = this.nodeData.nodes.get(properties.nodes); - if (selectedNodes.length > 0) { - this.showDetailsChange.emit(getWrapperFromNode(selectedNodes[0])); - } else { - this.showDetailsChange.emit(null); - } - }); + this.networkHandler.activeNetwork.networkInternal.setData({nodes: undefined, edge: undefined}); + setTimeout(() => { + this.networkHandler.activeNetwork.networkInternal.setData(this.nodeData); + }, 1000); - this.analysis.subscribeList((items, selected) => { - // return if analysis panel is closed or no nodes are loaded - if (!this.token) { - return; - } + this.networkHandler.activeNetwork.networkInternal.on('deselectNode', (properties) => { + this.showDetailsChange.emit(null); + }); - if (selected !== null) { - const updatedNodes: Node[] = []; - for (const item of items) { - const node = this.nodeData.nodes.get(item.id); - if (!node) { - continue; + this.networkHandler.activeNetwork.networkInternal.on('doubleClick', (properties) => { + const nodeIds: Array<string> = properties.nodes; + if (nodeIds.length > 0) { + const nodeId = nodeIds[0]; + const node = this.nodeData.nodes.get(nodeId); + if (node.nodeType === 'drug' || node.drugstoneId === undefined || node.drugstoneType !== 'protein') { + return; + } + const wrapper = getWrapperFromNode(node); + if (this.analysis.inSelection(wrapper)) { + this.analysis.removeItems([wrapper]); + this.analysis.getCount(); + } else { + this.analysis.addItems([wrapper]); + this.analysis.getCount(); + } } - const pos = this.networkHandler.activeNetwork.networkInternal.getPositions([item.id]); - node.x = pos[item.id].x; - node.y = pos[item.id].y; - const isSeed = this.networkHandler.activeNetwork.highlightSeeds ? this.networkHandler.activeNetwork.seedMap[node.id] : false; - const nodeStyled = NetworkSettings.getNodeStyle( - node, - this.myConfig, - isSeed, - selected, - this.networkHandler.activeNetwork.getGradient(item.id), - this.networkHandler.activeNetwork.nodeRenderer - ) - updatedNodes.push(nodeStyled); - } - this.nodeData.nodes.update(updatedNodes); - - const proteinSelection = this.tableSelectedProteins; - for (const item of items) { - // TODO: Refactor! - const found = proteinSelection.findIndex((i) => getProteinNodeId(i) === item.id); - const tableItem = this.tableProteins.find((i) => getProteinNodeId(i) === item.id); - if (selected && found === -1 && tableItem) { - proteinSelection.push(tableItem); - } - if (!selected && found !== -1 && tableItem) { - proteinSelection.splice(found, 1); + }); + + this.networkHandler.activeNetwork.networkInternal.on('click', (properties) => { + const selectedNodes = this.nodeData.nodes.get(properties.nodes); + if (selectedNodes.length > 0) { + this.showDetailsChange.emit(getWrapperFromNode(selectedNodes[0])); + } else { + this.showDetailsChange.emit(null); } - } - this.tableSelectedProteins = [...proteinSelection]; - } else { - // else: selected is null - const updatedNodes = []; - this.nodeData.nodes.forEach((node) => { - const isSeed = this.networkHandler.activeNetwork.highlightSeeds ? this.networkHandler.activeNetwork.seedMap[node.id] : false; - const nodeStyled = NetworkSettings.getNodeStyle( - node, - this.myConfig, - isSeed, - selected, - this.networkHandler.activeNetwork.getGradient(node.id), - this.networkHandler.activeNetwork.nodeRenderer - ) - updatedNodes.push(nodeStyled); }); - this.nodeData.nodes.update(updatedNodes); - const proteinSelection = []; - for (const item of items) { - const tableItem = this.tableProteins.find((i) => getProteinNodeId(i) === item.id); - if (tableItem) { - proteinSelection.push(tableItem); + this.analysis.subscribeList((items, selected) => { + // return if analysis panel is closed or no nodes are loaded + if (!this.token) { + return; } - } - this.tableSelectedProteins = [...proteinSelection]; - } + + if (selected !== null) { + const updatedNodes: Node[] = []; + for (const item of items) { + const node = this.nodeData.nodes.get(item.id); + if (!node) { + continue; + } + const pos = this.networkHandler.activeNetwork.networkInternal.getPositions([item.id]); + node.x = pos[item.id].x; + node.y = pos[item.id].y; + const isSeed = this.networkHandler.activeNetwork.highlightSeeds ? this.networkHandler.activeNetwork.seedMap[node.id] : false; + const nodeStyled = NetworkSettings.getNodeStyle( + node, + this.myConfig, + isSeed, + selected, + this.networkHandler.activeNetwork.getGradient(item.id), + this.networkHandler.activeNetwork.nodeRenderer + ) + updatedNodes.push(nodeStyled); + } + this.nodeData.nodes.update(updatedNodes); + + const proteinSelection = this.tableSelectedProteins; + for (const item of items) { + // TODO: Refactor! + const found = proteinSelection.findIndex((i) => getProteinNodeId(i) === item.id); + const tableItem = this.tableProteins.find((i) => getProteinNodeId(i) === item.id); + if (selected && found === -1 && tableItem) { + proteinSelection.push(tableItem); + } + if (!selected && found !== -1 && tableItem) { + proteinSelection.splice(found, 1); + } + } + this.tableSelectedProteins = [...proteinSelection]; + } else { + // else: selected is null + const updatedNodes = []; + this.nodeData.nodes.forEach((node) => { + const isSeed = this.networkHandler.activeNetwork.highlightSeeds ? this.networkHandler.activeNetwork.seedMap[node.id] : false; + if (!isSeed) + return + const nodeStyled = NetworkSettings.getNodeStyle( + node, + this.myConfig, + isSeed, + selected, + this.networkHandler.activeNetwork.getGradient(node.id), + this.networkHandler.activeNetwork.nodeRenderer + ); + updatedNodes.push(nodeStyled); + }); + this.nodeData.nodes.update(updatedNodes); + + const proteinSelection = []; + for (const item of items) { + const tableItem = this.tableProteins.find((i) => getProteinNodeId(i) === item.id); + if (tableItem) { + proteinSelection.push(tableItem); + } + } + this.tableSelectedProteins = [...proteinSelection]; + } + }); + }); }); } } @@ -401,7 +420,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit * @param result * @returns */ - public createNetwork(result: any): { edges: any[], nodes: any[] } { + public async createNetwork(result: any): Promise<{ edges: any[]; nodes: any[]; }> { const config = result.parameters.config; this.myConfig = config; @@ -417,6 +436,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit this.proteins = []; this.effects = []; const network = result.network; + network.nodes = [...new Set<string>(network.nodes)] const details = attributes.details || {}; const nodeIdMap = {} @@ -427,29 +447,33 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit nodeIdMap[id] = e[1][identifier][0] }) }) - for (const nodeId of Object.keys(details)) { - const nodeDetails = details[nodeId] - nodeDetails.id = nodeDetails.id ? nodeDetails.id : (typeof nodeDetails.drugstoneId === 'string' ? nodeDetails.drugstoneId : nodeDetails.drugstoneId[0]); - if (nodeDetails.drugstoneId && nodeDetails.drugstoneType === 'protein') { - // node is protein from database, has been mapped on init to backend protein from backend - // or was found during analysis - // FIXME connectorNodes are not visualized correctly - nodeDetails.group = result.targetNodes && result.targetNodes.indexOf(nodeId) !== -1 ? 'foundNode' : (nodeDetails.group ? nodeDetails.group : 'connectorNode'); - nodeDetails.label = nodeDetails.label ? nodeDetails.label : nodeDetails[identifier]; - nodeDetails.id = nodeDetails[identifier][0] ? nodeDetails[identifier][0] : nodeDetails.id; - this.proteins.push(nodeDetails); - } else if (nodeDetails.drugstoneId && nodeDetails.drugstoneType === 'drug') { - // node is drug, was found during analysis - nodeDetails.type = 'Drug'; - nodeDetails.group = 'foundDrug'; + for (const nodeId of network.nodes) { + if (details[nodeId]) { + const nodeDetails = details[nodeId] + nodeDetails.id = nodeDetails.id ? nodeDetails.id : (typeof nodeDetails.drugstoneId === 'string' ? nodeDetails.drugstoneId : nodeDetails.drugstoneId[0]); + if (nodeDetails.drugstoneId && nodeDetails.drugstoneType === 'protein') { + // node is protein from database, has been mapped on init to backend protein from backend + // or was found during analysis + // FIXME connectorNodes are not visualized correctly + nodeDetails.group = result.targetNodes && result.targetNodes.indexOf(nodeId) !== -1 ? 'foundNode' : (nodeDetails.group ? nodeDetails.group : 'connectorNode'); + nodeDetails.label = nodeDetails.label ? nodeDetails.label : nodeDetails[identifier]; + nodeDetails.id = nodeDetails[identifier][0] ? nodeDetails[identifier][0] : nodeDetails.id; + this.proteins.push(nodeDetails); + } else if (nodeDetails.drugstoneId && nodeDetails.drugstoneType === 'drug') { + // node is drug, was found during analysis + nodeDetails.type = 'Drug'; + nodeDetails.group = 'foundDrug'; + } else { + // node is custom input from user, could not be mapped to backend protein + nodeDetails.group = nodeDetails.group ? nodeDetails.group : 'default'; + nodeDetails.label = nodeDetails.label ? nodeDetails.label : nodeDetails[identifier] + } + // further analysis and the button function can be used to highlight seeds + // option to use scores[node] as gradient, but sccores are very small + nodes.push(NetworkSettings.getNodeStyle(nodeDetails as Node, config, false, false, 1, this.networkHandler.activeNetwork.nodeRenderer)) } else { - // node is custom input from user, could not be mapped to backend protein - nodeDetails.group = nodeDetails.group ? nodeDetails.group : 'default'; - nodeDetails.label = nodeDetails.label ? nodeDetails.label : nodeDetails[identifier] + console.log("Missing details for " + nodeId) } - // further analysis and the button function can be used to highlight seeds - // option to use scores[node] as gradient, but sccores are very small - nodes.push(NetworkSettings.getNodeStyle(nodeDetails as Node, config, false, false, 1, this.networkHandler.activeNetwork.nodeRenderer)) } diff --git a/src/app/components/network/network.component.ts b/src/app/components/network/network.component.ts index b4dd056b2e6974359c79de8f929ed9498ba37353..331fc3bb7e632d1dd2f44f5ef3ff343e78983a4a 100644 --- a/src/app/components/network/network.component.ts +++ b/src/app/components/network/network.component.ts @@ -80,6 +80,8 @@ export class NetworkComponent implements OnInit { public nodeRenderer = null; + public loading = false + constructor(public configService: DrugstoneConfigService, public legendService: LegendService, public networkHandler: NetworkHandlerService, public analysis: AnalysisService, public drugstoneConfig: DrugstoneConfigService, public netex: NetexControllerService, public omnipath: OmnipathControllerService) { } @@ -88,6 +90,10 @@ export class NetworkComponent implements OnInit { this.networkSidebarOpen = this.configService.config.expandNetworkMenu || false; } + setLoading(bool: boolean): void { + this.loading = bool; + } + async getInteractions(key: InteractionDatabase) { let edges = []; if (key === 'omnipath') { @@ -101,9 +107,10 @@ export class NetworkComponent implements OnInit { updateQueryItems() { this.queryItems = []; - this.currentViewNodes.forEach((protein) => { - this.queryItems.push(getWrapperFromNode(protein)); - }); + if (this.currentViewNodes) + this.currentViewNodes.forEach((protein) => { + this.queryItems.push(getWrapperFromNode(protein)); + }); } public saveAddNodes(nodeList: Node[]) { @@ -341,25 +348,25 @@ export class NetworkComponent implements OnInit { this.nodeRenderer = null; const updatedNodes = []; // for (const item of this.proteins) { - for (const item of this.currentViewProteins) { - if (item.drugstoneId === undefined) { + for (const node of this.nodeData.nodes.get().filter(n => n.drugstoneType === 'protein')) { + if (node.drugstoneId === undefined) { // nodes that are not mapped to backend remain untouched continue; } - const node: Node = this.nodeData.nodes.get(item.id); + // const node: Node = this.nodeData.nodes.get(item.id); if (!node) { continue; } - const pos = this.networkInternal.getPositions([item.id]); - node.x = pos[item.id].x; - node.y = pos[item.id].y; + const pos = this.networkInternal.getPositions([node.id]); + node.x = pos[node.id].x; + node.y = pos[node.id].y; Object.assign( node, NetworkSettings.getNodeStyle( node, this.drugstoneConfig.config, - false, - this.analysis.inSelection(getWrapperFromNode(item)), + node.isSeed && this.networkHandler.activeNetwork.highlightSeeds, + this.analysis.inSelection(getWrapperFromNode(node)), 1.0, this.nodeRenderer ) @@ -422,7 +429,7 @@ export class NetworkComponent implements OnInit { NetworkSettings.getNodeStyle( node, this.drugstoneConfig.config, - node.isSeed, + node.isSeed && this.networkHandler.activeNetwork.highlightSeeds, this.analysis.inSelection(wrapper), gradient, this.nodeRenderer)); @@ -461,18 +468,18 @@ export class NetworkComponent implements OnInit { this.legendService.add_to_context('seeds') else this.legendService.remove_from_context('seeds') - for (const item of this.currentViewProteins) { - if (item.drugstoneId === undefined) { + for (const node of this.nodeData.nodes.get().filter(n => n.drugstoneType === 'protein')) { + if (node.drugstoneId === undefined) { // nodes that are not mapped to backend remain untouched continue; } - const node: Node = this.nodeData.nodes.get(item.id); + // const node: Node = this.nodeData.nodes.get(item.id); if (!node) { continue; } - const pos = this.networkHandler.activeNetwork.networkInternal.getPositions([item.id]); - node.x = pos[item.id].x; - node.y = pos[item.id].y; + const pos = this.networkHandler.activeNetwork.networkInternal.getPositions([node.id]); + node.x = pos[node.id].x; + node.y = pos[node.id].y; const isSeed = this.highlightSeeds ? this.seedMap[node.id] : false; Object.assign( node, @@ -480,8 +487,8 @@ export class NetworkComponent implements OnInit { node, this.drugstoneConfig.config, isSeed, - this.analysis.inSelection(getWrapperFromNode(item)), - this.getGradient(item.id), + this.analysis.inSelection(getWrapperFromNode(node)), + this.getGradient(node.id), this.nodeRenderer ) ) diff --git a/src/app/dialogs/launch-analysis/launch-analysis.component.ts b/src/app/dialogs/launch-analysis/launch-analysis.component.ts index 752cdf6ef2c3a31c590d983dba855b2d2af6592a..132a99d73ad53e0c63efe011873c4368ff0b86f3 100644 --- a/src/app/dialogs/launch-analysis/launch-analysis.component.ts +++ b/src/app/dialogs/launch-analysis/launch-analysis.component.ts @@ -116,7 +116,6 @@ export class LaunchAnalysisComponent implements OnInit, OnChanges { config: this.drugstoneConfig.config, input_network: this.networkHandler.activeNetwork.inputNetwork }; - console.log(parameters) parameters.ppi_dataset = this.drugstoneConfig.config.interactionProteinProtein; parameters.pdi_dataset = this.drugstoneConfig.config.interactionDrugProtein; parameters.licenced = this.drugstoneConfig.config.licensedDatasets; diff --git a/src/app/interfaces.ts b/src/app/interfaces.ts index 0a3895278a5d9480682e1d2db9a76c5e3f7c1339..cf6f8832a480353c55b74aba5228ad8b164a68c0 100644 --- a/src/app/interfaces.ts +++ b/src/app/interfaces.ts @@ -22,6 +22,7 @@ export interface Node { borderWidth: number; borderWidthSelected: number; opacity?: number; + shadow?:any; font: { color: string; size: number; @@ -43,7 +44,7 @@ export interface NetworkData { edges: NetworkEdge[] } -export type NodeType= 'protein' | 'drug' | 'disorder' | 'other' +export type NodeType = 'protein' | 'drug' | 'disorder' | 'other' export type NetworkType = 'explorer' | 'analysis' @@ -191,7 +192,7 @@ export interface Wrapper { label: string; type?: string; symbol?: Array<string>; - drugstoneId?: Array<string> |string; + drugstoneId?: Array<string> | string; drugstoneType: NodeType, ensg?: Array<string>; entrez?: Array<string>; diff --git a/src/app/network-settings.ts b/src/app/network-settings.ts index 971f137d242d821f91144684781f603ad0bbf4d6..01d0b927b4fb78ce1583de2e9f11add359c1a6c3 100644 --- a/src/app/network-settings.ts +++ b/src/app/network-settings.ts @@ -1,8 +1,8 @@ -import { getGradientColor } from './utils'; +import {getGradientColor} from './utils'; import { Node, } from './interfaces'; -import { IConfig, defaultConfig } from './config'; +import {IConfig, defaultConfig} from './config'; import * as merge from 'lodash/fp/merge'; export class NetworkSettings { @@ -60,24 +60,29 @@ export class NetworkSettings { stabilization: true }; - static getOptions(network: 'main' | 'analysis' | 'analysis-big', physicsOn) { + static getOptions(network: 'main' | 'analysis' | 'analysis-big', config) { + const physicsOn = config.physicsOn; + const groups = config.nodeGroups; if (network === 'main') { return { layout: this.mainLayout, edges: this.mainEdges, physics: physicsOn || this.mainPhysics, + groups, }; } else if (network === 'analysis') { return { layout: this.analysisLayout, edges: this.analysisEdges, physics: physicsOn || this.analysisPhysics, + groups, }; } else if (network === 'analysis-big') { return { layout: this.analysisLayout, edges: this.analysisEdges, physics: physicsOn || this.analysisBigPhysics, + groups, }; } } @@ -92,41 +97,77 @@ export class NetworkSettings { // delete possible old styles Object.keys(config.nodeGroups.default).forEach(e => delete node[e]); - // set group styles - if (node.group === 'default') { - node = merge(node, config.nodeGroups.default); - } else { - node = merge(node, config.nodeGroups[node.group]); - } - // note that seed and selected node style are applied after the node style is fetched. // this allows to overwrite only attributes of interest, therefore in e.g. seedNode group // certain attributes like shape can remain undefined // use lodash merge to not lose deep attributes, e.g. "font.size" + // @ts-ignore + if (node._group) + // @ts-ignore + node.group = node._group + // @ts-ignore + if (node._shadow) { // @ts-ignore + node.shadow = node._shadow + }else{ + if (config.nodeGroups[node.group].shadow) { + node.shadow = {enabled: config.nodeGroups[node.group].shadow} + node.shadow.color = 'rgba(0,0,0,0.5)' + } else { + node.shadow = {color: 'rgba(0,0,0,0.5)'} + } + } if (isSeed) { // apply seed node style to node - node = merge(node, config.nodeGroups.seedNode); + // @ts-ignore + node._group = node.group + node.group = 'seedNode' } // selection on purpose after seed style, so seed style will be combined with selection style if (isSelected) { + // @ts-ignore + node._group = node.group // apply selected node style to node - node = merge(node, config.nodeGroups.selectedNode); + node.group = 'selectedNode' + if (config.nodeGroups[node.group].shadow) { + node.shadow = {enabled: config.nodeGroups[node.group].shadow} + node.shadow.color = '#000000' + } else { + node.shadow = {color: '#000000'} + } } + // show image if image url is given. If seed nodes are highlighted, ignore image property if (node.image && !isSeed) { node.shape = 'image'; } - // use opactiy as gradient - if (gradient === null) { - node.opacity = 0 - } else { - node.opacity = gradient - } + // custom ctx renderer for e.g. pie chart if (renderer !== null) { + // @ts-ignore node.shape = 'custom'; + node.color = {opacity: gradient} + node.opacity = gradient + if (isSeed) { + // apply seed node style to node + // @ts-ignore + node.color = config.nodeGroups[node.group].color + }else{ + delete node.color + } + // @ts-ignore + node._shadow = node.shadow + if (config.nodeGroups[node.group].shadow) { + node.shadow = {enabled: config.nodeGroups[node.group].shadow} + node.shadow.color = 'rgba(0,0,0,0.5)' + } else { + node.shadow = {color: 'rgba(0,0,0,0.5)'} + } node.ctxRenderer = renderer; + } else { + node.opacity = undefined + delete node.ctxRenderer; } + return node; } } diff --git a/src/app/pages/explorer-page/explorer-page.component.ts b/src/app/pages/explorer-page/explorer-page.component.ts index bd300ee8eaecc2f71b2868c236a32208e067892f..05da418ca7e63014c7d5ab11a197b4c11ab55022 100644 --- a/src/app/pages/explorer-page/explorer-page.component.ts +++ b/src/app/pages/explorer-page/explorer-page.component.ts @@ -24,8 +24,8 @@ import {NetexControllerService} from 'src/app/services/netex-controller/netex-co import {removeDuplicateObjectsFromList} from '../../utils'; import * as merge from 'lodash/fp/merge'; import * as JSON5 from 'json5'; -import { DrugstoneConfigService } from 'src/app/services/drugstone-config/drugstone-config.service'; -import { NetworkHandlerService } from 'src/app/services/network-handler/network-handler.service'; +import {DrugstoneConfigService} from 'src/app/services/drugstone-config/drugstone-config.service'; +import {NetworkHandlerService} from 'src/app/services/network-handler/network-handler.service'; declare var vis: any; @@ -164,19 +164,6 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { updatedNodes.push(nodeStyled); } this.nodeData.nodes.update(updatedNodes); - } else { - const updatedNodes = []; - this.nodeData.nodes.forEach((node) => { - // const nodeSelected = this.analysis.idInSelection(node.id); - // if (node.group == 'default') { - // Object.assign(node, this.drugstoneConfig.config.nodeGroups.default); - // } else { - // Object.assign(node, this.drugstoneConfig.config.nodeGroups[node.group]); - // }; - Object.assign(node, this.drugstoneConfig.config.nodeGroups[node.group]); - - }); - this.nodeData.nodes.update(updatedNodes); } }); } @@ -261,8 +248,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { this.networkHandler.activeNetwork.selectedWrapper = null; // getNetwork synchronizes the input network with the database await this.getNetwork(); - this.proteinData = new ProteinNetwork(this.networkHandler.activeNetwork.inputNetwork.nodes,this.networkHandler.activeNetwork.inputNetwork.edges); - + this.proteinData = new ProteinNetwork(this.networkHandler.activeNetwork.inputNetwork.nodes, this.networkHandler.activeNetwork.inputNetwork.edges); if (this.networkHandler.activeNetwork.networkPositions) { this.proteinData.updateNodePositions(this.networkHandler.activeNetwork.networkPositions); } @@ -302,16 +288,16 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { return true }) - // @ts-ignore + // @ts-ignore if (!this.drugstoneConfig.selfReferences) { - edges = edges.filter(el => el.from !== el.to); - } + edges = edges.filter(el => el.from !== el.to); + } this.nodeData.nodes = new vis.DataSet(nodes); this.nodeData.edges = new vis.DataSet(edges); const container = this.networkHandler.activeNetwork.networkEl.nativeElement; - const options = NetworkSettings.getOptions('main', this.drugstoneConfig.config.physicsOn); + const options = NetworkSettings.getOptions('main', this.drugstoneConfig.config); this.networkHandler.activeNetwork.networkInternal = new vis.Network(container, this.nodeData, options); @@ -410,7 +396,6 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { network.nodes.forEach((node) => { // set node label to original id before node id will be set to netex id node.label = node.label ? node.label : node.id; - }); // adjust edge labels accordingly and filter @@ -574,14 +559,14 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { //TODO change to access through network service @ViewChild('analysisPanel') analysisPanel; - getNodes() :any { + getNodes(): any { if (this.selectedAnalysisToken && this.analysisPanel) return this.analysisPanel.getResultNodes() return this.networkHandler.activeNetwork.inputNetwork.nodes; } - getEdges() :any { - if(this.selectedAnalysisToken && this.analysisPanel) + getEdges(): any { + if (this.selectedAnalysisToken && this.analysisPanel) return this.analysisPanel.getResultEdges() return this.networkHandler.activeNetwork.inputNetwork.edges } diff --git a/src/app/services/netex-controller/netex-controller.service.ts b/src/app/services/netex-controller/netex-controller.service.ts index 8c9864b0c44b27027d0a6744a2310299ebf4caf9..de49c7b14fae14251b32c5dc46c08723faa08936 100644 --- a/src/app/services/netex-controller/netex-controller.service.ts +++ b/src/app/services/netex-controller/netex-controller.service.ts @@ -20,7 +20,7 @@ export class NetexControllerService { return this.http.post<any>(`${environment.backend}tasks/`, {tokens: JSON.stringify(tokens)}).toPromise(); } - public async getTaskResult(token): Promise<any> { + public getTaskResult(token) { /** * returns promise of task result of COMPLETED task */ diff --git a/src/index.html b/src/index.html index c1f77a357967d3d484f724238a6d7b7f00ff4157..f00e735faa639d9e9d747e71eafbcbb590621b3f 100644 --- a/src/index.html +++ b/src/index.html @@ -92,9 +92,9 @@ <drugst-one id="netexp1" pluginId="2" - groups='{"nodeGroups":{"patient":{"type":"patient","color":"#000000","font":{"color":"#000000"},"groupName":"Patient","shape":"image","image":"https://static.thenounproject.com/png/22780-200.png"},"condition":{"type":"condition","color":"#000000","font":{"color":"#000000"},"groupName":"Condition","shape":"text"},"important":{"type":"gene","color":"#ff881f","font":{"color":"#000000"},"groupName":"Important Gene","shape":"ellipse"},"gene":{"type":"gene","color":"#4da300","font":{"color":"#f0f0f0"},"groupName":"Gene","shape":"circle"},"foundDrug":{"type":"drug","color":"#F12590","font":{"color":"#000000"},"groupName":"Drug","shape":"diamond"}},"edgeGroups":{"genotype":{"color":"#000000","groupName":"Relevant Gene"},"has-condition":{"color":"#000000","groupName":"Has Condition","dashes":[2,2]},"default":{"color":"#000000","groupName":"default edge"},"ggi":{"color":"#000000","groupName":"Interaction","dashes":[3,2]}}}' - config='{"expandNetworkMenu": false, "showSimpleAnalysis": true, "licensedDatasets": false, "physicsOn":false,"identifier":"symbol","title":"Breast cancer example network","nodeShadow":true,"edgeShadow":false,"autofillEdges":true,"showLegend":true}' - network='{"nodes":[{"id": "FOXP3"},{"id":"patient-1","group":"patient","x":592,"y":446},{"id":"patient-2","group":"patient","x":235,"y":87},{"id":"patient-3","group":"patient","x":105,"y":369},{"id":"ATM","label":"ATM","group":"gene","x":289,"y":242},{"id":"BARD1","label":"BARD1","group":"gene","x":44,"y":250},{"id":"BRCA1","label":"BRCA1","group":"gene","x":466,"y":576},{"id":"BRCA2","label":"BRCA2","group":"gene","x":507,"y":285},{"id":"BRIP1","label":"BRIP1","group":"gene","x":54,"y":474},{"id":"CHEK2","label":"CHEK2","group":"gene","x":216,"y":590},{"id":"CDH1","label":"CDH1","group":"gene","x":320,"y":-57},{"id":"NF1","label":"NF1","group":"gene","x":481,"y":111},{"id":"NBN","label":"NBN","group":"gene","x":-57,"y":314},{"id":"PALB2","label":"PALB2","group":"gene","x":450,"y":190},{"id":"PTEN","label":"PTEN","group":"important","x":305,"y":494},{"id":"RAD51C","label":"RAD51C","group":"gene","x":182,"y":-90},{"id":"RAD51D","label":"RAD51D","group":"gene","x":368,"y":73},{"id":"STK11","label":"STK11","group":"gene","x":686,"y":330},{"id":"TP53","label":"TP53","group":"important","x":333,"y":316},{"id":"subtype-1","label":"Subtype 1","group":"condition","x":556,"y":171},{"id":"subtype-2","label":"Subtype 2","group":"condition","x":-87,"y":221}],"edges":[{"from":"PTEN","to":"NBN","group":"ggi"}, {"from":"patient-3","to":"subtype-2","group":"has-condition"}]}' + groups='{"nodeGroups":{"important":{"type":"gene","color":"#ff881f","font":{"color":"#000000"},"groupName":"Seed","shape":"star"},"gene":{"type":"gene","color":"#4da300","font":{"color":"#f0f0f0"},"groupName":"Discovered target","shape":"circle"},"foundDrug":{"type":"drug","color":"#F12590","font":{"color":"#000000"},"groupName":"Drug","shape":"diamond"}},"edgeGroups":{"default":{"color":"#000000","groupName":"default edge"}}}' + config='{"identifier":"symbol","title":"ROBUST output network", "taskDrugName": "Drug Search", "showLegendNodes": true, "showLegendEdges": true, "showSidebar": "left", "showOverview": true, "legendPos": "left", "legendClass": "legend", "showQuery": true, "showItemSelector": true,"showSimpleAnalysis": false,"showAdvAnalysis": true,"showSelection": true,"showTasks": true,"showNetworkMenu": "right","showLegend": true,"showNetworkMenuButtonExpression": true, "showNetworkMenuButtonScreenshot": true,"showNetworkMenuButtonExportGraphml": true,"showNetworkMenuButtonAdjacentDrugs": true,"showNetworkMenuButtonCenter": true,"showConnectGenes": false,"networkMenuButtonAdjacentDrugsLabel": "Drugs","showNetworkMenuButtonAdjacentDisordersProteins": true,"networkMenuButtonAdjacentDisordersProteinsLabel": "Disorders (protein)","showNetworkMenuButtonAdjacentDisordersDrugs": true,"networkMenuButtonAdjacentDisordersDrugsLabel": "Disorders (drug)","showNetworkMenuButtonAnimation": true,"networkMenuButtonAnimationLabel": "Animation", "autofillEdges": false, "physicsOn": false,"useNedrexLicenced": true,"selfReferences": false, "interactionDrugProtein": "NeDRex", "indicationDrugDisorder": "NeDRex","nodeShadow": true,"edgeShadow": true, "algorithms": {"drug": ["trustrank", "closeness", "degree", "proximity"], "drug-target": ["trustrank", "multisteiner", "keypathwayminer", "degree", "closeness", "betweenness"]}, "associatedProteinDisorder": "NeDRex", "expandNetworkMenu": true}' + network='{"nodes": [{"id": "UBE2I", "group": "gene"}, {"id": "EEF1A1", "group": "gene"}, {"id": "KDM5A", "group": "gene"}, {"id": "THOC2", "group": "gene"}, {"id": "XPO1", "group": "gene"}, {"id": "RPL4", "group": "gene"}, {"id": "TOP1", "group": "gene"}, {"id": "YWHAE", "group": "gene"}, {"id": "CHUK", "group": "gene"}, {"id": "HSP90AB1", "group": "gene"}, {"id": "CD6", "group": "important"}, {"id": "TYK2", "group": "important"}, {"id": "FSTL1", "group": "gene"}, {"id": "CBL", "group": "gene"}, {"id": "NR2F2", "group": "gene"}, {"id": "RUNX1T1", "group": "gene"}, {"id": "MED23", "group": "gene"}, {"id": "IFNAR1", "group": "gene"}, {"id": "LCOR", "group": "gene"}, {"id": "IL10", "group": "important"}, {"id": "NLRP3", "group": "important"}, {"id": "A2M", "group": "gene"}, {"id": "EIF4A1", "group": "gene"}, {"id": "HSPA4", "group": "gene"}, {"id": "ACTB", "group": "gene"}, {"id": "SNRPB", "group": "gene"}, {"id": "KIF1B", "group": "important"}, {"id": "HIST1H1B", "group": "gene"}, {"id": "EFNB3", "group": "gene"}, {"id": "ERP44", "group": "gene"}, {"id": "HSP90AA1", "group": "gene"}, {"id": "KIF2C", "group": "gene"}, {"id": "KCNJ10", "group": "important"}, {"id": "APOE", "group": "important"}, {"id": "RNF14", "group": "gene"}, {"id": "TM9SF1", "group": "gene"}, {"id": "TRIM28", "group": "gene"}, {"id": "RIPK2", "group": "gene"}, {"id": "IL1R1", "group": "gene"}, {"id": "IL1B", "group": "important"}, {"id": "PRDX2", "group": "gene"}, {"id": "GOPC", "group": "gene"}, {"id": "ARHGEF7", "group": "gene"}, {"id": "CASK", "group": "gene"}, {"id": "MYC", "group": "gene"}, {"id": "SNW1", "group": "gene"}, {"id": "KRT31", "group": "gene"}, {"id": "TSSC1", "group": "gene"}, {"id": "LRP2", "group": "gene"}, {"id": "VCAM1", "group": "important"}, {"id": "CRK", "group": "gene"}, {"id": "LGALS3BP", "group": "gene"}, {"id": "PCMT1", "group": "gene"}, {"id": "MLLT4", "group": "gene"}, {"id": "BRCA1", "group": "gene"}, {"id": "IL7R", "group": "important"}, {"id": "BAG1", "group": "gene"}, {"id": "RAB3B", "group": "gene"}, {"id": "MAPK1", "group": "gene"}, {"id": "CPSF7", "group": "gene"}, {"id": "STAT1", "group": "gene"}, {"id": "HLA-DPB1", "group": "important"}, {"id": "NCOR2", "group": "gene"}, {"id": "IL7", "group": "important"}, {"id": "TNFAIP3", "group": "important"}, {"id": "RNF31", "group": "gene"}, {"id": "IRF8", "group": "important"}, {"id": "PTPN11", "group": "gene"}, {"id": "CLEC16A", "group": "important"}, {"id": "BIRC3", "group": "gene"}, {"id": "DEFA1", "group": "gene"}, {"id": "POMC", "group": "important"}, {"id": "UBR4", "group": "gene"}, {"id": "SMARCA5", "group": "gene"}, {"id": "SEC24A", "group": "gene"}, {"id": "ADRB2", "group": "gene"}, {"id": "COPS2", "group": "gene"}, {"id": "TRAF3IP2", "group": "gene"}, {"id": "RBPJ", "group": "important"}, {"id": "RAB39B", "group": "gene"}, {"id": "NCOA6", "group": "gene"}, {"id": "IFNG", "group": "important"}, {"id": "SIAH1", "group": "gene"}, {"id": "CD58", "group": "important"}, {"id": "KRTAP10-8", "group": "gene"}, {"id": "WRAP73", "group": "gene"}, {"id": "FYN", "group": "gene"}, {"id": "GNAI2", "group": "gene"}, {"id": "YWHAH", "group": "gene"}, {"id": "CBLB", "group": "important"}, {"id": "IL2RA", "group": "important"}, {"id": "P2RX7", "group": "important"}, {"id": "CCND3", "group": "gene"}, {"id": "MCAM", "group": "important"}, {"id": "YBX3", "group": "gene"}, {"id": "IL1RN", "group": "important"}, {"id": "IFNB1", "group": "important"}, {"id": "FAF1", "group": "gene"}, {"id": "SPDL1", "group": "gene"}, {"id": "ELAVL1", "group": "gene"}, {"id": "IL12A", "group": "important"}, {"id": "LGALS8", "group": "gene"}, {"id": "GNAI3", "group": "gene"}, {"id": "VDR", "group": "important"}, {"id": "SNTA1", "group": "gene"}, {"id": "TNFRSF1A", "group": "important"}, {"id": "CD40", "group": "important"}, {"id": "RAP1GAP", "group": "gene"}, {"id": "PDGFRB", "group": "gene"}, {"id": "SELE", "group": "important"}, {"id": "VCL", "group": "gene"}, {"id": "IFI16", "group": "gene"}, {"id": "YWHAB", "group": "gene"}, {"id": "IL17A", "group": "important"}, {"id": "KIF11", "group": "gene"}, {"id": "GRB2", "group": "gene"}, {"id": "CNR1", "group": "important"}, {"id": "RELA", "group": "gene"}, {"id": "HSPA8", "group": "gene"}, {"id": "STAT4", "group": "important"}, {"id": "SND1", "group": "gene"}, {"id": "LRP8", "group": "gene"}, {"id": "GNAI1", "group": "gene"}, {"id": "F11R", "group": "gene"}, {"id": "HNRNPC", "group": "gene"}, {"id": "COPS5", "group": "gene"}, {"id": "ACTA2", "group": "gene"}, {"id": "FLNA", "group": "gene"}, {"id": "CSNK2A1", "group": "gene"}, {"id": "JUN", "group": "gene"}, {"id": "VDAC1", "group": "gene"}, {"id": "PSMC5", "group": "gene"}, {"id": "IL12B", "group": "gene"}, {"id": "SLAMF1", "group": "gene"}, {"id": "HLA-DRA", "group": "important"}, {"id": "APP", "group": "gene"}, {"id": "HLA-DPA1", "group": "gene"}, {"id": "BCHE", "group": "important"}, {"id": "ICAM1", "group": "important"}, {"id": "NLRC4", "group": "gene"}, {"id": "RNF41", "group": "gene"}, {"id": "COL14A1", "group": "gene"}, {"id": "YWHAG", "group": "gene"}, {"id": "MS4A1", "group": "gene"}, {"id": "SF1", "group": "gene"}, {"id": "CASP10", "group": "gene"}, {"id": "TP53", "group": "gene"}, {"id": "GC", "group": "important"}, {"id": "TRAF6", "group": "gene"}, {"id": "CASP1", "group": "important"}], "edges": [{"from": "UBE2I", "to": "KIF1B", "group": "default"}, {"from": "UBE2I", "to": "TNFRSF1A", "group": "default"}, {"from": "EEF1A1", "to": "VCAM1", "group": "default"}, {"from": "EEF1A1", "to": "KIF1B", "group": "default"}, {"from": "KDM5A", "to": "RBPJ", "group": "default"}, {"from": "KDM5A", "to": "VDR", "group": "default"}, {"from": "THOC2", "to": "VCAM1", "group": "default"}, {"from": "THOC2", "to": "KIF1B", "group": "default"}, {"from": "XPO1", "to": "RBPJ", "group": "default"}, {"from": "XPO1", "to": "VCAM1", "group": "default"}, {"from": "XPO1", "to": "RAP1GAP", "group": "default"}, {"from": "RPL4", "to": "APOE", "group": "default"}, {"from": "RPL4", "to": "ICAM1", "group": "default"}, {"from": "RPL4", "to": "VCAM1", "group": "default"}, {"from": "TOP1", "to": "NLRP3", "group": "default"}, {"from": "TOP1", "to": "IL7R", "group": "default"}, {"from": "TOP1", "to": "IRF8", "group": "default"}, {"from": "YWHAE", "to": "TNFAIP3", "group": "default"}, {"from": "YWHAE", "to": "HLA-DRA", "group": "default"}, {"from": "YWHAE", "to": "KIF1B", "group": "default"}, {"from": "CHUK", "to": "CD40", "group": "default"}, {"from": "CHUK", "to": "TNFRSF1A", "group": "default"}, {"from": "HSP90AB1", "to": "HLA-DRA", "group": "default"}, {"from": "HSP90AB1", "to": "VCAM1", "group": "default"}, {"from": "CD6", "to": "MYC", "group": "default"}, {"from": "TYK2", "to": "COPS5", "group": "default"}, {"from": "TYK2", "to": "IFNAR1", "group": "default"}, {"from": "TYK2", "to": "TRIM28", "group": "default"}, {"from": "TYK2", "to": "LGALS3BP", "group": "default"}, {"from": "TYK2", "to": "FYN", "group": "default"}, {"from": "TYK2", "to": "CBL", "group": "default"}, {"from": "TYK2", "to": "LRP8", "group": "default"}, {"from": "FSTL1", "to": "IL12A", "group": "default"}, {"from": "FSTL1", "to": "DEFA1", "group": "default"}, {"from": "CBL", "to": "IRF8", "group": "default"}, {"from": "CBL", "to": "TNFRSF1A", "group": "default"}, {"from": "NR2F2", "to": "RBPJ", "group": "default"}, {"from": "NR2F2", "to": "GC", "group": "default"}, {"from": "RUNX1T1", "to": "VDR", "group": "default"}, {"from": "RUNX1T1", "to": "RBPJ", "group": "default"}, {"from": "MED23", "to": "RBPJ", "group": "default"}, {"from": "MED23", "to": "VDR", "group": "default"}, {"from": "IFNAR1", "to": "IFNB1", "group": "default"}, {"from": "LCOR", "to": "RBPJ", "group": "default"}, {"from": "LCOR", "to": "VDR", "group": "default"}, {"from": "IL10", "to": "A2M", "group": "default"}, {"from": "NLRP3", "to": "FAF1", "group": "default"}, {"from": "NLRP3", "to": "YBX3", "group": "default"}, {"from": "NLRP3", "to": "HNRNPC", "group": "default"}, {"from": "NLRP3", "to": "SNRPB", "group": "default"}, {"from": "NLRP3", "to": "NLRC4", "group": "default"}, {"from": "NLRP3", "to": "HIST1H1B", "group": "default"}, {"from": "NLRP3", "to": "SMARCA5", "group": "default"}, {"from": "NLRP3", "to": "HSP90AA1", "group": "default"}, {"from": "A2M", "to": "IL1B", "group": "default"}, {"from": "A2M", "to": "APOE", "group": "default"}, {"from": "EIF4A1", "to": "VCAM1", "group": "default"}, {"from": "EIF4A1", "to": "KIF1B", "group": "default"}, {"from": "HSPA4", "to": "CD40", "group": "default"}, {"from": "HSPA4", "to": "KCNJ10", "group": "default"}, {"from": "ACTB", "to": "GC", "group": "default"}, {"from": "ACTB", "to": "ICAM1", "group": "default"}, {"from": "SNRPB", "to": "ICAM1", "group": "default"}, {"from": "KIF1B", "to": "YWHAH", "group": "default"}, {"from": "KIF1B", "to": "GOPC", "group": "default"}, {"from": "KIF1B", "to": "YWHAG", "group": "default"}, {"from": "KIF1B", "to": "SIAH1", "group": "default"}, {"from": "KIF1B", "to": "SEC24A", "group": "default"}, {"from": "KIF1B", "to": "BRCA1", "group": "default"}, {"from": "KIF1B", "to": "YWHAB", "group": "default"}, {"from": "KIF1B", "to": "ELAVL1", "group": "default"}, {"from": "HIST1H1B", "to": "VCAM1", "group": "default"}, {"from": "EFNB3", "to": "P2RX7", "group": "default"}, {"from": "ERP44", "to": "CD40", "group": "default"}, {"from": "ERP44", "to": "IL12B", "group": "default"}, {"from": "HSP90AA1", "to": "TNFAIP3", "group": "default"}, {"from": "HSP90AA1", "to": "HLA-DRA", "group": "default"}, {"from": "KIF2C", "to": "RBPJ", "group": "default"}, {"from": "KIF2C", "to": "TNFRSF1A", "group": "default"}, {"from": "KCNJ10", "to": "HSPA8", "group": "default"}, {"from": "KCNJ10", "to": "APP", "group": "default"}, {"from": "KCNJ10", "to": "BAG1", "group": "default"}, {"from": "KCNJ10", "to": "SNTA1", "group": "default"}, {"from": "KCNJ10", "to": "SIAH1", "group": "default"}, {"from": "KCNJ10", "to": "SEC24A", "group": "default"}, {"from": "APOE", "to": "LRP2", "group": "default"}, {"from": "APOE", "to": "ELAVL1", "group": "default"}, {"from": "APOE", "to": "HLA-DPA1", "group": "default"}, {"from": "APOE", "to": "CSNK2A1", "group": "default"}, {"from": "APOE", "to": "PCMT1", "group": "default"}, {"from": "APOE", "to": "LRP8", "group": "default"}, {"from": "APOE", "to": "PRDX2", "group": "default"}, {"from": "APOE", "to": "VDAC1", "group": "default"}, {"from": "RNF14", "to": "TNFAIP3", "group": "default"}, {"from": "RNF14", "to": "VDR", "group": "default"}, {"from": "TM9SF1", "to": "P2RX7", "group": "default"}, {"from": "TRIM28", "to": "STAT4", "group": "default"}, {"from": "TRIM28", "to": "VCAM1", "group": "default"}, {"from": "RIPK2", "to": "CASP1", "group": "default"}, {"from": "RIPK2", "to": "TNFRSF1A", "group": "default"}, {"from": "RIPK2", "to": "CD40", "group": "default"}, {"from": "IL1R1", "to": "IL1RN", "group": "default"}, {"from": "IL1R1", "to": "IL1B", "group": "default"}, {"from": "IL1B", "to": "ELAVL1", "group": "default"}, {"from": "IL1B", "to": "APP", "group": "default"}, {"from": "IL1B", "to": "CASP1", "group": "default"}, {"from": "IL1B", "to": "FYN", "group": "default"}, {"from": "PRDX2", "to": "VCAM1", "group": "default"}, {"from": "GOPC", "to": "IFNG", "group": "default"}, {"from": "ARHGEF7", "to": "CBLB", "group": "default"}, {"from": "ARHGEF7", "to": "ICAM1", "group": "default"}, {"from": "CASK", "to": "P2RX7", "group": "default"}, {"from": "MYC", "to": "VDR", "group": "default"}, {"from": "MYC", "to": "RBPJ", "group": "default"}, {"from": "SNW1", "to": "RBPJ", "group": "default"}, {"from": "SNW1", "to": "VDR", "group": "default"}, {"from": "KRT31", "to": "P2RX7", "group": "default"}, {"from": "TSSC1", "to": "CLEC16A", "group": "default"}, {"from": "LRP2", "to": "GC", "group": "default"}, {"from": "VCAM1", "to": "VCL", "group": "default"}, {"from": "VCAM1", "to": "CPSF7", "group": "default"}, {"from": "VCAM1", "to": "MLLT4", "group": "default"}, {"from": "VCAM1", "to": "UBR4", "group": "default"}, {"from": "VCAM1", "to": "SND1", "group": "default"}, {"from": "VCAM1", "to": "PCMT1", "group": "default"}, {"from": "VCAM1", "to": "VDAC1", "group": "default"}, {"from": "VCAM1", "to": "YWHAB", "group": "default"}, {"from": "VCAM1", "to": "PSMC5", "group": "default"}, {"from": "VCAM1", "to": "SF1", "group": "default"}, {"from": "CRK", "to": "STAT4", "group": "default"}, {"from": "CRK", "to": "CBLB", "group": "default"}, {"from": "LGALS3BP", "to": "SELE", "group": "default"}, {"from": "MLLT4", "to": "F11R", "group": "default"}, {"from": "MLLT4", "to": "RAP1GAP", "group": "default"}, {"from": "BRCA1", "to": "CASP1", "group": "default"}, {"from": "BRCA1", "to": "VDR", "group": "default"}, {"from": "IL7R", "to": "YBX3", "group": "default"}, {"from": "IL7R", "to": "HNRNPC", "group": "default"}, {"from": "IL7R", "to": "SF1", "group": "default"}, {"from": "BAG1", "to": "VDR", "group": "default"}, {"from": "RAB3B", "to": "IL12A", "group": "default"}, {"from": "RAB3B", "to": "SLAMF1", "group": "default"}, {"from": "MAPK1", "to": "VDR", "group": "default"}, {"from": "MAPK1", "to": "TNFRSF1A", "group": "default"}, {"from": "CPSF7", "to": "BCHE", "group": "default"}, {"from": "STAT1", "to": "VDR", "group": "default"}, {"from": "STAT1", "to": "TNFRSF1A", "group": "default"}, {"from": "HLA-DPB1", "to": "HLA-DPA1", "group": "default"}, {"from": "NCOR2", "to": "RBPJ", "group": "default"}, {"from": "NCOR2", "to": "VDR", "group": "default"}, {"from": "IL7", "to": "APP", "group": "default"}, {"from": "TNFAIP3", "to": "TNFRSF1A", "group": "default"}, {"from": "TNFAIP3", "to": "YWHAH", "group": "default"}, {"from": "TNFAIP3", "to": "YWHAG", "group": "default"}, {"from": "TNFAIP3", "to": "TP53", "group": "default"}, {"from": "TNFAIP3", "to": "KIF11", "group": "default"}, {"from": "RNF31", "to": "CD40", "group": "default"}, {"from": "RNF31", "to": "TNFRSF1A", "group": "default"}, {"from": "IRF8", "to": "COPS5", "group": "default"}, {"from": "IRF8", "to": "RELA", "group": "default"}, {"from": "IRF8", "to": "PDGFRB", "group": "default"}, {"from": "IRF8", "to": "COPS2", "group": "default"}, {"from": "IRF8", "to": "TRAF6", "group": "default"}, {"from": "PTPN11", "to": "CBLB", "group": "default"}, {"from": "PTPN11", "to": "SELE", "group": "default"}, {"from": "CLEC16A", "to": "RNF41", "group": "default"}, {"from": "CLEC16A", "to": "WRAP73", "group": "default"}, {"from": "CLEC16A", "to": "RAB39B", "group": "default"}, {"from": "BIRC3", "to": "CASP1", "group": "default"}, {"from": "BIRC3", "to": "TNFRSF1A", "group": "default"}, {"from": "DEFA1", "to": "BCHE", "group": "default"}, {"from": "POMC", "to": "APP", "group": "default"}, {"from": "POMC", "to": "UBR4", "group": "default"}, {"from": "SMARCA5", "to": "RBPJ", "group": "default"}, {"from": "ADRB2", "to": "STAT4", "group": "default"}, {"from": "ADRB2", "to": "MCAM", "group": "default"}, {"from": "COPS2", "to": "VDR", "group": "default"}, {"from": "TRAF3IP2", "to": "CD40", "group": "default"}, {"from": "TRAF3IP2", "to": "IL17A", "group": "default"}, {"from": "RBPJ", "to": "SND1", "group": "default"}, {"from": "RBPJ", "to": "APP", "group": "default"}, {"from": "NCOA6", "to": "CD40", "group": "default"}, {"from": "NCOA6", "to": "VDR", "group": "default"}, {"from": "CD58", "to": "LGALS8", "group": "default"}, {"from": "CD58", "to": "APP", "group": "default"}, {"from": "KRTAP10-8", "to": "P2RX7", "group": "default"}, {"from": "FYN", "to": "MCAM", "group": "default"}, {"from": "FYN", "to": "TNFRSF1A", "group": "default"}, {"from": "FYN", "to": "CBLB", "group": "default"}, {"from": "GNAI2", "to": "CNR1", "group": "default"}, {"from": "CBLB", "to": "PDGFRB", "group": "default"}, {"from": "CBLB", "to": "GRB2", "group": "default"}, {"from": "CBLB", "to": "TRAF6", "group": "default"}, {"from": "IL2RA", "to": "ICAM1", "group": "default"}, {"from": "IL2RA", "to": "SNTA1", "group": "default"}, {"from": "CCND3", "to": "GC", "group": "default"}, {"from": "CCND3", "to": "VDR", "group": "default"}, {"from": "MCAM", "to": "LGALS8", "group": "default"}, {"from": "YBX3", "to": "ICAM1", "group": "default"}, {"from": "IL1RN", "to": "RELA", "group": "default"}, {"from": "FAF1", "to": "CD40", "group": "default"}, {"from": "SPDL1", "to": "IL12A", "group": "default"}, {"from": "IL12A", "to": "F11R", "group": "default"}, {"from": "IL12A", "to": "COL14A1", "group": "default"}, {"from": "IL12A", "to": "IL12B", "group": "default"}, {"from": "GNAI3", "to": "CNR1", "group": "default"}, {"from": "VDR", "to": "JUN", "group": "default"}, {"from": "VDR", "to": "TP53", "group": "default"}, {"from": "VDR", "to": "PSMC5", "group": "default"}, {"from": "TNFRSF1A", "to": "HSPA8", "group": "default"}, {"from": "TNFRSF1A", "to": "TRAF6", "group": "default"}, {"from": "TNFRSF1A", "to": "GRB2", "group": "default"}, {"from": "TNFRSF1A", "to": "CASP10", "group": "default"}, {"from": "CD40", "to": "MS4A1", "group": "default"}, {"from": "RAP1GAP", "to": "CNR1", "group": "default"}, {"from": "SELE", "to": "ACTA2", "group": "default"}, {"from": "SELE", "to": "VCL", "group": "default"}, {"from": "SELE", "to": "FLNA", "group": "default"}, {"from": "IFI16", "to": "ICAM1", "group": "default"}, {"from": "IFI16", "to": "CASP1", "group": "default"}, {"from": "IL17A", "to": "TRAF6", "group": "default"}, {"from": "KIF11", "to": "CASP1", "group": "default"}, {"from": "GRB2", "to": "GC", "group": "default"}, {"from": "CNR1", "to": "GNAI1", "group": "default"}, {"from": "HSPA8", "to": "HLA-DRA", "group": "default"}, {"from": "STAT4", "to": "JUN", "group": "default"}, {"from": "ACTA2", "to": "GC", "group": "default"}, {"from": "FLNA", "to": "ICAM1", "group": "default"}, {"from": "CSNK2A1", "to": "ICAM1", "group": "default"}, {"from": "SLAMF1", "to": "BCHE", "group": "default"}, {"from": "HLA-DRA", "to": "MS4A1", "group": "default"}, {"from": "BCHE", "to": "SF1", "group": "default"}, {"from": "NLRC4", "to": "CASP1", "group": "default"}, {"from": "CASP10", "to": "CASP1", "group": "default"}]}' > </drugst-one>