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

Add info for baits and drugs

parent e6d08eb6
No related branches found
No related tags found
No related merge requests found
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {Protein, Task} from './interfaces'; import {QueryItem, Task} from './interfaces';
import {Subject} from 'rxjs'; import {Subject} from 'rxjs';
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
import {environment} from '../environments/environment'; import {environment} from '../environments/environment';
...@@ -10,8 +10,8 @@ import {environment} from '../environments/environment'; ...@@ -10,8 +10,8 @@ import {environment} from '../environments/environment';
export class AnalysisService { export class AnalysisService {
private selectedProteins = new Map<string, Protein>(); private selectedItems = new Map<string, QueryItem>();
private selectSubject = new Subject<{ protein: Protein, selected: boolean }>(); private selectSubject = new Subject<{ item: QueryItem, selected: boolean }>();
public tokens: string[] = []; public tokens: string[] = [];
public tasks: Task[] = []; public tasks: Task[] = [];
...@@ -44,45 +44,42 @@ export class AnalysisService { ...@@ -44,45 +44,42 @@ export class AnalysisService {
}); });
} }
addProtein(protein: Protein) { public addItem(item: QueryItem) {
if (!this.inSelection(protein)) { if (!this.inSelection(item.name)) {
this.selectedProteins.set(`${protein.proteinAc}`, protein); this.selectedItems.set(`${item.name}`, item);
this.selectSubject.next({protein, selected: true}); this.selectSubject.next({item, selected: true});
} }
} }
resetSelection() { resetSelection() {
const oldSelection = this.selectedProteins.values(); const oldSelection = this.selectedItems.values();
for (const protein of oldSelection) { for (const item of oldSelection) {
this.removeProtein(protein); this.removeItem(item.name);
} }
} }
inSelection(protein: Protein): boolean { inSelection(itemName: string): boolean {
return this.selectedProteins.has(protein.proteinAc); return this.selectedItems.has(itemName);
} }
idInSelection(id: string): boolean { removeItem(itemName: string) {
return this.selectedProteins.has(id); const item = this.selectedItems.get(itemName);
} if (this.selectedItems.delete(itemName)) {
this.selectSubject.next({item, selected: false});
removeProtein(protein: Protein) {
if (this.selectedProteins.delete(`${protein.proteinAc}`)) {
this.selectSubject.next({protein, selected: false});
} }
} }
getSelection(): Protein[] { getSelection(): QueryItem[] {
return Array.from(this.selectedProteins.values()); return Array.from(this.selectedItems.values());
} }
getCount(): number { getCount(): number {
return this.selectedProteins.size; return this.selectedItems.size;
} }
subscribe(cb: (protein: Protein, selected: boolean) => void) { subscribe(cb: (item: QueryItem, selected: boolean) => void) {
this.selectSubject.subscribe((event) => { this.selectSubject.subscribe((event) => {
cb(event.protein, event.selected); cb(event.item, event.selected);
}); });
} }
......
...@@ -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, NodeType} from '../../interfaces'; import {Protein, Task, NodeType, ViralProtein, QueryItem} from '../../interfaces';
declare var vis: any; declare var vis: any;
...@@ -24,7 +24,16 @@ declare var vis: any; ...@@ -24,7 +24,16 @@ declare var vis: any;
export class AnalysisWindowComponent implements OnInit, OnChanges { export class AnalysisWindowComponent implements OnInit, OnChanges {
@Input() token: string | null = null; @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() tokenChange = new EventEmitter<string | null>();
@Output() showDetailsChange: EventEmitter<any> = new EventEmitter();
public task: Task | null = null; public task: Task | null = null;
...@@ -67,25 +76,58 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -67,25 +76,58 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
const options = {}; const options = {};
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('selectNode', (properties) => {
const selectedNodes = this.nodeData.nodes.get(properties.nodes); const selectedNodes = this.nodeData.nodes.get(properties.nodes);
if (selectedNodes.length > 0) { if (selectedNodes.length > 0) {
if (selectedNodes[0].nodeType === 'host') { if (selectedNodes[0].nodeType === 'host') {
const protein: Protein = {name: '', proteinAc: selectedNodes[0].id}; 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';
if (properties.event.srcEvent.ctrlKey) {
if (this.analysis.inSelection(protein.proteinAc)) {
this.analysis.removeItem(protein.proteinAc);
} else {
this.analysis.addItem({name: protein.proteinAc, type: 'Host Protein', data: protein});
this.analysis.getCount();
}
}
} 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';
if (properties.event.srcEvent.ctrlKey) { if (properties.event.srcEvent.ctrlKey) {
if (this.analysis.inSelection(protein) === true) { if (this.analysis.inSelection(virus.effectName)) {
this.analysis.removeProtein(protein); this.analysis.removeItem(virus.effectName);
} else { } else {
this.analysis.addProtein(protein); this.analysis.addItem(this.selectedProteinItem);
this.analysis.getCount(); this.analysis.getCount();
} }
} }
} }
this.showDetailsChange.emit([true, [this.selectedProteinItem, this.selectedProteinName,
this.selectedProteinType, this.selectedProteinAc, this.selectedProteinDataset, this.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.analysis.subscribe((protein, selected) => { this.analysis.subscribe((item, selected) => {
const nodeId = `${protein.proteinAc}`; const nodeId = item.name;
const node = this.nodeData.nodes.get(nodeId); const node = this.nodeData.nodes.get(nodeId);
if (!node) { if (!node) {
return; return;
...@@ -164,7 +206,7 @@ export class AnalysisWindowComponent implements OnInit, OnChanges { ...@@ -164,7 +206,7 @@ export class AnalysisWindowComponent implements OnInit, OnChanges {
if (nodeType === 'host') { if (nodeType === 'host') {
shape = 'ellipse'; shape = 'ellipse';
if (this.analysis.idInSelection(nodeId)) { if (this.analysis.inSelection(nodeId)) {
color = '#c7661c'; color = '#c7661c';
} else { } else {
color = '#e2b600'; color = '#e2b600';
......
...@@ -43,7 +43,7 @@ export class LaunchAnalysisComponent implements OnInit { ...@@ -43,7 +43,7 @@ export class LaunchAnalysisComponent implements OnInit {
public async startTask() { public async startTask() {
const parameters: any = { const parameters: any = {
seeds: this.analysis.getSelection().map((protein) => protein.proteinAc), seeds: this.analysis.getSelection().map((item) => item.name),
}; };
if (this.algorithm === 'dummy') { if (this.algorithm === 'dummy') {
......
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
<p> <p>
<small>Started {{task.info.startedAt | date :'short'}}</small> <small>Started {{task.info.startedAt | date :'short'}}</small>
</p> </p>
<progress class="progress is-primary" [value]="task.info.progress * 100" max="100">Test</progress> <progress class="progress is-success" [value]="task.info.progress * 100" max="100">Test</progress>
</div> </div>
<div *ngIf="task.info.done" (click)="open(task.token)"> <div *ngIf="task.info.done" (click)="open(task.token)">
<p> <p>
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
<i class="fas fa-database" aria-hidden="true"></i> <i class="fas fa-database" aria-hidden="true"></i>
</span> Choose Dataset </span> Choose Dataset
</p> </p>
<a (click)="collabsData = !collabsData" data-action="collapse" class="card-header-icon is-hidden-fullscreen" aria-label="more options"> <a (click)="collabsData = !collabsData" data-action="collapse" class="card-header-icon is-hidden-fullscreen"
aria-label="more options">
<span class="icon"> <span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i> <i class="fas fa-angle-down" aria-hidden="true"></i>
</span> </span>
...@@ -37,7 +38,8 @@ ...@@ -37,7 +38,8 @@
<i class="fas fa-info" aria-hidden="true"></i> <i class="fas fa-info" aria-hidden="true"></i>
</span> Network Overview </span> Network Overview
</p> </p>
<a (click)="collabsOverview= !collabsOverview" data-action="collapse" class="card-header-icon is-hidden-fullscreen" aria-label="more options"> <a (click)="collabsOverview= !collabsOverview" data-action="collapse"
class="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span class="icon"> <span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i> <i class="fas fa-angle-down" aria-hidden="true"></i>
</span> </span>
...@@ -76,7 +78,8 @@ ...@@ -76,7 +78,8 @@
<i class="fas fa-search" aria-hidden="true"></i> <i class="fas fa-search" aria-hidden="true"></i>
</span> Query Protein </span> Query Protein
</p> </p>
<a (click)="collabsQuery = !collabsQuery" data-action="collapse" class="card-header-icon is-hidden-fullscreen" aria-label="more options"> <a (click)="collabsQuery = !collabsQuery" data-action="collapse"
class="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span class="icon"> <span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i> <i class="fas fa-angle-down" aria-hidden="true"></i>
</span> </span>
...@@ -101,7 +104,8 @@ ...@@ -101,7 +104,8 @@
<i class="fas fa-filter" aria-hidden="true"></i> <i class="fas fa-filter" aria-hidden="true"></i>
</span> Filter Viral Proteins </span> Filter Viral Proteins
</p> </p>
<a (click)="collabsDFilter = !collabsDFilter" data-action="collapse" class="card-header-icon is-hidden-fullscreen" aria-label="more options"> <a (click)="collabsDFilter = !collabsDFilter" data-action="collapse"
class="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span class="icon"> <span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i> <i class="fas fa-angle-down" aria-hidden="true"></i>
</span> </span>
...@@ -179,7 +183,8 @@ ...@@ -179,7 +183,8 @@
</div> </div>
<div class="analysis-view" *ngIf="selectedAnalysisToken"> <div class="analysis-view" *ngIf="selectedAnalysisToken">
<app-analysis-window [(token)]="selectedAnalysisToken"></app-analysis-window> <app-analysis-window [(token)]="selectedAnalysisToken"
(showDetailsChange)="showDetails = $event[0]; changeInfo($event[1])"></app-analysis-window>
</div> </div>
</div> </div>
...@@ -190,9 +195,10 @@ ...@@ -190,9 +195,10 @@
<p class="card-header-title"> <p class="card-header-title">
<span class="icon"> <span class="icon">
<i class="fas fa-info" aria-hidden="true"></i> <i class="fas fa-info" aria-hidden="true"></i>
</span> {{currentProteinAc}} </span> {{ selectedProteinType }}
</p> </p>
<a (click)="collabsDetails = !collabsDetails" data-action="collapse" class="card-header-icon is-hidden-fullscreen" aria-label="more options"> <a (click)="collabsDetails = !collabsDetails" data-action="collapse"
class="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span class="icon"> <span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i> <i class="fas fa-angle-down" aria-hidden="true"></i>
</span> </span>
...@@ -201,18 +207,17 @@ ...@@ -201,18 +207,17 @@
<div *ngIf="collabsDetails"> <div *ngIf="collabsDetails">
<div class="card-content"> <div class="card-content">
<div *ngIf="showDetails"> <div *ngIf="showDetails">
<p><b>Protein Name:</b> {{ currentProteinAc }}</p> <p *ngIf="selectedProteinName"><b>Name:</b> {{ selectedProteinName }}</p>
<p><b>Protein AC(s):</b> <p *ngIf="selectedProteinDataset"><b>Virus:</b> {{ selectedProteinVirus }}</p>
<a href="https://www.uniprot.org/uniprot/{{proteinAc}}" target="_blank" <p *ngIf="selectedProteinAc"><b>Protein AC:</b>
*ngFor="let proteinAc of proteinAcs"> <a href="https://www.uniprot.org/uniprot/{{ selectedProteinAc }}"
{{ proteinAc }} target="_blank"> {{ selectedProteinAc }}</a>
</a>
</p> </p>
<div class="field has-addons add-remove-toggle"> <div class="field has-addons add-remove-toggle">
<p class="control"> <p class="control">
<button class="button is-rounded" [class.is-success]="!inSelection(currentProteinAc)" <button class="button is-rounded" [class.is-success]="!analysis.inSelection(selectedProteinName)"
[disabled]="inSelection(currentProteinAc)" [disabled]="analysis.inSelection(selectedProteinName)"
(click)="addToSelection(currentProteinAc)"> (click)="analysis.addItem(selectedProteinItem)">
<span class="icon is-small"> <span class="icon is-small">
<i class="fas fa-plus"></i> <i class="fas fa-plus"></i>
</span> </span>
...@@ -220,9 +225,9 @@ ...@@ -220,9 +225,9 @@
</button> </button>
</p> </p>
<p class="control"> <p class="control">
<button class="button is-rounded" [class.is-danger]="inSelection(currentProteinAc)" <button class="button is-rounded" [class.is-danger]="analysis.inSelection(selectedProteinName)"
[disabled]="!inSelection(currentProteinAc)" [disabled]="!analysis.inSelection(selectedProteinName)"
(click)="removeFromSelection(currentProteinAc)"> (click)="analysis.removeItem(selectedProteinName)">
<span>Remove</span> <span>Remove</span>
<span class="icon is-small"> <span class="icon is-small">
<i class="fas fa-trash"></i> <i class="fas fa-trash"></i>
...@@ -246,7 +251,8 @@ ...@@ -246,7 +251,8 @@
<i class="fas fa-flask" aria-hidden="true"></i> <i class="fas fa-flask" aria-hidden="true"></i>
</span> Analysis </span> Analysis
</p> </p>
<a (click)="collabsAnalysis = !collabsAnalysis" data-action="collapse" class="card-header-icon is-hidden-fullscreen" aria-label="more options"> <a (click)="collabsAnalysis = !collabsAnalysis" data-action="collapse"
class="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span class="icon"> <span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i> <i class="fas fa-angle-down" aria-hidden="true"></i>
</span> </span>
...@@ -275,7 +281,8 @@ ...@@ -275,7 +281,8 @@
<i class="fas fa-filter" aria-hidden="true"></i> <i class="fas fa-filter" aria-hidden="true"></i>
</span> Tasks </span> Tasks
</p> </p>
<a (click)="collabsTask = !collabsTask" data-action="collapse" class="card-header-icon is-hidden-fullscreen" aria-label="more options"> <a (click)="collabsTask = !collabsTask" data-action="collapse" class="card-header-icon is-hidden-fullscreen"
aria-label="more options">
<span class="icon"> <span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i> <i class="fas fa-angle-down" aria-hidden="true"></i>
</span> </span>
...@@ -286,7 +293,8 @@ ...@@ -286,7 +293,8 @@
<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(); selectedAnalysisToken = null;" 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>
...@@ -306,7 +314,8 @@ ...@@ -306,7 +314,8 @@
<i class="fas fa-filter" aria-hidden="true"></i> <i class="fas fa-filter" aria-hidden="true"></i>
</span> Selection </span> Selection
</p> </p>
<a (click)="collabsSelection = !collabsSelection" data-action="collapse" class="card-header-icon is-hidden-fullscreen" aria-label="more options"> <a (click)="collabsSelection = !collabsSelection" data-action="collapse"
class="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span class="icon"> <span class="icon">
<i class="fas fa-angle-down" aria-hidden="true"></i> <i class="fas fa-angle-down" aria-hidden="true"></i>
</span> </span>
...@@ -323,9 +332,9 @@ ...@@ -323,9 +332,9 @@
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let p of analysis.getSelection()"> <tr *ngFor="let p of analysis.getSelection()">
<td>{{p.proteinAc}}</td> <td>{{p.name}}</td>
<td> <td>
<button (click)="analysis.removeProtein(p)" class="button is-small is-danger is-outlined"> <button (click)="analysis.removeItem(p.name)" class="button is-small is-danger is-outlined">
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
</button> </button>
</td> </td>
...@@ -345,7 +354,7 @@ ...@@ -345,7 +354,7 @@
Host Proteins Host Proteins
</span> </span>
</a> </a>
<a class="card-footer-item has-text-grey-light"> <a (click)="addAllViralProteins()" class="card-footer-item has-text-success">
<span class="icon"> <span class="icon">
<i class="fa fa-plus"></i> <i class="fa fa-plus"></i>
</span> </span>
...@@ -367,7 +376,6 @@ ...@@ -367,7 +376,6 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
...@@ -5,7 +5,6 @@ import { ...@@ -5,7 +5,6 @@ import {
OnInit, OnInit,
ViewChild ViewChild
} from '@angular/core'; } from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {ProteinViralInteraction, ViralProtein, Protein, QueryItem} from '../../interfaces'; import {ProteinViralInteraction, ViralProtein, Protein, QueryItem} from '../../interfaces';
import {ProteinNetwork, getDatasetFilename} from '../../main-network'; import {ProteinNetwork, getDatasetFilename} from '../../main-network';
import {HttpClient, HttpParams} from '@angular/common/http'; import {HttpClient, HttpParams} from '@angular/common/http';
...@@ -23,6 +22,12 @@ declare var vis: any; ...@@ -23,6 +22,12 @@ declare var vis: any;
export class ExplorerPageComponent implements OnInit, AfterViewInit { export class ExplorerPageComponent implements OnInit, AfterViewInit {
public showDetails = false; public showDetails = false;
public selectedProteinName = null;
public selectedProteinType = null;
public selectedProteinAc = null;
public selectedProteinItem = null;
public selectedProteinVirus = null;
public selectedProteinDataset = null;
public collabsAnalysis = true; public collabsAnalysis = true;
public collabsDetails = true; public collabsDetails = true;
public collabsTask = true; public collabsTask = true;
...@@ -31,10 +36,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -31,10 +36,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
public collabsQuery = true; public collabsQuery = true;
public collabsData = true; public collabsData = true;
public collabsOverview = true; public collabsOverview = true;
public currentProteinAc = '';
public geneNames: Array<string> = [];
public proteinNames: Array<string> = [];
public proteinAcs: Array<string> = [];
public viralProteinCheckboxes: Array<{ checked: boolean; data: ViralProtein }> = []; public viralProteinCheckboxes: Array<{ checked: boolean; data: ViralProtein }> = [];
...@@ -66,7 +68,12 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -66,7 +68,12 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
data: [['TUM', 'HCoV'], ['TUM', 'SARS-CoV2'], ['Krogan', 'SARS-CoV2']] data: [['TUM', 'HCoV'], ['TUM', 'SARS-CoV2'], ['Krogan', 'SARS-CoV2']]
}, },
{id: 'HCoV (TUM)', label: 'HCoV', datasets: 'TUM', data: [['TUM', 'HCoV']]}, {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 (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 (Krogan)', label: 'CoV2', datasets: 'Krogan', data: [['Krogan', 'SARS-CoV2']]},
{id: 'CoV2 (TUM)', label: 'CoV2', datasets: 'TUM', data: [['TUM', 'SARS-CoV2']]}]; {id: 'CoV2 (TUM)', label: 'CoV2', datasets: 'TUM', data: [['TUM', 'SARS-CoV2']]}];
...@@ -74,45 +81,17 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -74,45 +81,17 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
@ViewChild('network', {static: false}) networkEl: ElementRef; @ViewChild('network', {static: false}) networkEl: ElementRef;
constructor(private http: HttpClient, constructor(private http: HttpClient, public analysis: AnalysisService) {
private route: ActivatedRoute,
private router: Router,
public analysis: AnalysisService) {
this.geneNames.push('IFI16');
this.proteinNames.push('Gamma-interface-inducible protein 16');
this.proteinAcs.push('Q16666');
this.route.queryParams.subscribe(async (params) => {
this.dumpPositions = params.dumpPositions;
this.physicsEnabled = !!this.dumpPositions;
const protein = params.protein;
if (!protein) {
// In this case, the URL is just `/explorer`
// Therefore, we do not show a modal
this.showDetails = false;
return;
}
// In this case, the URL is `/explorer/<protein>` this.showDetails = false;
if (this.currentProteinAc === protein) { this.analysis.subscribe((item, selected) => {
// The protein group is the same as before, so we do not need to do anything let nodeId;
// TODO Also highlight node when reloading the page/sharing the URL if (item.type === 'Host Protein') {
return; nodeId = `p_${item.name}`;
} else if (item.type === 'Viral Protein') {
nodeId = `eff_${item.name}`;
} }
// We have a new protein id, so we need to load it and show the modal...
this.currentProteinAc = protein;
// TODO: Perform call here for 'protein'...
// this.zoomToNode(protein)
this.showDetails = true;
});
this.analysis.subscribe((protein, selected) => {
const nodeId = `p_${protein.proteinAc}`;
const node = this.nodeData.nodes.get(nodeId); const node = this.nodeData.nodes.get(nodeId);
if (!node) { if (!node) {
return; return;
...@@ -122,11 +101,14 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -122,11 +101,14 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
node.y = pos[nodeId].y; node.y = pos[nodeId].y;
if (selected) { if (selected) {
node.color = '#48C774'; node.color = '#48C774';
this.nodeData.nodes.update(node);
} else { } else {
if (item.type === 'Host Protein') {
node.color = '#e2b600'; node.color = '#e2b600';
this.nodeData.nodes.update(node); } else if (item.type === 'Viral Protein') {
node.color = '#118AB2';
} }
}
this.nodeData.nodes.update(node);
}); });
} }
...@@ -174,15 +156,45 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -174,15 +156,45 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
}); });
} }
public async openSummary(protein: Protein, zoom: boolean) { public changeInfo(showList: any[]) {
await this.router.navigate(['explorer'], {queryParams: {protein: protein.proteinAc}}); this.selectedProteinItem = showList[0];
this.selectedProteinName = showList[1];
this.selectedProteinType = showList[2];
this.selectedProteinAc = showList[3];
this.selectedProteinDataset = showList[4];
this.selectedProteinVirus = showList[5];
}
public async openSummary(item: QueryItem, zoom: boolean) {
this.selectedProteinAc = null;
this.selectedProteinItem = item;
this.selectedProteinType = item.type;
this.selectedProteinName = item.name;
if (this.selectedProteinType === 'Host Protein') {
const hostProtein = item.data as Protein;
this.selectedProteinAc = hostProtein.proteinAc;
if (zoom) {
this.zoomToNode(`p_${item.name}`);
}
} else if (item.type === 'Viral Protein') {
const viralProtein = item.data as ViralProtein;
this.selectedProteinVirus = viralProtein.virusName;
this.selectedProteinDataset = viralProtein.datasetName;
if (zoom) { if (zoom) {
this.zoomToNode(`p_${protein.proteinAc}`); this.zoomToNode(`eff_${viralProtein.effectName}_${viralProtein.datasetName}_${viralProtein.virusName}`);
}
} }
this.showDetails = true;
} }
public async closeSummary() { public async closeSummary() {
await this.router.navigate(['explorer']); this.selectedProteinItem = null;
this.selectedProteinName = null;
this.selectedProteinType = null;
this.selectedProteinAc = null;
this.selectedProteinVirus = null;
this.selectedProteinDataset = null;
this.showDetails = false;
} }
public async createNetwork(dataset: Array<[string, string]>) { public async createNetwork(dataset: Array<[string, string]>) {
...@@ -229,28 +241,45 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -229,28 +241,45 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
}, },
}, },
}; };
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('selectNode', (properties) => {
const id: Array<string> = properties.nodes; const id: Array<string> = properties.nodes;
if (id.length > 0) { if (id.length > 0) {
if (id[0].startsWith('p_')) { const nodeId = id[0].split('_');
const protein = this.proteinData.getProtein(id[0].substr(2)); let node: QueryItem;
this.openSummary(protein, false); if (nodeId[0].startsWith('p')) {
node = {
name: nodeId[1],
type: 'Host Protein',
data: this.proteinData.getProtein(nodeId[1])
};
} else if (nodeId[0].startsWith('e')) {
node = {
name: nodeId[1] + '_' + nodeId[2] + '_' + nodeId[3],
type: 'Viral Protein',
data: this.effects.find((eff) => eff.effectName === nodeId[1] && eff.datasetName === nodeId[2] && eff.virusName === nodeId[3])
};
}
if (properties.event.srcEvent.ctrlKey) { if (properties.event.srcEvent.ctrlKey) {
if (this.inSelection(protein.proteinAc) === true) { if (this.analysis.inSelection(node.name) === true) {
this.removeFromSelection(protein.proteinAc); this.analysis.inSelection(node.name);
} else { } else {
this.addToSelection(protein.proteinAc); this.analysis.addItem(node);
this.analysis.getCount(); this.analysis.getCount();
} }
this.openSummary(node, false);
} else {
this.openSummary(node, false);
} }
} else { } else {
this.closeSummary(); this.closeSummary();
} }
} });
this.network.on('deselectNode', (properties) => {
this.closeSummary();
}); });
if (this.dumpPositions) { if (this.dumpPositions) {
this.network.on('stabilizationIterationsDone', () => { this.network.on('stabilizationIterationsDone', () => {
// tslint:disable-next-line:no-console // tslint:disable-next-line:no-console
...@@ -261,14 +290,16 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -261,14 +290,16 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
this.network.stabilize(); this.network.stabilize();
} }
if (this.currentProteinAc) { if (this.selectedProteinItem) {
this.zoomToNode(`p_${this.currentProteinAc}`); this.zoomToNode(`p_${this.selectedProteinItem.name}`);
} }
this.queryItems = []; this.queryItems = [];
this.fillQueryItems(this.proteins, this.effects); this.fillQueryItems(this.proteins, this.effects);
if (this.selectedProteinItem) {
this.network.selectNodes(['p_' + this.selectedProteinItem.name]);
}
} }
fillQueryItems(hostProteins: Protein[], viralProteins: ViralProtein[]) { fillQueryItems(hostProteins: Protein[], viralProteins: ViralProtein[]) {
this.queryItems = []; this.queryItems = [];
...@@ -307,7 +338,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -307,7 +338,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
} }
}); });
viralProteins.forEach((effect) => { viralProteins.forEach((effect) => {
const nodeId = `eff_${effect.effectName}_${effect.virusName}_${effect.datasetName}`; const nodeId = `eff_${effect.effectName}_${effect.datasetName}_${effect.effectName}`;
const found = visibleIds.has(nodeId); const found = visibleIds.has(nodeId);
if ((cb.checked || showAll) && !found) { if ((cb.checked || showAll) && !found) {
const node = this.mapViralProteinToNode(effect); const node = this.mapViralProteinToNode(effect);
...@@ -349,14 +380,8 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -349,14 +380,8 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
public queryAction(item: any) { public queryAction(item: any) {
if (item) { if (item) {
if (item.type === 'Host Protein') { this.openSummary(item, true);
this.openSummary(item.data, true);
} else if (item.type === 'Viral Protein') {
this.zoomToNode(`eff_${item.data.effectName}_${item.data.virusName}_${item.data.datasetName}`
);
}
} }
} }
public updatePhysicsEnabled(bool) { public updatePhysicsEnabled(bool) {
...@@ -371,34 +396,38 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -371,34 +396,38 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
}); });
} }
private mapHostProteinToNode(protein: Protein): any { private mapHostProteinToNode(hostProtein: Protein): any {
let color = '#e2b600'; let color = '#e2b600';
if (this.analysis.inSelection(protein)) { if (this.analysis.inSelection(hostProtein.proteinAc)) {
color = '#48C774'; color = '#48C774';
} }
return { return {
id: `p_${protein.proteinAc}`, id: `p_${hostProtein.proteinAc}`,
label: `${protein.proteinAc}`, label: `${hostProtein.proteinAc}`,
size: 10, font: '5px', color, shape: 'ellipse', shadow: false, size: 10, font: '5px', color, shape: 'ellipse', shadow: false,
x: protein.x, x: hostProtein.x,
y: protein.y, y: hostProtein.y,
}; };
} }
private mapViralProteinToNode(effect: ViralProtein): any { private mapViralProteinToNode(viralProtein: ViralProtein): any {
let color = '#118AB2';
if (this.analysis.inSelection(`${viralProtein.effectName}_${viralProtein.datasetName}_${viralProtein.virusName}`)) {
color = '#48C774';
}
return { return {
id: `eff_${effect.effectName}_${effect.virusName}_${effect.datasetName}`, id: `eff_${viralProtein.effectName}_${viralProtein.datasetName}_${viralProtein.virusName}`,
label: `${effect.effectName} (${effect.virusName}, ${effect.datasetName})`, label: `${viralProtein.effectName} (${viralProtein.datasetName}, ${viralProtein.virusName})`,
size: 10, color: '#118AB2', shape: 'box', shadow: true, font: {color: '#FFFFFF'}, size: 10, color, shape: 'box', shadow: true, font: {color: '#FFFFFF'},
x: effect.x, x: viralProtein.x,
y: effect.y, y: viralProtein.y,
}; };
} }
private mapEdge(edge: ProteinViralInteraction): any { private mapEdge(edge: ProteinViralInteraction): any {
return { return {
from: `p_${edge.proteinAc}`, from: `p_${edge.proteinAc}`,
to: `eff_${edge.effectName}_${edge.virusName}_${edge.datasetName}`, to: `eff_${edge.effectName}_${edge.datasetName}_${edge.virusName}`,
color: {color: '#afafaf', highlight: '#854141'}, color: {color: '#afafaf', highlight: '#854141'},
}; };
} }
...@@ -430,43 +459,25 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { ...@@ -430,43 +459,25 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
for (const protein of this.proteinData.proteins) { for (const protein of this.proteinData.proteins) {
const nodeId = `p_${protein.proteinAc}`; const nodeId = `p_${protein.proteinAc}`;
const found = visibleIds.has(nodeId); const found = visibleIds.has(nodeId);
if (found && !this.analysis.inSelection(protein)) { if (found && !this.analysis.inSelection(protein.name)) {
this.analysis.addProtein(protein); this.analysis.addItem({name: protein.proteinAc, type: 'Host Protein', data: protein});
}
}
}
inSelection(proteinAc: string): boolean {
if (!this.proteinData || !proteinAc) {
return false;
}
const protein = this.proteinData.getProtein(proteinAc);
if (!protein) {
return false;
} }
return this.analysis.inSelection(protein);
} }
addToSelection(proteinAc: string) {
if (!this.proteinData || !proteinAc) {
return false;
}
const protein = this.proteinData.getProtein(proteinAc);
if (!protein) {
return false;
}
this.analysis.addProtein(protein);
} }
removeFromSelection(proteinAc: string) { public addAllViralProteins() {
if (!this.proteinData || !proteinAc) { const visibleIds = new Set<string>(this.nodeData.nodes.getIds());
return false; for (const effect of this.proteinData.effects) {
const nodeId = `eff_${effect.effectName + '_' + effect.datasetName + '_' + effect.virusName}`;
const found = visibleIds.has(nodeId);
if (found && !this.analysis.inSelection(effect.effectName + '_' + effect.datasetName + '_' + effect.virusName)) {
this.analysis.addItem({
name: effect.effectName + '_' + effect.datasetName + '_' + effect.virusName,
type: 'Viral Protein',
data: effect
});
} }
const protein = this.proteinData.getProtein(proteinAc);
if (!protein) {
return false;
} }
this.analysis.removeProtein(protein);
} }
public toCanvas() { public toCanvas() {
......
...@@ -49,7 +49,8 @@ img { ...@@ -49,7 +49,8 @@ img {
img.inline { img.inline {
height: 30px; height: 30px;
margin-left: 0px; align: middle;
} }
button.i { button.i {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment