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

Merge branch 'scores' into 'master'

Scores

See merge request covid-19/frontend!60
parents 9245f123 b6dbd884
No related branches found
No related tags found
No related merge requests found
......@@ -101,58 +101,101 @@
</footer>
</div>
<div class="content tab-content scrollable" *ngIf="task && task.info.done" [class.is-visible]="tab === 'table'">
<h4 class="is-4" *ngIf="tableDrugs.length > 0">Drugs</h4>
<div class="field has-addons footer-toggle-buttons" *ngIf="tableHasScores">
<p class="control">
<button class="button is-rounded" [class.is-primary]="tableNormalize" (click)="toggleNormalization(true)">
<span class="icon is-small">
<i class="fa fa-ruler-vertical"></i>
</span>
<span>Normalization On</span>
</button>
</p>
<p class="control">
<button class="button is-rounded" [class.is-primary]="!tableNormalize" (click)="toggleNormalization(false)">
<span>Off</span>
</button>
</p>
</div>
<div *ngIf="tableDrugs.length > 0">
<h4 class="is-4">
<span class="icon"><i class="fa fa-capsules"></i></span>
<span>Drugs</span>
</h4>
<a [href]="downloadLink('drugs')" class="button is-primary is-outlined is-pulled-right is-small">
<span class="icon"><i class="fa fa-download"></i></span>
<span>Download</span>
</a>
</div>
<table class="table is-striped" *ngIf="tableDrugs.length > 0">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
<td>Status</td>
<td>Score</td>
<td *ngIf="tableHasScores">Score</td>
</tr>
</thead>
<tbody>
<tr *ngFor="let e of tableDrugs">
<td>{{e.drugId}}</td>
<td><a href="https://www.drugbank.ca/drugs/{{ e.drugId }}" target="_blank">{{ e.drugId }}</a></td>
<td>{{e.name}}</td>
<td>{{e.status}}</td>
<td>{{e.score}}</td>
<td *ngIf="tableHasScores">{{e.score}}</td>
</tr>
</tbody>
</table>
<h4 class="is-4" *ngIf="tableProteins.length > 0">Proteins</h4>
<div *ngIf="tableProteins.length > 0">
<h4 class="is-4">
<span class="icon"><i class="fa fa-dna"></i></span>
<span>Proteins</span>
</h4>
<a [href]="downloadLink('proteins')" class="button is-primary is-outlined is-pulled-right is-small">
<span class="icon"><i class="fa fa-download"></i></span>
<span>Download</span>
</a>
</div>
<table class="table is-striped" *ngIf="tableProteins.length > 0">
<thead>
<tr>
<td>AC</td>
<td>Gene</td>
<td>Score</td>
<td *ngIf="tableHasScores">Score</td>
</tr>
</thead>
<tbody>
<tr *ngFor="let e of tableProteins">
<td>{{e.proteinAc}}</td>
<td><a href="https://www.uniprot.org/uniprot/{{ e.proteinAc }}" target="_blank">{{ e.proteinAc }}</a></td>
<td>{{e.name}}</td>
<td>{{e.score}}</td>
<td *ngIf="tableHasScores">{{e.score}}</td>
</tr>
</tbody>
</table>
<h4 class="is-4" *ngIf="tableViralProteins.length > 0">Viral Proteins</h4>
<div *ngIf="tableViralProteins.length > 0">
<h4 class="is-4">
<span class="icon"><i class="fa fa-virus"></i></span>
<span>Viral Proteins</span>
</h4>
<a [href]="downloadLink('viral_proteins')" class="button is-primary is-outlined is-pulled-right is-small">
<span class="icon"><i class="fa fa-download"></i></span>
<span>Download</span>
</a>
</div>
<table class="table is-striped" *ngIf="tableViralProteins.length > 0">
<thead>
<tr>
<td>Name</td>
<td>Virus Strain</td>
<td>Score</td>
<td *ngIf="tableHasScores">Score</td>
</tr>
</thead>
<tbody>
<tr *ngFor="let e of tableViralProteins">
<td>{{e.effectName}}</td>
<td>{{e.virusName}}</td>
<td>{{e.score}}</td>
<td *ngIf="tableHasScores">{{e.score}}</td>
</tr>
</tbody>
</table>
......
......@@ -20,5 +20,10 @@ div.network {
&.scrollable {
overflow-y: auto;
padding-right: 10px;
}
h4 {
margin-top: 60px;
}
}
......@@ -17,6 +17,11 @@ import html2canvas from 'html2canvas';
declare var vis: any;
interface Scored {
score: number; // Normalized or unnormalized (whichever user selects, will be displayed in the table)
rawScore: number; // Unnormalized (kept to restore unnormalized value)
}
@Component({
selector: 'app-analysis-window',
templateUrl: './analysis-window.component.html',
......@@ -42,9 +47,11 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
public showDrugs = false;
public tab = 'network';
public tableDrugs: Array<any> = [];
public tableProteins: Array<any> = [];
public tableViralProteins: Array<any> = [];
public tableDrugs: Array<Drug & Scored> = [];
public tableProteins: Array<Protein & Scored> = [];
public tableViralProteins: Array<ViralProtein & Scored> = [];
public tableNormalize = false;
public tableHasScores = false;
constructor(private http: HttpClient, public analysis: AnalysisService) {
}
......@@ -74,45 +81,38 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
this.nodeData.nodes = new vis.DataSet(nodes);
this.nodeData.edges = new vis.DataSet(edges);
// Fill tables
result.networks.forEach((network, i) => {
const attributes = result.nodeAttributes[i];
const nodeTypes = attributes.nodeTypes || {};
const nodeDetails = attributes.details || {};
const nodeScores = attributes.scores || {};
const normalizeScore = network.maxScore || 1.0;
network.nodes.forEach((nodeId, j) => {
const nodeType = nodeTypes[nodeId] || this.inferNodeType(nodeId);
const entry = nodeDetails[nodeId] || {};
entry.score = nodeScores[nodeId] || null;
if (entry.score) {
entry.score /= normalizeScore;
}
switch (nodeType) {
case 'drug':
this.tableDrugs.push(entry);
break;
case 'host':
this.tableProteins.push(entry);
break;
case 'virus':
this.tableViralProteins.push(entry);
break;
}
});
});
this.tableDrugs = this.tableDrugs.reverse();
this.tableProteins = this.tableProteins.reverse();
this.tableViralProteins = this.tableViralProteins.reverse();
const container = this.networkEl.nativeElement;
const options = {};
this.network = new vis.Network(container, this.nodeData, options);
const promises: Promise<any>[] = [];
promises.push(this.http.get<any>(`${environment.backend}task_result/?token=${this.token}&view=proteins`).toPromise()
.then((table) => {
this.tableProteins = table;
this.tableProteins.forEach((r) => r.rawScore = r.score);
}));
promises.push(this.http.get<any>(`${environment.backend}task_result/?token=${this.token}&view=viral_proteins`).toPromise()
.then((table) => {
this.tableViralProteins = table;
this.tableViralProteins.forEach((r) => r.rawScore = r.score);
}));
promises.push(this.http.get<any>(`${environment.backend}task_result/?token=${this.token}&view=drugs`).toPromise()
.then((table) => {
this.tableDrugs = table;
this.tableDrugs.forEach((r) => r.rawScore = r.score);
}));
await Promise.all(promises);
this.tableHasScores = this.task.info.algorithm === 'trustrank';
if (this.tableHasScores) {
this.toggleNormalization(true);
}
this.network.on('deselectNode', (properties) => {
this.showDetailsChange.emit([false, [null, null, null, null, null, null]]);
});
this.network.on('selectNode', (properties) => {
const selectedNodes = this.nodeData.nodes.get(properties.nodes);
if (selectedNodes.length > 0) {
......@@ -169,7 +169,6 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
} else {
this.showDetailsChange.emit([false, [null, null, null, null, null, null]]);
}
});
this.analysis.subscribe((item, selected) => {
......@@ -206,6 +205,42 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
}
public toggleNormalization(normalize: boolean) {
this.tableNormalize = normalize;
const normalizeFn = (table) => {
let max = 0;
table.forEach(i => {
if (i.rawScore > max) {
max = i.rawScore;
}
});
table.forEach(i => {
i.score = i.rawScore / max;
});
};
const unnormalizeFn = (table) => {
table.forEach(i => {
i.score = i.rawScore;
});
};
if (normalize) {
normalizeFn(this.tableDrugs);
normalizeFn(this.tableProteins);
normalizeFn(this.tableViralProteins);
} else {
unnormalizeFn(this.tableDrugs);
unnormalizeFn(this.tableProteins);
unnormalizeFn(this.tableViralProteins);
}
}
public downloadLink(view: string): string {
return `${environment.backend}task_result/?token=${this.token}&view=${view}&fmt=csv`;
}
public inferNodeType(nodeId: string): 'host' | 'virus' | 'drug' {
if (nodeId.indexOf('-') !== -1 || nodeId.indexOf('_') !== -1) {
return 'virus';
......
......@@ -2,7 +2,7 @@ import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges
import {AnalysisService} from '../../analysis.service';
interface Algorithm {
slug: string;
slug: 'trustrank' | 'keypathwayminer' | 'multisteiner';
name: string;
}
......@@ -51,10 +51,12 @@ export class LaunchAnalysisComponent implements OnInit, OnChanges {
ngOnChanges(changes: SimpleChanges): void {
if (this.target === 'drug-target') {
this.algorithms = [TRUSTRANK, MULTISTEINER, KEYPATHWAYMINER];
this.algorithms = [MULTISTEINER, TRUSTRANK, KEYPATHWAYMINER];
this.algorithm = MULTISTEINER.slug;
this.trustrankStrain = 'SARS_CoV2';
} else if (this.target === 'drug') {
this.algorithms = [TRUSTRANK];
this.algorithm = TRUSTRANK.slug;
this.trustrankStrain = 'drugs';
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment