Skip to content
Snippets Groups Projects
Commit da5b8596 authored by Julian Matschinske's avatar Julian Matschinske Committed by Julian Späth
Browse files

Adapt Analysis Window

parent d184e0cd
Branches
Tags
No related merge requests found
Showing
with 181 additions and 179 deletions
...@@ -62,6 +62,10 @@ export class AnalysisService { ...@@ -62,6 +62,10 @@ export class AnalysisService {
return this.selectedProteins.has(protein.proteinAc); return this.selectedProteins.has(protein.proteinAc);
} }
idInSelection(id: string): boolean {
return this.selectedProteins.has(id);
}
removeProtein(protein: Protein) { removeProtein(protein: Protein) {
if (this.selectedProteins.delete(`${protein.proteinAc}`)) { if (this.selectedProteins.delete(`${protein.proteinAc}`)) {
this.selectSubject.next({protein, selected: false}); this.selectSubject.next({protein, selected: false});
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
</button> </button>
</p> </p>
<p class="control"> <p class="control">
<button class="button is-danger is-rounded" (click)="analysis.removeTask(token)"> <button class="button is-danger is-rounded" (click)="analysis.removeTask(token); close()">
<span class="icon"> <span class="icon">
<i class="fas fa-trash" aria-hidden="true"></i> <i class="fas fa-trash" aria-hidden="true"></i>
</span> </span>
......
...@@ -12,7 +12,7 @@ import { ...@@ -12,7 +12,7 @@ import {
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
import {environment} from '../../../environments/environment'; import {environment} from '../../../environments/environment';
import {AnalysisService} from '../../analysis.service'; import {AnalysisService} from '../../analysis.service';
import {Protein, Task} from '../../interfaces'; import {Protein, Task, NodeType} from '../../interfaces';
declare var vis: any; declare var vis: any;
...@@ -34,7 +34,6 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -34,7 +34,6 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
private nodeData: { nodes: any, edges: any } = {nodes: null, edges: null}; private nodeData: { nodes: any, edges: any } = {nodes: null, edges: null};
private drugNodes = []; private drugNodes = [];
public showDrugs = false; public showDrugs = false;
private result: any;
constructor(private http: HttpClient, public analysis: AnalysisService) { constructor(private http: HttpClient, public analysis: AnalysisService) {
} }
...@@ -51,57 +50,33 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -51,57 +50,33 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
this.task = await this.getTask(this.token); this.task = await this.getTask(this.token);
if (this.task && this.task.info.done) { if (this.task && this.task.info.done) {
const result = await this.http.get<any>(`${environment.backend}result/?token=${this.token}`).toPromise(); const result = await this.http.get<any>(`${environment.backend}task_result/?token=${this.token}`).toPromise();
this.result = result;
// Reset
this.nodeData = {nodes: null, edges: null};
this.networkEl.nativeElement.innerHTML = ''; this.networkEl.nativeElement.innerHTML = '';
this.network = null; this.network = null;
this.showDrugs = false; this.showDrugs = false;
this.nodeData = {nodes: null, edges: null};
this.createNetwork(result);
}
}
}
private async getTask(token: string): Promise<any> {
return await this.http.get(`${environment.backend}task/?token=${token}`).toPromise();
}
close() {
this.token = null;
this.tokenChange.emit(this.token);
}
discard() {
}
export() { // Create
const {nodes, edges} = this.createNetwork(result);
}
public async createNetwork(result: any) {
const {nodes, edges} = this.mapDataToNodes(result);
this.nodeData.nodes = new vis.DataSet(nodes); this.nodeData.nodes = new vis.DataSet(nodes);
this.nodeData.edges = new vis.DataSet(edges); this.nodeData.edges = new vis.DataSet(edges);
const container = this.networkEl.nativeElement; const container = this.networkEl.nativeElement;
const options = { const options = {};
layout: {
improvedLayout: false,
},
};
this.network = new vis.Network(container, this.nodeData, options); this.network = new vis.Network(container, this.nodeData, options);
this.network.on('select', (properties) => { this.network.on('select', (properties) => {
const id: Array<string> = properties.nodes; const selectedNodes = this.nodeData.nodes.get(properties.nodes);
if (id.length > 0) { if (selectedNodes.length > 0) {
if (id[0].startsWith('p_')) { if (selectedNodes[0].nodeType === 'host') {
const protein = this.getProtein(id[0].substr(2)); const protein: Protein = {name: '', proteinAc: selectedNodes[0].id};
if (properties.event.srcEvent.ctrlKey) { if (properties.event.srcEvent.ctrlKey) {
if (this.inSelection(protein.proteinAc) === true) { if (this.analysis.inSelection(protein) === true) {
this.removeFromSelection(protein.proteinAc); this.analysis.removeProtein(protein);
} else { } else {
this.addToSelection(protein.proteinAc); this.analysis.addProtein(protein);
this.analysis.getCount(); this.analysis.getCount();
} }
} }
...@@ -110,7 +85,7 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -110,7 +85,7 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
}); });
this.analysis.subscribe((protein, selected) => { this.analysis.subscribe((protein, selected) => {
const nodeId = `p_${protein.proteinAc}`; const nodeId = `${protein.proteinAc}`;
const node = this.nodeData.nodes.get(nodeId); const node = this.nodeData.nodes.get(nodeId);
if (!node) { if (!node) {
return; return;
...@@ -118,122 +93,117 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -118,122 +93,117 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
const pos = this.network.getPositions([nodeId]); const pos = this.network.getPositions([nodeId]);
node.x = pos[nodeId].x; node.x = pos[nodeId].x;
node.y = pos[nodeId].y; node.y = pos[nodeId].y;
if (selected) { const {color} = this.getNodeLooks(nodeId, node.nodeType, node.isSeed);
node.color = '#48C774'; node.color = color;
this.nodeData.nodes.update(node);
} else {
node.color = '#e2b600';
this.nodeData.nodes.update(node); this.nodeData.nodes.update(node);
}
}); });
} }
inSelection(proteinAc: string): boolean {
if (!this.result.proteins || !proteinAc) {
return false;
}
const protein = this.getProtein(proteinAc);
if (!protein) {
return false;
} }
return this.analysis.inSelection(protein);
} }
addToSelection(proteinAc: string) { private async getTask(token: string): Promise<any> {
if (!this.result.proteins || !proteinAc) { return await this.http.get(`${environment.backend}task/?token=${token}`).toPromise();
return false;
} }
const protein = this.getProtein(proteinAc);
if (!protein) { close() {
return false; this.token = null;
this.tokenChange.emit(this.token);
} }
this.analysis.addProtein(protein);
discard() {
} }
removeFromSelection(proteinAc: string) { export() {
if (!this.result.proteins || !proteinAc) {
return false;
} }
const protein = this.getProtein(proteinAc);
if (!protein) { public inferNodeType(nodeId: string): 'host' | 'virus' | 'drug' {
return false; if (nodeId.indexOf('-') !== -1 || nodeId.indexOf('_') !== -1) {
return 'virus';
} }
this.analysis.removeProtein(protein); return 'host';
} }
public getProtein(ac: string): Protein | undefined { public createNetwork(result: any): { edges: any[], nodes: any[] } {
return this.result.proteins.find((p) => p.proteinAc === ac); const nodes = [];
} const edges = [];
const nodeAttributes = result.nodeAttributes || [];
private mapProteinToNode(protein: any): any { for (let i = 0; i < result.networks.length; i++) {
let color = '#e2b600'; const network = result.networks[i];
if (this.analysis.inSelection(protein)) {
color = '#48C774';
}
return {
id: `p_${protein.proteinAc}`,
label: `${protein.proteinAc}`,
size: 10, color, shape: 'ellipse', shadow: false,
};
}
private mapDrugToNode(drug: any): any { const attributes = nodeAttributes[i] || {};
let color = '#ffffff'; const nodeTypes = attributes.nodeTypes || {};
if (drug.status === 'investigational') { const isSeed = attributes.isSeed || {};
color = '#ffa066'; const scores = attributes.scores || {};
} else if (drug.status === 'approved') {
color = '#a0ff66'; for (const node of network.nodes) {
} nodes.push(this.mapNode(node, nodeTypes[node] || this.inferNodeType(node), isSeed[node], scores[node]));
return {
id: `d_${drug.drugId}`,
label: `${drug.name}`,
size: 10, color, shape: 'ellipse', shadow: true, font: {color: '#000000', size: 5},
};
} }
private mapProteinProteinInteractionToEdge(edge: any): any { for (const edge of network.edges) {
return { edges.push(this.mapEdge(edge));
from: `p_${edge.from}`, }
to: `p_${edge.to}`,
color: {color: '#afafaf', highlight: '#854141'},
};
} }
private mapDrugProteinInteractionToEdge(edge: any): any {
return { return {
from: `p_${edge.proteinAc}`, nodes,
to: `d_${edge.drugId}`, edges,
color: {color: '#afafaf', highlight: '#854141'},
}; };
} }
private mapDataToNodes(result: any): { nodes: any[], edges: any[] } { private getNodeLooks(nodeId: string, nodeType: NodeType, isSeed: boolean):
const nodes = []; { color: string, shape: string, size: number, font: any, shadow: boolean } {
const edges = []; let color = '';
let shape = '';
let size = 10;
let font = {};
let shadow = false;
for (const protein of result.proteins) { if (nodeType === 'host') {
nodes.push(this.mapProteinToNode(protein)); shape = 'ellipse';
if (this.analysis.idInSelection(nodeId)) {
color = '#c7661c';
} else {
color = '#e2b600';
} }
size = 10;
this.drugNodes = []; } else if (nodeType === 'virus') {
for (const drug of result.drugs) { shape = 'box';
this.drugNodes.push(this.mapDrugToNode(drug)); color = '#118AB2';
size = 12;
font = {color: 'white'};
shadow = true;
} else if (nodeType === 'drug') {
shape = 'ellipse';
color = '#26b28b';
size = 6;
} }
for (const network of result.networks) { if (isSeed) {
for (const edge of network.ppEdges) { color = '#c064c7';
edges.push(this.mapProteinProteinInteractionToEdge(edge));
} }
return {color, shape, size, font, shadow};
} }
for (const edge of result.dpEdges) { private mapNode(nodeId: any, nodeType?: NodeType, isSeed?: boolean, score?: number): any {
edges.push(this.mapDrugProteinInteractionToEdge(edge)); const {shape, color, size, font, shadow} = this.getNodeLooks(nodeId, nodeType, isSeed);
return {
id: nodeId,
label: nodeId,
size, color, shape, font, shadow,
nodeType, isSeed,
};
} }
private mapEdge(edge: any): any {
return { return {
nodes, from: `${edge.from}`,
edges, to: `${edge.to}`,
color: {color: '#afafaf', highlight: '#854141'},
}; };
} }
......
...@@ -30,7 +30,6 @@ export class LaunchAnalysisComponent implements OnInit { ...@@ -30,7 +30,6 @@ export class LaunchAnalysisComponent implements OnInit {
public multisteinerStrain = 'SARS_CoV2'; public multisteinerStrain = 'SARS_CoV2';
public multisteinerNumTrees = 5; public multisteinerNumTrees = 5;
constructor(public analysis: AnalysisService) { constructor(public analysis: AnalysisService) {
} }
...@@ -44,13 +43,13 @@ export class LaunchAnalysisComponent implements OnInit { ...@@ -44,13 +43,13 @@ export class LaunchAnalysisComponent implements OnInit {
public async startTask() { public async startTask() {
const parameters: any = { const parameters: any = {
proteins: this.analysis.getSelection().map((protein) => protein.proteinAc), seeds: this.analysis.getSelection().map((protein) => protein.proteinAc),
}; };
if (this.algorithm === 'dummy') { if (this.algorithm === 'dummy') {
// No parameters for dummy // No parameters for dummy
} else if (this.algorithm === 'trustrank') { } else if (this.algorithm === 'trustrank') {
parameters.strain = this.trustrankStrain; parameters.strain_or_drugs = this.trustrankStrain;
parameters.datasets = []; parameters.datasets = [];
parameters.ignored_edge_types = []; parameters.ignored_edge_types = [];
parameters.damping_factor = this.trustrankDampingFactor; parameters.damping_factor = this.trustrankDampingFactor;
......
<div class="content"> <div class="content">
<ng-select [items]="datasetItems" bindLabel="label" [virtualScroll]="true" class="custom" <ng-select [items]="datasetItems" bindLabel="id" [virtualScroll]="true" class="custom"
placeholder="Select..." [ngModel]="selectedDataset" (ngModelChange)="select($event)"> placeholder="Select..." [ngModel]="selectedDataset" (ngModelChange)="select($event)">
<ng-template ng-option-tmp let-item="item"> <ng-template ng-option-tmp let-item="item">
{{item.label}} <br/> {{item.label}} <br/>
......
...@@ -14,10 +14,8 @@ export class SelectDatasetComponent { ...@@ -14,10 +14,8 @@ export class SelectDatasetComponent {
@Input() datasetItems: Array<{label: string, datasets: string, data: Array<[string, string]>}>; @Input() datasetItems: Array<{label: string, datasets: string, data: Array<[string, string]>}>;
public select(selectionItem) { public select(selectionItem) {
// console.log(selectionItem);
this.selectedDataset = selectionItem; this.selectedDataset = selectionItem;
this.selectedDatasetChange.emit(selectionItem); this.selectedDatasetChange.emit(selectionItem);
} }
} }
...@@ -2,26 +2,41 @@ ...@@ -2,26 +2,41 @@
<div class="list is-hoverable"> <div class="list is-hoverable">
<a *ngFor="let task of analysis.tasks" class="list-item" [class.is-active]="task.token === token"> <a *ngFor="let task of analysis.tasks" class="list-item" [class.is-active]="task.token === token">
<div *ngIf="!task.info.startedAt" (click)="open(task.token)"> <div *ngIf="!task.info.startedAt" (click)="open(task.token)">
<span><b>{{task.info.algorithm}} (Queued)</b></span> <p>
<span class="icon"><i class="fas fa-pause" aria-hidden="true"></i></span><br> <span class="is-capitalized">{{task.info.algorithm}}</span>
Queue Length: {{task.stats.queueLength}}<br> <span class="icon is-pulled-right"><i class="fas fa-pause" aria-hidden="true"></i></span>
Queue Position:{{task.stats.queuePosition}} </p>
<p>
<small>Queue position: {{task.stats.queuePosition}}/{{task.stats.queueLength}}</small>
</p>
</div> </div>
<div *ngIf="task.info.startedAt && !task.info.done && !task.info.failed" (click)="open(task.token)"> <div *ngIf="!task.info.done && !task.info.failed && task.info.startedAt" (click)="open(task.token)">
<span><b>{{task.info.algorithm}} ({{task.info.startedAt | date :'short'}})</b></span> <p>
<span class="icon"><i class="fas fa-spinner" aria-hidden="true"></i></span> <span class="is-capitalized">{{task.info.algorithm}}</span>
<br> <span class="icon is-pulled-right"><i class="fas fa-spinner fa-spin" aria-hidden="true"></i></span>
<progress class="progress is-primary" [value]="task.info.progress * 100" max="100"></progress> </p>
<p>
<small>Started {{task.info.startedAt | date :'short'}}</small>
</p>
<progress class="progress is-primary" [value]="task.info.progress * 100" max="100">Test</progress>
</div> </div>
<div *ngIf="task.info.failed && task.info.finishedAt == null"> <div *ngIf="task.info.done" (click)="open(task.token)">
<span><b>{{task.info.algorithm}} ({{task.info.startedAt | date :'short'}})</b></span> <p>
<span class="icon"><i class="fas fa-exclamation-triangle" aria-hidden="true"></i> <span class="is-capitalized">{{task.info.algorithm}}</span>
</span> <span class="icon is-pulled-right"><i class="fas fa-check" aria-hidden="true"></i></span>
</p>
<p>
<small>Finished {{task.info.finishedAt | date :'short'}}</small>
</p>
</div> </div>
<div *ngIf="task.info.done && !task.info.failed" (click)="open(task.token)"> <div *ngIf="task.info.failed && task.info.finishedAt == null">
<span><b>{{task.info.algorithm}} ({{task.info.startedAt | date :'short'}})</b></span> <p>
<span class="icon"><i class="fas fa-check" aria-hidden="true"></i> <span class="is-capitalized">{{task.info.algorithm}}</span>
</span> <span class="icon is-pulled-right"><i class="fas fa-exclamation-triangle" aria-hidden="true"></i></span>
</p>
<p class="has-text-danger">
<small>{{task.info.status}}</small>
</p>
</div> </div>
</a> </a>
</div> </div>
......
.list {
p {
margin-bottom: 0;
}
progress {
margin-top: 5px;
margin-bottom: 5px;
}
}
export type NodeType = 'host' | 'virus' | 'drug';
export interface Protein { export interface Protein {
name: string; name: string;
proteinAc: string; proteinAc: string;
...@@ -25,7 +27,7 @@ export interface ProteinViralInteraction { ...@@ -25,7 +27,7 @@ export interface ProteinViralInteraction {
export interface Task { export interface Task {
token: string; token: string;
info: { info: {
algorithm: string; algorithm: 'trustrank' | 'multisteiner' | 'keypathwayminer';
parameters?: { [key: string]: any }; parameters?: { [key: string]: any };
workerId?: string; workerId?: string;
......
...@@ -281,7 +281,7 @@ ...@@ -281,7 +281,7 @@
<app-task-list [(token)]="selectedAnalysisToken"></app-task-list> <app-task-list [(token)]="selectedAnalysisToken"></app-task-list>
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
<a (click)="analysis.removeAllTasks();" class="card-footer-item has-text-danger"> <a (click)="analysis.removeAllTasks(); selectedAnalysisToken = null;" class="card-footer-item has-text-danger">
<span class="icon"> <span class="icon">
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
</span> </span>
......
...@@ -58,15 +58,19 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -58,15 +58,19 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
public currentDataset = []; public currentDataset = [];
private screenshotArray = [0]; private screenshotArray = [0];
public datasetItems: Array<{ label: string, datasets: string, data: Array<[string, string]> }> = [ public datasetItems: Array<{ id: string, label: string, datasets: string, data: Array<[string, string]> }> = [
{label: 'All', datasets: 'TUM & Krogan', data: [['TUM', 'HCoV'], ['TUM', 'SARS-CoV2'], ['Krogan', 'SARS-CoV2']]}, {
{label: 'HCoV', datasets: 'TUM', data: [['TUM', 'HCoV']]}, id: 'All (TUM & Krogan)',
{label: 'CoV2', datasets: 'TUM & Krogan', data: [['TUM', 'SARS-CoV2'], ['Krogan', 'SARS-CoV2']]}, label: 'All',
{label: 'CoV2', datasets: 'Krogan', data: [['Krogan', 'SARS-CoV2']]}, datasets: 'TUM & Krogan',
{label: 'CoV2', datasets: 'TUM', data: [['TUM', 'SARS-CoV2']]}]; data: [['TUM', 'HCoV'], ['TUM', 'SARS-CoV2'], ['Krogan', 'SARS-CoV2']]
},
public selectedDataset = this.datasetItems[0]; {id: 'HCoV (TUM)', label: 'HCoV', datasets: 'TUM', data: [['TUM', 'HCoV']]},
{id: 'CoV2 (TUM & Krogan)', label: 'CoV2', datasets: 'TUM & Krogan', data: [['TUM', 'SARS-CoV2'], ['Krogan', 'SARS-CoV2']]},
{id: 'CoV2 (Krogan)', label: 'CoV2', datasets: 'Krogan', data: [['Krogan', 'SARS-CoV2']]},
{id: 'CoV2 (TUM)', label: 'CoV2', datasets: 'TUM', data: [['TUM', 'SARS-CoV2']]}];
public selectedDataset = this.datasetItems[3];
@ViewChild('network', {static: false}) networkEl: ElementRef; @ViewChild('network', {static: false}) networkEl: ElementRef;
...@@ -132,8 +136,8 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -132,8 +136,8 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
async ngAfterViewInit() { async ngAfterViewInit() {
if (!this.network) { if (!this.network) {
this.selectedDataset = this.datasetItems[4]; this.selectedDataset = this.datasetItems[3];
await this.createNetwork(this.datasetItems[4].data); await this.createNetwork(this.selectedDataset.data);
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment