diff --git a/src/app/analysis.service.ts b/src/app/analysis.service.ts index a302c42ad6f56705a769774e796883779ed10cd3..d85b8c6734eb64d9ef7aa52d9489a669a189fc3e 100644 --- a/src/app/analysis.service.ts +++ b/src/app/analysis.service.ts @@ -92,9 +92,10 @@ export class AnalysisService { }); } - async startAnalysis(algorithm, parameters) { + async startAnalysis(algorithm, target: 'drug' | 'drug-target', parameters) { const resp = await this.http.post<any>(`${environment.backend}task/`, { algorithm, + target, parameters, }).toPromise(); this.tokens.push(resp.token); diff --git a/src/app/components/analysis-window/analysis-window.component.html b/src/app/components/analysis-window/analysis-window.component.html index ba091706768457771946e5dfb4fd0ffdabdcb7c6..b147c55efe656c72e8f528a8bfc389f3ffcc4726 100644 --- a/src/app/components/analysis-window/analysis-window.component.html +++ b/src/app/components/analysis-window/analysis-window.component.html @@ -1,5 +1,5 @@ <div *ngIf="token"> - <div class="card analysis" *ngIf="task && task.info.done"> + <div class="card analysis"> <header class="card-header"> <p class="card-header-title"> <span class="icon"> @@ -13,9 +13,36 @@ </span> </a> </header> - <div class="card-content"> - <div class="content"> + <div class="tabs is-centered"> + <ul> + <li [class.is-active]="tab === 'meta'"><a (click)="tab = 'meta'">Meta</a></li> + <li [class.is-active]="tab === 'network'"><a (click)="tab = 'network'">Network</a></li> + <li [class.is-active]="tab === 'table'"><a (click)="tab = 'table'">Table</a></li> + </ul> + </div> + <div class="content tab-content" *ngIf="task && task.info.done" [class.is-visible]="tab === 'meta'"> + <div *ngIf="task"> + <p> + Algorithm: {{task.info.algorithm}} + </p> + <div *ngIf="task.info.algorithm === 'trustrank'"> + <table class="table is-narrow"> + <tbody> + <tr> + <td>Damping Factor</td> + <td>{{task.info.parameters.dampingFactor}}</td> + </tr> + <tr> + <td>Result Size</td> + <td>{{task.info.parameters.resultSize}}</td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + <div class="content tab-content" *ngIf="task && task.info.done" [class.is-visible]="tab === 'network'"> <div class="card-image"> <div class="network center" #network> <button class="button is-loading center">Loading</button> @@ -71,79 +98,9 @@ </div> </footer> </div> - </div> - - <div class="card analysis" *ngIf="task && !task.info.startedAt"> - <header class="card-header"> - <p class="card-header-title"> - <span class="icon"> - <i class="fas fa-cog" aria-hidden="true"></i> - </span> - Analysis Queued... - </p> - <a (click)="close()" class="card-header-icon" aria-label="close"> - <span class="icon"> - <i class="fas fa-times" aria-hidden="true"></i> - </span> - </a> - </header> - <div class="card-content"> - <div class="content"> - The analysis is queued - <!--TODO: Display queue information--> - </div> - </div> - <footer class="card-footer"> - </footer> - </div> - - <div class="card analysis" *ngIf="task && task.info.startedAt && !task.info.done"> - <header class="card-header"> - <p class="card-header-title"> - <span class="icon"> - <i class="fas fa-cog fa-spin" aria-hidden="true"></i> - </span> - Analysis in Progress... - </p> - <a (click)="close()" class="card-header-icon" aria-label="close"> - <span class="icon"> - <i class="fas fa-times" aria-hidden="true"></i> - </span> - </a> - </header> - <div class="card-content"> - <div class="content"> - The analysis is in progress - <!--TODO: Display analysis progress--> - </div> - </div> - <footer class="card-footer"> - </footer> - </div> - - <div class="card analysis" *ngIf="!task"> - <header class="card-header"> - <p class="card-header-title"> - <span class="icon"> - <i class="fas fa-question" aria-hidden="true"></i> - </span> - Analysis not found - </p> - <a (click)="close()" class="card-header-icon" aria-label="more options"> - <span class="icon"> - <i class="fas fa-times" aria-hidden="true"></i> - </span> - </a> - </header> - <div class="card-content"> - <div class="content"> - <span class="notification is-danger"> - The analysis you were looking for is either gone or never existed. - </span> - </div> + <div class="content tab-content" *ngIf="task && task.info.done" [class.is-visible]="tab === 'table'"> + TABLE </div> - <footer class="card-footer"> - </footer> </div> </div> </div> diff --git a/src/app/components/analysis-window/analysis-window.component.scss b/src/app/components/analysis-window/analysis-window.component.scss index 4888ec899f7bbc18d0f23d308447415d8e5ac075..056832a086a4be55405c315ec225e0365fd83e22 100644 --- a/src/app/components/analysis-window/analysis-window.component.scss +++ b/src/app/components/analysis-window/analysis-window.component.scss @@ -3,3 +3,15 @@ height: 100%; width: 100%; } + +div.network { + height: calc(100vh - 210px - 80px); +} + +.tab-content { + visibility: hidden; + + &.is-visible { + visibility: visible; + } +} diff --git a/src/app/components/analysis-window/analysis-window.component.ts b/src/app/components/analysis-window/analysis-window.component.ts index b90fde8554d8d789621a83e7e71dc7785e28741c..ccc612efb07948e1ef6d8a6165d9f0208d207c03 100644 --- a/src/app/components/analysis-window/analysis-window.component.ts +++ b/src/app/components/analysis-window/analysis-window.component.ts @@ -12,7 +12,7 @@ import { import {HttpClient} from '@angular/common/http'; import {environment} from '../../../environments/environment'; import {AnalysisService} from '../../analysis.service'; -import {Protein, Task, NodeType, ViralProtein, QueryItem} from '../../interfaces'; +import {Protein, Task, NodeType, ViralProtein} from '../../interfaces'; declare var vis: any; @@ -24,12 +24,6 @@ declare var vis: any; export class AnalysisWindowComponent implements OnInit, OnChanges { @Input() token: string | null = null; - @Input() selectedProteinName: string; - @Input() selectedProteinType: string; - @Input() selectedProteinAc: string; - @Input() selectedProteinItem: QueryItem; - @Input() selectedProteinVirus: string; - @Input() selectedProteinDataset: string; @Output() tokenChange = new EventEmitter<string | null>(); @Output() showDetailsChange: EventEmitter<any> = new EventEmitter(); @@ -43,6 +37,7 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { private nodeData: { nodes: any, edges: any } = {nodes: null, edges: null}; private drugNodes = []; public showDrugs = false; + public tab = 'network'; constructor(private http: HttpClient, public analysis: AnalysisService) { } @@ -79,14 +74,20 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { this.network.on('selectNode', (properties) => { const selectedNodes = this.nodeData.nodes.get(properties.nodes); if (selectedNodes.length > 0) { + let selectedProteinItem; + let selectedProteinName; + let selectedProteinType; + let selectedProteinAc; + let selectedProteinDataset; + let selectedProteinVirus; if (selectedNodes[0].nodeType === 'host') { const protein: Protein = {name: '', proteinAc: selectedNodes[0].id}; - this.selectedProteinName = null; - this.selectedProteinDataset = null; - this.selectedProteinVirus = null; - this.selectedProteinItem = {name: selectedNodes[0].id, type: 'Host Protein', data: protein}; - this.selectedProteinAc = protein.proteinAc; - this.selectedProteinType = 'Host Protein'; + selectedProteinName = null; + selectedProteinDataset = null; + selectedProteinVirus = null; + selectedProteinItem = {name: selectedNodes[0].id, type: 'Host Protein', data: protein}; + selectedProteinAc = protein.proteinAc; + selectedProteinType = 'Host Protein'; if (properties.event.srcEvent.ctrlKey) { if (this.analysis.inSelection(protein.proteinAc)) { this.analysis.removeItem(protein.proteinAc); @@ -96,33 +97,26 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { } } } else if (selectedNodes[0].nodeType === 'virus') { - const virus: ViralProtein = {effectName: selectedNodes[0].id, virusName: null, datasetName: null}; - this.selectedProteinAc = null; - this.selectedProteinDataset = null; - this.selectedProteinVirus = null; - this.selectedProteinItem = {name: virus.effectName, type: 'Viral Protein', data: virus}; - this.selectedProteinName = virus.effectName; - this.selectedProteinType = 'Viral Protein'; + const virus: ViralProtein = {viralProteinId: null, effectName: selectedNodes[0].id, virusName: null, datasetName: null}; + selectedProteinAc = null; + selectedProteinDataset = null; + selectedProteinVirus = null; + selectedProteinItem = {name: virus.effectName, type: 'Viral Protein', data: virus}; + selectedProteinName = virus.effectName; + selectedProteinType = 'Viral Protein'; if (properties.event.srcEvent.ctrlKey) { if (this.analysis.inSelection(virus.effectName)) { this.analysis.removeItem(virus.effectName); } else { - this.analysis.addItem(this.selectedProteinItem); + this.analysis.addItem(selectedProteinItem); this.analysis.getCount(); } } } - this.showDetailsChange.emit([true, [this.selectedProteinItem, this.selectedProteinName, - this.selectedProteinType, this.selectedProteinAc, this.selectedProteinDataset, this.selectedProteinVirus]]); + this.showDetailsChange.emit([true, [selectedProteinItem, selectedProteinName, selectedProteinType, selectedProteinAc, + selectedProteinDataset, selectedProteinVirus]]); } else { - this.selectedProteinItem = null; - this.selectedProteinName = null; - this.selectedProteinType = null; - this.selectedProteinAc = null; - this.selectedProteinDataset = null; - this.selectedProteinVirus = null; - this.showDetailsChange.emit([false, [this.selectedProteinItem, this.selectedProteinName, - this.selectedProteinType, this.selectedProteinAc, this.selectedProteinDataset, this.selectedProteinVirus]]); + this.showDetailsChange.emit([false, [null, null, null, null, null, null]]); } }); diff --git a/src/app/components/launch-analysis/launch-analysis.component.html b/src/app/components/launch-analysis/launch-analysis.component.html index b85a31c9f1ccf8d3e2301785b4486d1d863f9258..54a64d53bca5d2ce661bd806b118d8a301bd3bf1 100644 --- a/src/app/components/launch-analysis/launch-analysis.component.html +++ b/src/app/components/launch-analysis/launch-analysis.component.html @@ -2,35 +2,32 @@ <div class="modal-background"></div> <div class="modal-card"> <header class="modal-card-head"> - <p class="modal-card-title">Launch Analysis</p> + <p class="modal-card-title" *ngIf="target === 'drug'"> + <span class="icon"><i class="fa fa-capsules"></i></span> + Find Drugs + </p> + <p class="modal-card-title" *ngIf="target === 'drug-target'"> + <span class="icon"><i class="fa fa-crosshairs"></i></span> + Find Drug Targets + </p> <button (click)="close()" class="delete" aria-label="close"></button> </header> <section class="modal-card-body"> <div class="tabs is-toggle is-small is-fullwidth is-rounded"> <ul> - <li [class.is-active]="algorithm === 'dummy'"> - <a (click)="algorithm = 'dummy'" class="is-boxed is-medium">Dummy</a> - </li> - <li [class.is-active]="algorithm === 'trustrank'"> - <a (click)="algorithm = 'trustrank'" class="is-boxed is-medium">Trustrank</a> - </li> - <li [class.is-active]="algorithm === 'keypathwayminer'"> - <a (click)="algorithm = 'keypathwayminer'" class="is-boxed is-medium">KeyPathwayMiner</a> - </li> - <li [class.is-active]="algorithm === 'multisteiner'"> - <a (click)="algorithm = 'multisteiner'" class="is-boxed is-medium">Multi-Steiner</a> + <li [class.is-active]="algorithm === algo.slug" *ngFor="let algo of algorithms"> + <a (click)="algorithm = algo.slug" class="is-boxed is-medium">{{algo.name}}</a> </li> </ul> </div> <div *ngIf="algorithm==='trustrank'"> - <div class="field"> + <div class="field" *ngIf="target === 'drug-target'"> <label class="label" for="trustrank-strain">Strain</label> <div class="control"> <div class="select"> <select id="trustrank-strain" [(ngModel)]="trustrankStrain"> <option [ngValue]="'SARS_CoV2'">SARS Coronavirus 2</option> - <option [ngValue]="'drugs'">Drugs</option> </select> </div> </div> diff --git a/src/app/components/launch-analysis/launch-analysis.component.ts b/src/app/components/launch-analysis/launch-analysis.component.ts index cb1f46e3108eaa6cac883814ed33a33351426fdd..fc743ec71e3aa78cfdd4dfc03a6fbc194b40281b 100644 --- a/src/app/components/launch-analysis/launch-analysis.component.ts +++ b/src/app/components/launch-analysis/launch-analysis.component.ts @@ -1,20 +1,34 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core'; import {AnalysisService} from '../../analysis.service'; +interface Algorithm { + slug: string; + name: string; +} + +const DUMMY: Algorithm = {slug: 'dummy', name: 'Dummy'}; +const TRUSTRANK: Algorithm = {slug: 'trustrank', name: 'Trust-Rank'}; +const KEYPATHWAYMINER: Algorithm = {slug: 'keypathwayminer', name: 'KeyPathwayMiner'}; +const MULTISTEINER: Algorithm = {slug: 'multisteiner', name: 'Multi-Steiner'}; + @Component({ selector: 'app-launch-analysis', templateUrl: './launch-analysis.component.html', styleUrls: ['./launch-analysis.component.scss'] }) -export class LaunchAnalysisComponent implements OnInit { +export class LaunchAnalysisComponent implements OnInit, OnChanges { @Input() public show = false; + @Input() + public target: 'drug' | 'drug-target'; @Output() public showChange = new EventEmitter<boolean>(); public algorithm: 'dummy' | 'trustrank' | 'keypathwayminer' | 'multisteiner'; + public algorithms: Array<Algorithm> = []; + // Trustrank Parameters public trustrankStrain = 'SARS_CoV2'; public trustrankDampingFactor = 0.85; @@ -36,6 +50,16 @@ export class LaunchAnalysisComponent implements OnInit { ngOnInit(): void { } + ngOnChanges(changes: SimpleChanges): void { + if (this.target === 'drug-target') { + this.algorithms = [TRUSTRANK, MULTISTEINER, KEYPATHWAYMINER, DUMMY]; + this.trustrankStrain = 'SARS_CoV2'; + } else if (this.target === 'drug') { + this.algorithms = [TRUSTRANK, DUMMY]; + this.trustrankStrain = 'drugs'; + } + } + public close() { this.show = false; this.showChange.emit(this.show); @@ -60,10 +84,9 @@ export class LaunchAnalysisComponent implements OnInit { } else if (this.algorithm === 'multisteiner') { parameters.strain = this.multisteinerStrain; parameters.num_trees = this.multisteinerNumTrees; - } - await this.analysis.startAnalysis(this.algorithm, parameters); + await this.analysis.startAnalysis(this.algorithm, this.target, parameters); } } diff --git a/src/app/components/task-list/task-list.component.html b/src/app/components/task-list/task-list.component.html index 1a9c4881f702b73d47f26ffa2a8d55a72cdf561d..292d3cc0db9b88ff1209b7a7a50d86d151a54699 100644 --- a/src/app/components/task-list/task-list.component.html +++ b/src/app/components/task-list/task-list.component.html @@ -3,7 +3,7 @@ <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)"> <p> - <span class="is-capitalized">{{task.info.algorithm}}</span> + <span class="is-capitalized"><i class="fa" [class.fa-capsules]="task.info.target === 'drug'" [class.fa-crosshairs]="task.info.target === 'drug-target'"></i> {{task.info.algorithm}}</span> <span class="icon is-pulled-right"><i class="fas fa-pause" aria-hidden="true"></i></span> </p> <p> @@ -12,7 +12,7 @@ </div> <div *ngIf="!task.info.done && !task.info.failed && task.info.startedAt" (click)="open(task.token)"> <p> - <span class="is-capitalized">{{task.info.algorithm}}</span> + <span class="is-capitalized"><i class="fa" [class.fa-capsules]="task.info.target === 'drug'" [class.fa-crosshairs]="task.info.target === 'drug-target'"></i> {{task.info.algorithm}}</span> <span class="icon is-pulled-right"><i class="fas fa-spinner fa-spin" aria-hidden="true"></i></span> </p> <p> @@ -23,7 +23,7 @@ </div> <div *ngIf="task.info.done" (click)="open(task.token)"> <p> - <span class="is-capitalized">{{task.info.algorithm}}</span> + <span class="is-capitalized"><i class="fa" [class.fa-capsules]="task.info.target === 'drug'" [class.fa-crosshairs]="task.info.target === 'drug-target'"></i> {{task.info.algorithm}}</span> <span class="icon is-pulled-right"><i class="fas fa-check" aria-hidden="true"></i></span> </p> <p> @@ -32,7 +32,7 @@ </div> <div *ngIf="task.info.failed && task.info.finishedAt == null"> <p> - <span class="is-capitalized">{{task.info.algorithm}}</span> + <span class="is-capitalized"><i class="fa" [class.fa-capsules]="task.info.target === 'drug'" [class.fa-crosshairs]="task.info.target === 'drug-target'"></i> {{task.info.algorithm}}</span> <span class="icon is-pulled-right"><i class="fas fa-exclamation-triangle" aria-hidden="true"></i></span> </p> <p class="has-text-danger"> diff --git a/src/app/interfaces.ts b/src/app/interfaces.ts index 6a5341edfb8199db014c047fd00534fc836d1593..5ae4c54a0516f6ebd4a0b21cd9ebb2ca60122066 100644 --- a/src/app/interfaces.ts +++ b/src/app/interfaces.ts @@ -9,6 +9,7 @@ export interface Protein { } export interface ViralProtein { + viralProteinId: string; effectName: string; virusName: string; datasetName: string; @@ -27,6 +28,7 @@ export interface ProteinViralInteraction { export interface Task { token: string; info: { + target: 'drug' | 'drug-target', algorithm: 'trustrank' | 'multisteiner' | 'keypathwayminer'; parameters?: { [key: string]: any }; diff --git a/src/app/pages/explorer-page/explorer-page.component.html b/src/app/pages/explorer-page/explorer-page.component.html index 6cc3172c3f5fcad8d1381e4bd232fa0171573034..99f8936063403ea862d3339eaea7849f719592fd 100644 --- a/src/app/pages/explorer-page/explorer-page.component.html +++ b/src/app/pages/explorer-page/explorer-page.component.html @@ -1,4 +1,4 @@ -<app-launch-analysis [(show)]="showAnalysisDialog"></app-launch-analysis> +<app-launch-analysis [(show)]="showAnalysisDialog" [target]="analysisDialogTarget"></app-launch-analysis> <div class="covex explorer"> @@ -260,16 +260,34 @@ </header> <div *ngIf="collabsAnalysis"> <div class="card-content"> - <button (click)="showAnalysisDialog = true" - class="button is-primary is-fullwidth is-rounded" - [disabled]="analysis.getCount() === 0"> - <span class="icon"> - <i class="fa fa-rocket"></i> - </span> - <span> - Launch Analysis - </span> - </button> + <div class="field"> + <div class="control"> + <button (click)="analysisDialogTarget = 'drug-target'; showAnalysisDialog = true;" + class="button is-primary is-fullwidth is-rounded" + [disabled]="analysis.getCount() === 0"> + <span class="icon"> + <i class="fa fa-crosshairs"></i> + </span> + <span> + Find Drug Targets + </span> + </button> + </div> + </div> + <div class="field"> + <div class="control"> + <button (click)="analysisDialogTarget = 'drug'; showAnalysisDialog = true;" + class="button is-primary is-fullwidth is-rounded" + [disabled]="analysis.getCount() === 0"> + <span class="icon"> + <i class="fa fa-capsules"></i> + </span> + <span> + Find Drugs + </span> + </button> + </div> + </div> </div> </div> </div> diff --git a/src/app/pages/explorer-page/explorer-page.component.ts b/src/app/pages/explorer-page/explorer-page.component.ts index 7dd8002b7f8b90f32f62f7c09c3aa3b781fdb1e8..9d2b19f4f5cc90393cc4c44c2c93acad9e8d6094 100644 --- a/src/app/pages/explorer-page/explorer-page.component.ts +++ b/src/app/pages/explorer-page/explorer-page.component.ts @@ -55,6 +55,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { public queryItems: QueryItem[] = []; public showAnalysisDialog = false; + public analysisDialogTarget: 'drug' | 'drug-target'; public selectedAnalysisToken: string | null = null;